Browse Source

Merge pull request #948 from 0xJacky/feat/external-notify

feat: external notification
Jacky 3 weeks ago
parent
commit
7d4671386e
42 changed files with 3292 additions and 1393 deletions
  1. 13 0
      api/external_notify/external_notify.go
  2. 17 0
      app/src/api/external_notify.ts
  3. 18 18
      app/src/components/Notification/notifications.ts
  4. 4 0
      app/src/constants/errors/notification.ts
  5. 165 102
      app/src/language/ar/app.po
  6. 165 102
      app/src/language/de_DE/app.po
  7. 164 102
      app/src/language/en/app.po
  8. 165 105
      app/src/language/es/app.po
  9. 165 106
      app/src/language/fr_FR/app.po
  10. 165 102
      app/src/language/ko_KR/app.po
  11. 158 102
      app/src/language/messages.pot
  12. 165 102
      app/src/language/ru_RU/app.po
  13. 165 102
      app/src/language/tr_TR/app.po
  14. 164 102
      app/src/language/vi_VN/app.po
  15. 161 106
      app/src/language/zh_CN/app.po
  16. 165 105
      app/src/language/zh_TW/app.po
  17. 25 0
      app/src/views/preference/ExternalNotify.vue
  18. 9 2
      app/src/views/preference/Preference.vue
  19. 46 0
      app/src/views/preference/components/ExternalNotify/ExternalNotifyEditor.vue
  20. 18 0
      app/src/views/preference/components/ExternalNotify/bark.ts
  21. 50 0
      app/src/views/preference/components/ExternalNotify/columns.ts
  22. 18 0
      app/src/views/preference/components/ExternalNotify/dingtalk.ts
  23. 12 0
      app/src/views/preference/components/ExternalNotify/index.ts
  24. 18 0
      app/src/views/preference/components/ExternalNotify/telegram.ts
  25. 9 0
      app/src/views/preference/components/ExternalNotify/types.d.ts
  26. 269 0
      cmd/external_notifier/generate.go
  27. 3 0
      gen.sh
  28. 11 5
      go.mod
  29. 23 0
      go.sum
  30. 33 0
      internal/notification/bark.go
  31. 39 0
      internal/notification/dingding.go
  32. 9 0
      internal/notification/errors.go
  33. 100 0
      internal/notification/external.go
  34. 28 0
      internal/notification/push.go
  35. 0 20
      internal/notification/subscribe.go
  36. 54 0
      internal/notification/telegram.go
  37. 1 1
      internal/translation/translation.go
  38. 8 0
      model/external_notify.go
  39. 1 0
      model/model.go
  40. 370 0
      query/external_notifies.gen.go
  41. 117 109
      query/gen.go
  42. 2 0
      router/routers.go

+ 13 - 0
api/external_notify/external_notify.go

@@ -0,0 +1,13 @@
+package external_notify
+
+import (
+	"github.com/0xJacky/Nginx-UI/model"
+	"github.com/gin-gonic/gin"
+	"github.com/uozi-tech/cosy"
+)
+
+func InitRouter(r *gin.RouterGroup) {
+	c := cosy.Api[model.ExternalNotify]("/external_notifies")
+
+	c.InitRouter(r)
+}

+ 17 - 0
app/src/api/external_notify.ts

@@ -0,0 +1,17 @@
+import type { ModelBase } from '@/api/curd'
+import Curd from '@/api/curd'
+
+export interface ExternalNotify extends ModelBase {
+  type: string
+  config: Record<string, string>
+}
+
+class ExternalNotifyCurd extends Curd<ExternalNotify> {
+  constructor() {
+    super('/external_notifies')
+  }
+}
+
+const externalNotify: ExternalNotifyCurd = new ExternalNotifyCurd()
+
+export default externalNotify

+ 18 - 18
app/src/components/Notification/notifications.ts

@@ -4,6 +4,24 @@
 
 
 const notifications: Record<string, { title: () => string, content: (args: any) => string }> = {
 const notifications: Record<string, { title: () => string, content: (args: any) => string }> = {
 
 
+  // cluster module notifications
+  'Reload Remote Nginx Error': {
+    title: () => $gettext('Reload Remote Nginx Error'),
+    content: (args: any) => $gettext('Reload Nginx on %{node} failed, response: %{resp}', args),
+  },
+  'Reload Remote Nginx Success': {
+    title: () => $gettext('Reload Remote Nginx Success'),
+    content: (args: any) => $gettext('Reload Nginx on %{node} successfully', args),
+  },
+  'Restart Remote Nginx Error': {
+    title: () => $gettext('Restart Remote Nginx Error'),
+    content: (args: any) => $gettext('Restart Nginx on %{node} failed, response: %{resp}', args),
+  },
+  'Restart Remote Nginx Success': {
+    title: () => $gettext('Restart Remote Nginx Success'),
+    content: (args: any) => $gettext('Restart Nginx on %{node} successfully', args),
+  },
+
   // cert module notifications
   // cert module notifications
   'Sync Certificate Error': {
   'Sync Certificate Error': {
     title: () => $gettext('Sync Certificate Error'),
     title: () => $gettext('Sync Certificate Error'),
@@ -137,24 +155,6 @@ const notifications: Record<string, { title: () => string, content: (args: any)
     title: () => $gettext('All Recovery Codes Have Been Used'),
     title: () => $gettext('All Recovery Codes Have Been Used'),
     content: (args: any) => $gettext('Please generate new recovery codes in the preferences immediately to prevent lockout.', args),
     content: (args: any) => $gettext('Please generate new recovery codes in the preferences immediately to prevent lockout.', args),
   },
   },
-
-  // cluster module notifications
-  'Reload Remote Nginx Error': {
-    title: () => $gettext('Reload Remote Nginx Error'),
-    content: (args: any) => $gettext('Reload Nginx on %{node} failed, response: %{resp}', args),
-  },
-  'Reload Remote Nginx Success': {
-    title: () => $gettext('Reload Remote Nginx Success'),
-    content: (args: any) => $gettext('Reload Nginx on %{node} successfully', args),
-  },
-  'Restart Remote Nginx Error': {
-    title: () => $gettext('Restart Remote Nginx Error'),
-    content: (args: any) => $gettext('Restart Nginx on %{node} failed, response: %{resp}', args),
-  },
-  'Restart Remote Nginx Success': {
-    title: () => $gettext('Restart Remote Nginx Success'),
-    content: (args: any) => $gettext('Restart Nginx on %{node} successfully', args),
-  },
 }
 }
 
 
 export default notifications
 export default notifications

+ 4 - 0
app/src/constants/errors/notification.ts

@@ -0,0 +1,4 @@
+export default {
+  404001: () => $gettext('Notifier not found'),
+  400001: () => $gettext('Invalid notifier config'),
+}

+ 165 - 102
app/src/language/ar/app.po

@@ -34,6 +34,11 @@ msgstr "سجلات الدخول"
 msgid "Access Logs"
 msgid "Access Logs"
 msgstr "سجلات الدخول"
 msgstr "سجلات الدخول"
 
 
+#: src/views/preference/components/ExternalNotify/dingtalk.ts:9
+#, fuzzy
+msgid "Access Token"
+msgstr "سجلات الدخول"
+
 #: src/routes/modules/certificates.ts:20 src/views/certificate/ACMEUser.vue:113
 #: src/routes/modules/certificates.ts:20 src/views/certificate/ACMEUser.vue:113
 #: src/views/certificate/ACMEUserSelector.vue:85
 #: src/views/certificate/ACMEUserSelector.vue:85
 msgid "ACME User"
 msgid "ACME User"
@@ -48,6 +53,7 @@ msgstr "مستخدم ACME"
 #: src/views/nginx_log/NginxLogList.vue:53
 #: src/views/nginx_log/NginxLogList.vue:53
 #: src/views/notification/notificationColumns.tsx:66
 #: src/views/notification/notificationColumns.tsx:66
 #: src/views/preference/AuthSettings.vue:30
 #: src/views/preference/AuthSettings.vue:30
+#: src/views/preference/components/ExternalNotify/columns.ts:46
 #: src/views/site/site_list/columns.tsx:117 src/views/stream/StreamList.vue:74
 #: src/views/site/site_list/columns.tsx:117 src/views/stream/StreamList.vue:74
 #: src/views/user/userColumns.tsx:60
 #: src/views/user/userColumns.tsx:60
 msgid "Action"
 msgid "Action"
@@ -112,7 +118,7 @@ msgstr "بعد ذلك، قم بتحديث هذه الصفحة وانقر فوق
 msgid "All"
 msgid "All"
 msgstr "الكل"
 msgstr "الكل"
 
 
-#: src/components/Notification/notifications.ts:137
+#: src/components/Notification/notifications.ts:155
 #: src/language/constants.ts:58
 #: src/language/constants.ts:58
 msgid "All Recovery Codes Have Been Used"
 msgid "All Recovery Codes Have Been Used"
 msgstr ""
 msgstr ""
@@ -138,7 +144,7 @@ msgstr "رمز API"
 msgid "API Type"
 msgid "API Type"
 msgstr "رمز API"
 msgstr "رمز API"
 
 
-#: src/views/preference/Preference.vue:162
+#: src/views/preference/Preference.vue:163
 msgid "App"
 msgid "App"
 msgstr ""
 msgstr ""
 
 
@@ -195,7 +201,7 @@ msgstr "هل أنت متأكد أنك تريد حذف هذا العنصر نها
 msgid "Are you sure you want to delete this item?"
 msgid "Are you sure you want to delete this item?"
 msgstr "هل أنت متأكد أنك تريد حذف هذا العنصر؟"
 msgstr "هل أنت متأكد أنك تريد حذف هذا العنصر؟"
 
 
-#: src/views/site/site_list/SiteList.vue:163
+#: src/views/site/site_list/SiteList.vue:167
 #: src/views/stream/StreamList.vue:227
 #: src/views/stream/StreamList.vue:227
 msgid "Are you sure you want to delete?"
 msgid "Are you sure you want to delete?"
 msgstr "هل أنت متأكد أنك تريد الحذف؟"
 msgstr "هل أنت متأكد أنك تريد الحذف؟"
@@ -243,7 +249,7 @@ msgstr "محاولات"
 msgid "Attempts"
 msgid "Attempts"
 msgstr "محاولات"
 msgstr "محاولات"
 
 
-#: src/views/preference/Preference.vue:186
+#: src/views/preference/Preference.vue:193
 msgid "Auth"
 msgid "Auth"
 msgstr "مصادقة"
 msgstr "مصادقة"
 
 
@@ -327,12 +333,16 @@ msgstr "عناوين IP المحظورة"
 msgid "Banned Until"
 msgid "Banned Until"
 msgstr "محظور حتى"
 msgstr "محظور حتى"
 
 
+#: src/views/preference/components/ExternalNotify/bark.ts:5
+msgid "Bark"
+msgstr ""
+
 #: src/views/site/site_add/SiteAdd.vue:95
 #: src/views/site/site_add/SiteAdd.vue:95
 msgid "Base information"
 msgid "Base information"
 msgstr "المعلومات الأساسية"
 msgstr "المعلومات الأساسية"
 
 
 #: src/views/config/ConfigEditor.vue:290
 #: src/views/config/ConfigEditor.vue:290
-#: src/views/site/site_edit/RightSettings.vue:53
+#: src/views/site/site_edit/RightSettings.vue:52
 #: src/views/stream/components/RightSettings.vue:79
 #: src/views/stream/components/RightSettings.vue:79
 msgid "Basic"
 msgid "Basic"
 msgstr "أساسي"
 msgstr "أساسي"
@@ -364,6 +374,11 @@ msgstr "فيما يلي العناصر المحددة التي تريد تعدي
 msgid "Block is nil"
 msgid "Block is nil"
 msgstr ""
 msgstr ""
 
 
+#: src/views/preference/components/ExternalNotify/telegram.ts:9
+#, fuzzy
+msgid "Bot Token"
+msgstr "رمز API"
+
 #: src/views/system/About.vue:55
 #: src/views/system/About.vue:55
 msgid "Build with"
 msgid "Build with"
 msgstr "بناء مع"
 msgstr "بناء مع"
@@ -405,7 +420,7 @@ msgstr ""
 msgid "Cannot remove initial user"
 msgid "Cannot remove initial user"
 msgstr "مستخدم النظام الأولي"
 msgstr "مستخدم النظام الأولي"
 
 
-#: src/views/preference/Preference.vue:192
+#: src/views/preference/Preference.vue:199
 msgid "Cert"
 msgid "Cert"
 msgstr "شهادة"
 msgstr "شهادة"
 
 
@@ -485,6 +500,10 @@ msgstr "المسار المتغير"
 msgid "Channel"
 msgid "Channel"
 msgstr "قناة"
 msgstr "قناة"
 
 
+#: src/views/preference/components/ExternalNotify/telegram.ts:13
+msgid "Chat ID"
+msgstr ""
+
 #: src/views/system/Upgrade.vue:185
 #: src/views/system/Upgrade.vue:185
 msgid "Check again"
 msgid "Check again"
 msgstr "تحقق مرة أخرى"
 msgstr "تحقق مرة أخرى"
@@ -681,6 +700,7 @@ msgstr ""
 
 
 #: src/views/environments/group/columns.ts:31
 #: src/views/environments/group/columns.ts:31
 #: src/views/notification/notificationColumns.tsx:59
 #: src/views/notification/notificationColumns.tsx:59
+#: src/views/preference/components/ExternalNotify/columns.ts:41
 #: src/views/preference/components/Passkey.vue:95
 #: src/views/preference/components/Passkey.vue:95
 #: src/views/user/userColumns.tsx:48
 #: src/views/user/userColumns.tsx:48
 msgid "Created at"
 msgid "Created at"
@@ -752,7 +772,7 @@ msgstr "وصف"
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/views/site/ngx_conf/NgxServer.vue:110
 #: src/views/site/ngx_conf/NgxServer.vue:110
 #: src/views/site/ngx_conf/NgxUpstream.vue:128
 #: src/views/site/ngx_conf/NgxUpstream.vue:128
-#: src/views/site/site_list/SiteList.vue:172
+#: src/views/site/site_list/SiteList.vue:176
 #: src/views/stream/StreamList.vue:236
 #: src/views/stream/StreamList.vue:236
 msgid "Delete"
 msgid "Delete"
 msgstr "حذف"
 msgstr "حذف"
@@ -762,44 +782,44 @@ msgstr "حذف"
 msgid "Delete Permanently"
 msgid "Delete Permanently"
 msgstr "حذف نهائي"
 msgstr "حذف نهائي"
 
 
-#: src/components/Notification/notifications.ts:37 src/language/constants.ts:50
+#: src/components/Notification/notifications.ts:55 src/language/constants.ts:50
 msgid "Delete Remote Site Error"
 msgid "Delete Remote Site Error"
 msgstr "خطأ حذف الموقع البعيد"
 msgstr "خطأ حذف الموقع البعيد"
 
 
-#: src/components/Notification/notifications.ts:41 src/language/constants.ts:49
+#: src/components/Notification/notifications.ts:59 src/language/constants.ts:49
 msgid "Delete Remote Site Success"
 msgid "Delete Remote Site Success"
 msgstr "نجح حذف الموقع البعيد"
 msgstr "نجح حذف الموقع البعيد"
 
 
-#: src/components/Notification/notifications.ts:95
+#: src/components/Notification/notifications.ts:113
 #, fuzzy
 #, fuzzy
 msgid "Delete Remote Stream Error"
 msgid "Delete Remote Stream Error"
 msgstr "خطأ حذف الموقع البعيد"
 msgstr "خطأ حذف الموقع البعيد"
 
 
-#: src/components/Notification/notifications.ts:99
+#: src/components/Notification/notifications.ts:117
 #, fuzzy
 #, fuzzy
 msgid "Delete Remote Stream Success"
 msgid "Delete Remote Stream Success"
 msgstr "نجح حذف الموقع البعيد"
 msgstr "نجح حذف الموقع البعيد"
 
 
-#: src/components/Notification/notifications.ts:38
+#: src/components/Notification/notifications.ts:56
 #, fuzzy
 #, fuzzy
 msgid "Delete site %{name} from %{node} failed"
 msgid "Delete site %{name} from %{node} failed"
 msgstr "فشل نشر {conf_name}% إلى {node_name}%"
 msgstr "فشل نشر {conf_name}% إلى {node_name}%"
 
 
-#: src/components/Notification/notifications.ts:42
+#: src/components/Notification/notifications.ts:60
 #, fuzzy
 #, fuzzy
 msgid "Delete site %{name} from %{node} successfully"
 msgid "Delete site %{name} from %{node} successfully"
 msgstr "تمت إزالة الموقع %{site} من %{node} بنجاح"
 msgstr "تمت إزالة الموقع %{site} من %{node} بنجاح"
 
 
-#: src/views/site/site_list/SiteList.vue:94
+#: src/views/site/site_list/SiteList.vue:98
 msgid "Delete site: %{site_name}"
 msgid "Delete site: %{site_name}"
 msgstr "حذف الموقع: ‎%{site_name}"
 msgstr "حذف الموقع: ‎%{site_name}"
 
 
-#: src/components/Notification/notifications.ts:96
+#: src/components/Notification/notifications.ts:114
 #, fuzzy
 #, fuzzy
 msgid "Delete stream %{name} from %{node} failed"
 msgid "Delete stream %{name} from %{node} failed"
 msgstr "فشل نشر {conf_name}% إلى {node_name}%"
 msgstr "فشل نشر {conf_name}% إلى {node_name}%"
 
 
-#: src/components/Notification/notifications.ts:100
+#: src/components/Notification/notifications.ts:118
 #, fuzzy
 #, fuzzy
 msgid "Delete stream %{name} from %{node} successfully"
 msgid "Delete stream %{name} from %{node} successfully"
 msgstr "تمت إزالة الموقع %{site} من %{node} بنجاح"
 msgstr "تمت إزالة الموقع %{site} من %{node} بنجاح"
@@ -837,6 +857,14 @@ msgstr "تفاصيل"
 msgid "Development Mode"
 msgid "Development Mode"
 msgstr "وضع التطوير"
 msgstr "وضع التطوير"
 
 
+#: src/views/preference/components/ExternalNotify/bark.ts:9
+msgid "Device Key"
+msgstr ""
+
+#: src/views/preference/components/ExternalNotify/dingtalk.ts:5
+msgid "DingTalk"
+msgstr ""
+
 #: src/views/site/ngx_conf/directive/DirectiveAdd.vue:89
 #: src/views/site/ngx_conf/directive/DirectiveAdd.vue:89
 msgid "Directive"
 msgid "Directive"
 msgstr "توجيه"
 msgstr "توجيه"
@@ -870,60 +898,60 @@ msgstr "تعطيل"
 msgid "Disable auto-renewal failed for %{name}"
 msgid "Disable auto-renewal failed for %{name}"
 msgstr "فشل تعطيل التجديد التلقائي لـ {name}%"
 msgstr "فشل تعطيل التجديد التلقائي لـ {name}%"
 
 
-#: src/components/Notification/notifications.ts:45 src/language/constants.ts:52
+#: src/components/Notification/notifications.ts:63 src/language/constants.ts:52
 msgid "Disable Remote Site Error"
 msgid "Disable Remote Site Error"
 msgstr "خطأ في تعطيل الموقع البعيد"
 msgstr "خطأ في تعطيل الموقع البعيد"
 
 
-#: src/components/Notification/notifications.ts:69
+#: src/components/Notification/notifications.ts:87
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Site Maintenance Error"
 msgid "Disable Remote Site Maintenance Error"
 msgstr "خطأ في تعطيل الموقع البعيد"
 msgstr "خطأ في تعطيل الموقع البعيد"
 
 
-#: src/components/Notification/notifications.ts:73
+#: src/components/Notification/notifications.ts:91
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Site Maintenance Success"
 msgid "Disable Remote Site Maintenance Success"
 msgstr "تعطيل الموقع البعيد بنجاح"
 msgstr "تعطيل الموقع البعيد بنجاح"
 
 
-#: src/components/Notification/notifications.ts:49 src/language/constants.ts:51
+#: src/components/Notification/notifications.ts:67 src/language/constants.ts:51
 msgid "Disable Remote Site Success"
 msgid "Disable Remote Site Success"
 msgstr "تعطيل الموقع البعيد بنجاح"
 msgstr "تعطيل الموقع البعيد بنجاح"
 
 
-#: src/components/Notification/notifications.ts:103
+#: src/components/Notification/notifications.ts:121
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Stream Error"
 msgid "Disable Remote Stream Error"
 msgstr "خطأ في تعطيل الموقع البعيد"
 msgstr "خطأ في تعطيل الموقع البعيد"
 
 
-#: src/components/Notification/notifications.ts:107
+#: src/components/Notification/notifications.ts:125
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Stream Success"
 msgid "Disable Remote Stream Success"
 msgstr "تعطيل الموقع البعيد بنجاح"
 msgstr "تعطيل الموقع البعيد بنجاح"
 
 
-#: src/components/Notification/notifications.ts:46
+#: src/components/Notification/notifications.ts:64
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} from %{node} failed"
 msgid "Disable site %{name} from %{node} failed"
 msgstr "تم تعطيل الموقع %{site} على %{node} بنجاح"
 msgstr "تم تعطيل الموقع %{site} على %{node} بنجاح"
 
 
-#: src/components/Notification/notifications.ts:50
+#: src/components/Notification/notifications.ts:68
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} from %{node} successfully"
 msgid "Disable site %{name} from %{node} successfully"
 msgstr "تم تعطيل الموقع %{site} على %{node} بنجاح"
 msgstr "تم تعطيل الموقع %{site} على %{node} بنجاح"
 
 
-#: src/components/Notification/notifications.ts:70
+#: src/components/Notification/notifications.ts:88
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} maintenance on %{node} failed"
 msgid "Disable site %{name} maintenance on %{node} failed"
 msgstr "تم تعطيل الموقع %{site} على %{node} بنجاح"
 msgstr "تم تعطيل الموقع %{site} على %{node} بنجاح"
 
 
-#: src/components/Notification/notifications.ts:74
+#: src/components/Notification/notifications.ts:92
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} maintenance on %{node} successfully"
 msgid "Disable site %{name} maintenance on %{node} successfully"
 msgstr "تم تعطيل الموقع %{site} على %{node} بنجاح"
 msgstr "تم تعطيل الموقع %{site} على %{node} بنجاح"
 
 
-#: src/components/Notification/notifications.ts:104
+#: src/components/Notification/notifications.ts:122
 #, fuzzy
 #, fuzzy
 msgid "Disable stream %{name} from %{node} failed"
 msgid "Disable stream %{name} from %{node} failed"
 msgstr "فشل تفعيل %{conf_name} في %{node_name}"
 msgstr "فشل تفعيل %{conf_name} في %{node_name}"
 
 
-#: src/components/Notification/notifications.ts:108
+#: src/components/Notification/notifications.ts:126
 #, fuzzy
 #, fuzzy
 msgid "Disable stream %{name} from %{node} successfully"
 msgid "Disable stream %{name} from %{node} successfully"
 msgstr "تم تعطيل الموقع %{site} على %{node} بنجاح"
 msgstr "تم تعطيل الموقع %{site} على %{node} بنجاح"
@@ -1039,7 +1067,7 @@ msgstr ""
 "الويب غير HTTPS، إلا عند التشغيل على localhost."
 "الويب غير HTTPS، إلا عند التشغيل على localhost."
 
 
 #: src/views/site/site_list/SiteDuplicate.vue:72
 #: src/views/site/site_list/SiteDuplicate.vue:72
-#: src/views/site/site_list/SiteList.vue:158
+#: src/views/site/site_list/SiteList.vue:162
 #: src/views/stream/components/StreamDuplicate.vue:64
 #: src/views/stream/components/StreamDuplicate.vue:64
 #: src/views/stream/StreamList.vue:222
 #: src/views/stream/StreamList.vue:222
 msgid "Duplicate"
 msgid "Duplicate"
@@ -1107,60 +1135,60 @@ msgstr "فشل التفعيل"
 msgid "Enable HTTPS"
 msgid "Enable HTTPS"
 msgstr "تفعيل TOTP"
 msgstr "تفعيل TOTP"
 
 
-#: src/components/Notification/notifications.ts:53 src/language/constants.ts:54
+#: src/components/Notification/notifications.ts:71 src/language/constants.ts:54
 msgid "Enable Remote Site Error"
 msgid "Enable Remote Site Error"
 msgstr "خطأ في تفعيل الموقع البعيد"
 msgstr "خطأ في تفعيل الموقع البعيد"
 
 
-#: src/components/Notification/notifications.ts:61
+#: src/components/Notification/notifications.ts:79
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Site Maintenance Error"
 msgid "Enable Remote Site Maintenance Error"
 msgstr "خطأ في تفعيل الموقع البعيد"
 msgstr "خطأ في تفعيل الموقع البعيد"
 
 
-#: src/components/Notification/notifications.ts:65
+#: src/components/Notification/notifications.ts:83
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Site Maintenance Success"
 msgid "Enable Remote Site Maintenance Success"
 msgstr "نجح تفعيل الموقع البعيد"
 msgstr "نجح تفعيل الموقع البعيد"
 
 
-#: src/components/Notification/notifications.ts:57 src/language/constants.ts:53
+#: src/components/Notification/notifications.ts:75 src/language/constants.ts:53
 msgid "Enable Remote Site Success"
 msgid "Enable Remote Site Success"
 msgstr "نجح تفعيل الموقع البعيد"
 msgstr "نجح تفعيل الموقع البعيد"
 
 
-#: src/components/Notification/notifications.ts:111
+#: src/components/Notification/notifications.ts:129
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Stream Error"
 msgid "Enable Remote Stream Error"
 msgstr "خطأ في تفعيل الموقع البعيد"
 msgstr "خطأ في تفعيل الموقع البعيد"
 
 
-#: src/components/Notification/notifications.ts:115
+#: src/components/Notification/notifications.ts:133
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Stream Success"
 msgid "Enable Remote Stream Success"
 msgstr "نجح تفعيل الموقع البعيد"
 msgstr "نجح تفعيل الموقع البعيد"
 
 
-#: src/components/Notification/notifications.ts:62
+#: src/components/Notification/notifications.ts:80
 #, fuzzy
 #, fuzzy
 msgid "Enable site %{name} maintenance on %{node} failed"
 msgid "Enable site %{name} maintenance on %{node} failed"
 msgstr "فشل تفعيل %{conf_name} في %{node_name}"
 msgstr "فشل تفعيل %{conf_name} في %{node_name}"
 
 
-#: src/components/Notification/notifications.ts:66
+#: src/components/Notification/notifications.ts:84
 #, fuzzy
 #, fuzzy
 msgid "Enable site %{name} maintenance on %{node} successfully"
 msgid "Enable site %{name} maintenance on %{node} successfully"
 msgstr "تم تفعيل الموقع %{site} على %{node} بنجاح"
 msgstr "تم تفعيل الموقع %{site} على %{node} بنجاح"
 
 
-#: src/components/Notification/notifications.ts:54
+#: src/components/Notification/notifications.ts:72
 #, fuzzy
 #, fuzzy
 msgid "Enable site %{name} on %{node} failed"
 msgid "Enable site %{name} on %{node} failed"
 msgstr "فشل تفعيل %{conf_name} في %{node_name}"
 msgstr "فشل تفعيل %{conf_name} في %{node_name}"
 
 
-#: src/components/Notification/notifications.ts:58
+#: src/components/Notification/notifications.ts:76
 #, fuzzy
 #, fuzzy
 msgid "Enable site %{name} on %{node} successfully"
 msgid "Enable site %{name} on %{node} successfully"
 msgstr "تم تفعيل الموقع %{site} على %{node} بنجاح"
 msgstr "تم تفعيل الموقع %{site} على %{node} بنجاح"
 
 
-#: src/components/Notification/notifications.ts:112
+#: src/components/Notification/notifications.ts:130
 #, fuzzy
 #, fuzzy
 msgid "Enable stream %{name} on %{node} failed"
 msgid "Enable stream %{name} on %{node} failed"
 msgstr "فشل تفعيل %{conf_name} في %{node_name}"
 msgstr "فشل تفعيل %{conf_name} في %{node_name}"
 
 
-#: src/components/Notification/notifications.ts:116
+#: src/components/Notification/notifications.ts:134
 #, fuzzy
 #, fuzzy
 msgid "Enable stream %{name} on %{node} successfully"
 msgid "Enable stream %{name} on %{node} successfully"
 msgstr "تم تفعيل الموقع %{site} على %{node} بنجاح"
 msgstr "تم تفعيل الموقع %{site} على %{node} بنجاح"
@@ -1248,6 +1276,11 @@ msgstr "تنتهي في: %{date}"
 msgid "Export"
 msgid "Export"
 msgstr "تصدير"
 msgstr "تصدير"
 
 
+#: src/views/preference/ExternalNotify.vue:10
+#: src/views/preference/Preference.vue:169
+msgid "External Notify"
+msgstr ""
+
 #: src/views/site/cert/components/ObtainCertLive.vue:94
 #: src/views/site/cert/components/ObtainCertLive.vue:94
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
 msgstr "فشل في الحصول على الشهادة"
 msgstr "فشل في الحصول على الشهادة"
@@ -1652,7 +1685,7 @@ msgstr "الصفحة الرئيسية"
 msgid "Host"
 msgid "Host"
 msgstr "مضيف HTTP"
 msgstr "مضيف HTTP"
 
 
-#: src/views/preference/Preference.vue:174
+#: src/views/preference/Preference.vue:181
 #, fuzzy
 #, fuzzy
 msgid "HTTP"
 msgid "HTTP"
 msgstr "HTTP01"
 msgstr "HTTP01"
@@ -1713,12 +1746,12 @@ msgid "Import Certificate"
 msgstr "استيراد شهادة"
 msgstr "استيراد شهادة"
 
 
 #: src/views/nginx_log/NginxLogList.vue:137
 #: src/views/nginx_log/NginxLogList.vue:137
-#: src/views/site/site_list/SiteList.vue:128
+#: src/views/site/site_list/SiteList.vue:132
 msgid "Indexed"
 msgid "Indexed"
 msgstr ""
 msgstr ""
 
 
 #: src/views/nginx_log/NginxLogList.vue:134
 #: src/views/nginx_log/NginxLogList.vue:134
-#: src/views/site/site_list/SiteList.vue:125
+#: src/views/site/site_list/SiteList.vue:129
 msgid "Indexing..."
 msgid "Indexing..."
 msgstr ""
 msgstr ""
 
 
@@ -1802,6 +1835,11 @@ msgstr "اسم ملف غير صالح"
 msgid "Invalid folder name"
 msgid "Invalid folder name"
 msgstr "اسم المجلد غير صالح"
 msgstr "اسم المجلد غير صالح"
 
 
+#: src/constants/errors/notification.ts:3
+#, fuzzy
+msgid "Invalid notifier config"
+msgstr "رمز 2FA أو الاسترداد غير صالح"
+
 #: src/constants/errors/user.ts:4
 #: src/constants/errors/user.ts:4
 #, fuzzy
 #, fuzzy
 msgid "Invalid otp code"
 msgid "Invalid otp code"
@@ -1865,6 +1903,10 @@ msgstr ""
 msgid "Key Type"
 msgid "Key Type"
 msgstr "نوع المفتاح"
 msgstr "نوع المفتاح"
 
 
+#: src/views/preference/components/ExternalNotify/columns.ts:29
+msgid "Language"
+msgstr ""
+
 #: src/views/system/Upgrade.vue:179
 #: src/views/system/Upgrade.vue:179
 msgid "Last checked at"
 msgid "Last checked at"
 msgstr "آخر فحص في"
 msgstr "آخر فحص في"
@@ -1961,7 +2003,7 @@ msgstr "تم تسجيل الدخول بنجاح"
 msgid "Logout successful"
 msgid "Logout successful"
 msgstr "تم تسجيل الخروج بنجاح"
 msgstr "تم تسجيل الخروج بنجاح"
 
 
-#: src/views/preference/Preference.vue:210
+#: src/views/preference/Preference.vue:217
 msgid "Logrotate"
 msgid "Logrotate"
 msgstr "تدوير السجلات"
 msgstr "تدوير السجلات"
 
 
@@ -2009,7 +2051,7 @@ msgstr ""
 msgid "Manage Configs"
 msgid "Manage Configs"
 msgstr "إدارة التكوينات"
 msgstr "إدارة التكوينات"
 
 
-#: src/routes/modules/sites.ts:10 src/views/site/site_list/SiteList.vue:121
+#: src/routes/modules/sites.ts:10 src/views/site/site_list/SiteList.vue:125
 msgid "Manage Sites"
 msgid "Manage Sites"
 msgstr "إدارة المواقع"
 msgstr "إدارة المواقع"
 
 
@@ -2085,7 +2127,7 @@ msgstr "توجيه متعدد الأسطر"
 #: src/views/nginx_log/NginxLogList.vue:37
 #: src/views/nginx_log/NginxLogList.vue:37
 #: src/views/preference/components/AddPasskey.vue:75
 #: src/views/preference/components/AddPasskey.vue:75
 #: src/views/site/ngx_conf/NgxUpstream.vue:177
 #: src/views/site/ngx_conf/NgxUpstream.vue:177
-#: src/views/site/site_edit/RightSettings.vue:64
+#: src/views/site/site_edit/RightSettings.vue:63
 #: src/views/site/site_list/columns.tsx:17
 #: src/views/site/site_list/columns.tsx:17
 #: src/views/site/site_list/SiteDuplicate.vue:79
 #: src/views/site/site_list/SiteDuplicate.vue:79
 #: src/views/stream/components/RightSettings.vue:87
 #: src/views/stream/components/RightSettings.vue:87
@@ -2133,7 +2175,7 @@ msgstr "تم إصدار نسخة جديدة"
 msgid "Next"
 msgid "Next"
 msgstr "التالي"
 msgstr "التالي"
 
 
-#: src/views/preference/Preference.vue:198
+#: src/views/preference/Preference.vue:205
 msgid "Nginx"
 msgid "Nginx"
 msgstr "Nginx"
 msgstr "Nginx"
 
 
@@ -2273,7 +2315,7 @@ msgstr "خطأ في تحليل تكوين Nginx"
 #: src/views/preference/CertSettings.vue:73
 #: src/views/preference/CertSettings.vue:73
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:97
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:97
 #: src/views/site/ngx_conf/LocationEditor.vue:88
 #: src/views/site/ngx_conf/LocationEditor.vue:88
-#: src/views/site/site_list/SiteList.vue:161
+#: src/views/site/site_list/SiteList.vue:165
 #: src/views/stream/StreamList.vue:225
 #: src/views/stream/StreamList.vue:225
 msgid "No"
 msgid "No"
 msgstr "لا"
 msgstr "لا"
@@ -2288,12 +2330,12 @@ msgstr "إجراء"
 msgid "No records selected"
 msgid "No records selected"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/Preference.vue:168
+#: src/views/preference/Preference.vue:175
 #, fuzzy
 #, fuzzy
 msgid "Node"
 msgid "Node"
 msgstr "اسم العقدة"
 msgstr "اسم العقدة"
 
 
-#: src/views/site/site_edit/RightSettings.vue:67
+#: src/views/site/site_edit/RightSettings.vue:66
 #: src/views/site/site_list/columns.tsx:63
 #: src/views/site/site_list/columns.tsx:63
 #: src/views/stream/components/RightSettings.vue:90
 #: src/views/stream/components/RightSettings.vue:90
 #: src/views/stream/StreamList.vue:30
 #: src/views/stream/StreamList.vue:30
@@ -2337,7 +2379,7 @@ msgstr "غير صالح قبل: %{date}"
 msgid "Note"
 msgid "Note"
 msgstr "ملاحظة"
 msgstr "ملاحظة"
 
 
-#: src/views/site/site_edit/RightSettings.vue:96
+#: src/views/site/site_edit/RightSettings.vue:95
 #: src/views/stream/components/RightSettings.vue:118
 #: src/views/stream/components/RightSettings.vue:118
 msgid ""
 msgid ""
 "Note, if the configuration file include other configurations or "
 "Note, if the configuration file include other configurations or "
@@ -2355,6 +2397,11 @@ msgstr "إشعار"
 msgid "Notifications"
 msgid "Notifications"
 msgstr "الإشعارات"
 msgstr "الإشعارات"
 
 
+#: src/constants/errors/notification.ts:2
+#, fuzzy
+msgid "Notifier not found"
+msgstr "لم يتم العثور على الملف"
+
 #: src/views/site/cert/components/ObtainCert.vue:182
 #: src/views/site/cert/components/ObtainCert.vue:182
 msgid "Obtain certificate"
 msgid "Obtain certificate"
 msgstr "الحصول على شهادة"
 msgstr "الحصول على شهادة"
@@ -2399,7 +2446,7 @@ msgstr "حسنًا"
 #: src/views/site/ngx_conf/NgxServer.vue:79
 #: src/views/site/ngx_conf/NgxServer.vue:79
 #: src/views/site/ngx_conf/NgxUpstream.vue:33
 #: src/views/site/ngx_conf/NgxUpstream.vue:33
 #: src/views/site/site_edit/components/SiteStatusSegmented.vue:121
 #: src/views/site/site_edit/components/SiteStatusSegmented.vue:121
-#: src/views/site/site_list/SiteList.vue:162
+#: src/views/site/site_list/SiteList.vue:166
 #: src/views/stream/components/RightSettings.vue:54
 #: src/views/stream/components/RightSettings.vue:54
 #: src/views/stream/StreamList.vue:226
 #: src/views/stream/StreamList.vue:226
 #: src/views/system/Backup/BackupCreator.vue:149
 #: src/views/system/Backup/BackupCreator.vue:149
@@ -2422,7 +2469,7 @@ msgstr "متصل"
 msgid "Only zip files are allowed"
 msgid "Only zip files are allowed"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/Preference.vue:204
+#: src/views/preference/Preference.vue:211
 msgid "OpenAI"
 msgid "OpenAI"
 msgstr "أوبن أي آي"
 msgstr "أوبن أي آي"
 
 
@@ -2569,7 +2616,7 @@ msgstr ""
 "يرجى أولاً إضافة بيانات الاعتماد في الشهادات > بيانات اعتماد DNS، ثم اختيار "
 "يرجى أولاً إضافة بيانات الاعتماد في الشهادات > بيانات اعتماد DNS، ثم اختيار "
 "أحد بيانات الاعتماد أدناه لطلب API لمزود DNS."
 "أحد بيانات الاعتماد أدناه لطلب API لمزود DNS."
 
 
-#: src/components/Notification/notifications.ts:138
+#: src/components/Notification/notifications.ts:156
 #: src/language/constants.ts:59
 #: src/language/constants.ts:59
 msgid ""
 msgid ""
 "Please generate new recovery codes in the preferences immediately to prevent "
 "Please generate new recovery codes in the preferences immediately to prevent "
@@ -2660,7 +2707,7 @@ msgstr "إجراء"
 msgid "Pre-release"
 msgid "Pre-release"
 msgstr "ما قبل الإصدار"
 msgstr "ما قبل الإصدار"
 
 
-#: src/routes/modules/preference.ts:10 src/views/preference/Preference.vue:151
+#: src/routes/modules/preference.ts:10 src/views/preference/Preference.vue:152
 msgid "Preference"
 msgid "Preference"
 msgstr "تفضيل"
 msgstr "تفضيل"
 
 
@@ -2794,22 +2841,22 @@ msgstr "إعادة تحميل"
 msgid "Reload Nginx"
 msgid "Reload Nginx"
 msgstr "إعادة تحميل nginx"
 msgstr "إعادة تحميل nginx"
 
 
-#: src/components/Notification/notifications.ts:144
+#: src/components/Notification/notifications.ts:10
 #, fuzzy
 #, fuzzy
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgstr "خطأ في إزالة الموقع %{site} من %{node}، الاستجابة: %{resp}"
 msgstr "خطأ في إزالة الموقع %{site} من %{node}، الاستجابة: %{resp}"
 
 
-#: src/components/Notification/notifications.ts:148
+#: src/components/Notification/notifications.ts:14
 #, fuzzy
 #, fuzzy
 msgid "Reload Nginx on %{node} successfully"
 msgid "Reload Nginx on %{node} successfully"
 msgstr "تمت ترقية Nginx UI على %{node} بنجاح 🎉"
 msgstr "تمت ترقية Nginx UI على %{node} بنجاح 🎉"
 
 
-#: src/components/Notification/notifications.ts:143
+#: src/components/Notification/notifications.ts:9
 #, fuzzy
 #, fuzzy
 msgid "Reload Remote Nginx Error"
 msgid "Reload Remote Nginx Error"
 msgstr "خطأ في إعادة تسمية الموقع البعيد"
 msgstr "خطأ في إعادة تسمية الموقع البعيد"
 
 
-#: src/components/Notification/notifications.ts:147
+#: src/components/Notification/notifications.ts:13
 #, fuzzy
 #, fuzzy
 msgid "Reload Remote Nginx Success"
 msgid "Reload Remote Nginx Success"
 msgstr "تم إعادة تسمية الموقع البعيد بنجاح"
 msgstr "تم إعادة تسمية الموقع البعيد بنجاح"
@@ -2848,57 +2895,57 @@ msgstr "تمت الإزالة بنجاح"
 msgid "Rename"
 msgid "Rename"
 msgstr "إعادة تسمية"
 msgstr "إعادة تسمية"
 
 
-#: src/components/Notification/notifications.ts:28
+#: src/components/Notification/notifications.ts:46
 #, fuzzy
 #, fuzzy
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} failed"
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} failed"
 msgstr "تم إعادة تسمية %{orig_path} إلى %{new_path} على %{env_name} بنجاح"
 msgstr "تم إعادة تسمية %{orig_path} إلى %{new_path} على %{env_name} بنجاح"
 
 
-#: src/components/Notification/notifications.ts:32
+#: src/components/Notification/notifications.ts:50
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} successfully"
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} successfully"
 msgstr "تم إعادة تسمية %{orig_path} إلى %{new_path} على %{env_name} بنجاح"
 msgstr "تم إعادة تسمية %{orig_path} إلى %{new_path} على %{env_name} بنجاح"
 
 
-#: src/components/Notification/notifications.ts:27 src/language/constants.ts:42
+#: src/components/Notification/notifications.ts:45 src/language/constants.ts:42
 msgid "Rename Remote Config Error"
 msgid "Rename Remote Config Error"
 msgstr "خطأ في إعادة تسمية التكوين البعيد"
 msgstr "خطأ في إعادة تسمية التكوين البعيد"
 
 
-#: src/components/Notification/notifications.ts:31 src/language/constants.ts:41
+#: src/components/Notification/notifications.ts:49 src/language/constants.ts:41
 msgid "Rename Remote Config Success"
 msgid "Rename Remote Config Success"
 msgstr "إعادة تسمية تكوين البعيد بنجاح"
 msgstr "إعادة تسمية تكوين البعيد بنجاح"
 
 
-#: src/components/Notification/notifications.ts:77 src/language/constants.ts:56
+#: src/components/Notification/notifications.ts:95 src/language/constants.ts:56
 msgid "Rename Remote Site Error"
 msgid "Rename Remote Site Error"
 msgstr "خطأ في إعادة تسمية الموقع البعيد"
 msgstr "خطأ في إعادة تسمية الموقع البعيد"
 
 
-#: src/components/Notification/notifications.ts:81 src/language/constants.ts:55
+#: src/components/Notification/notifications.ts:99 src/language/constants.ts:55
 msgid "Rename Remote Site Success"
 msgid "Rename Remote Site Success"
 msgstr "تم إعادة تسمية الموقع البعيد بنجاح"
 msgstr "تم إعادة تسمية الموقع البعيد بنجاح"
 
 
-#: src/components/Notification/notifications.ts:119
+#: src/components/Notification/notifications.ts:137
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Stream Error"
 msgid "Rename Remote Stream Error"
 msgstr "خطأ في إعادة تسمية الموقع البعيد"
 msgstr "خطأ في إعادة تسمية الموقع البعيد"
 
 
-#: src/components/Notification/notifications.ts:123
+#: src/components/Notification/notifications.ts:141
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Stream Success"
 msgid "Rename Remote Stream Success"
 msgstr "تم إعادة تسمية الموقع البعيد بنجاح"
 msgstr "تم إعادة تسمية الموقع البعيد بنجاح"
 
 
-#: src/components/Notification/notifications.ts:78
+#: src/components/Notification/notifications.ts:96
 #, fuzzy
 #, fuzzy
 msgid "Rename site %{name} to %{new_name} on %{node} failed"
 msgid "Rename site %{name} to %{new_name} on %{node} failed"
 msgstr "إعادة تسمية الموقع %{site} إلى %{new_site} على %{node} بنجاح"
 msgstr "إعادة تسمية الموقع %{site} إلى %{new_site} على %{node} بنجاح"
 
 
-#: src/components/Notification/notifications.ts:82
+#: src/components/Notification/notifications.ts:100
 #, fuzzy
 #, fuzzy
 msgid "Rename site %{name} to %{new_name} on %{node} successfully"
 msgid "Rename site %{name} to %{new_name} on %{node} successfully"
 msgstr "إعادة تسمية الموقع %{site} إلى %{new_site} على %{node} بنجاح"
 msgstr "إعادة تسمية الموقع %{site} إلى %{new_site} على %{node} بنجاح"
 
 
-#: src/components/Notification/notifications.ts:120
+#: src/components/Notification/notifications.ts:138
 #, fuzzy
 #, fuzzy
 msgid "Rename stream %{name} to %{new_name} on %{node} failed"
 msgid "Rename stream %{name} to %{new_name} on %{node} failed"
 msgstr "إعادة تسمية الموقع %{site} إلى %{new_site} على %{node} بنجاح"
 msgstr "إعادة تسمية الموقع %{site} إلى %{new_site} على %{node} بنجاح"
 
 
-#: src/components/Notification/notifications.ts:124
+#: src/components/Notification/notifications.ts:142
 #, fuzzy
 #, fuzzy
 msgid "Rename stream %{name} to %{new_name} on %{node} successfully"
 msgid "Rename stream %{name} to %{new_name} on %{node} successfully"
 msgstr "إعادة تسمية الموقع %{site} إلى %{new_site} على %{node} بنجاح"
 msgstr "إعادة تسمية الموقع %{site} إلى %{new_site} على %{node} بنجاح"
@@ -2958,22 +3005,22 @@ msgstr "إعادة تشغيل"
 msgid "Restart Nginx"
 msgid "Restart Nginx"
 msgstr "إعادة التشغيل"
 msgstr "إعادة التشغيل"
 
 
-#: src/components/Notification/notifications.ts:152
+#: src/components/Notification/notifications.ts:18
 #, fuzzy
 #, fuzzy
 msgid "Restart Nginx on %{node} failed, response: %{resp}"
 msgid "Restart Nginx on %{node} failed, response: %{resp}"
 msgstr "خطأ في تفعيل الموقع %{site} على %{node}، الاستجابة: %{resp}"
 msgstr "خطأ في تفعيل الموقع %{site} على %{node}، الاستجابة: %{resp}"
 
 
-#: src/components/Notification/notifications.ts:156
+#: src/components/Notification/notifications.ts:22
 #, fuzzy
 #, fuzzy
 msgid "Restart Nginx on %{node} successfully"
 msgid "Restart Nginx on %{node} successfully"
 msgstr "تمت ترقية Nginx UI على %{node} بنجاح 🎉"
 msgstr "تمت ترقية Nginx UI على %{node} بنجاح 🎉"
 
 
-#: src/components/Notification/notifications.ts:151
+#: src/components/Notification/notifications.ts:17
 #, fuzzy
 #, fuzzy
 msgid "Restart Remote Nginx Error"
 msgid "Restart Remote Nginx Error"
 msgstr "خطأ في إعادة تسمية الموقع البعيد"
 msgstr "خطأ في إعادة تسمية الموقع البعيد"
 
 
-#: src/components/Notification/notifications.ts:155
+#: src/components/Notification/notifications.ts:21
 #, fuzzy
 #, fuzzy
 msgid "Restart Remote Nginx Success"
 msgid "Restart Remote Nginx Success"
 msgstr "تم إعادة تسمية الموقع البعيد بنجاح"
 msgstr "تم إعادة تسمية الموقع البعيد بنجاح"
@@ -3040,7 +3087,7 @@ msgstr "يعمل"
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/ConfigEditor.vue:271
 #: src/views/config/ConfigEditor.vue:271
 #: src/views/preference/components/Passkey.vue:130
 #: src/views/preference/components/Passkey.vue:130
-#: src/views/preference/Preference.vue:221
+#: src/views/preference/Preference.vue:228
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:127
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:127
 #: src/views/site/site_edit/components/ConfigName.vue:52
 #: src/views/site/site_edit/components/ConfigName.vue:52
 #: src/views/site/site_edit/SiteEdit.vue:292
 #: src/views/site/site_edit/SiteEdit.vue:292
@@ -3058,40 +3105,42 @@ msgstr "حفظ التوجيه"
 msgid "Save error %{msg}"
 msgid "Save error %{msg}"
 msgstr "خطأ في الحفظ %{msg}"
 msgstr "خطأ في الحفظ %{msg}"
 
 
-#: src/components/Notification/notifications.ts:85 src/language/constants.ts:48
+#: src/components/Notification/notifications.ts:103
+#: src/language/constants.ts:48
 msgid "Save Remote Site Error"
 msgid "Save Remote Site Error"
 msgstr "خطأ في حفظ الموقع البعيد"
 msgstr "خطأ في حفظ الموقع البعيد"
 
 
-#: src/components/Notification/notifications.ts:89 src/language/constants.ts:47
+#: src/components/Notification/notifications.ts:107
+#: src/language/constants.ts:47
 msgid "Save Remote Site Success"
 msgid "Save Remote Site Success"
 msgstr "حفظ الموقع البعيد بنجاح"
 msgstr "حفظ الموقع البعيد بنجاح"
 
 
-#: src/components/Notification/notifications.ts:127
+#: src/components/Notification/notifications.ts:145
 #, fuzzy
 #, fuzzy
 msgid "Save Remote Stream Error"
 msgid "Save Remote Stream Error"
 msgstr "خطأ في حفظ الموقع البعيد"
 msgstr "خطأ في حفظ الموقع البعيد"
 
 
-#: src/components/Notification/notifications.ts:131
+#: src/components/Notification/notifications.ts:149
 #, fuzzy
 #, fuzzy
 msgid "Save Remote Stream Success"
 msgid "Save Remote Stream Success"
 msgstr "حفظ الموقع البعيد بنجاح"
 msgstr "حفظ الموقع البعيد بنجاح"
 
 
-#: src/components/Notification/notifications.ts:86
+#: src/components/Notification/notifications.ts:104
 #, fuzzy
 #, fuzzy
 msgid "Save site %{name} to %{node} failed"
 msgid "Save site %{name} to %{node} failed"
 msgstr "تم حفظ الموقع %{site} إلى %{node} بنجاح"
 msgstr "تم حفظ الموقع %{site} إلى %{node} بنجاح"
 
 
-#: src/components/Notification/notifications.ts:90
+#: src/components/Notification/notifications.ts:108
 #, fuzzy
 #, fuzzy
 msgid "Save site %{name} to %{node} successfully"
 msgid "Save site %{name} to %{node} successfully"
 msgstr "تم حفظ الموقع %{site} إلى %{node} بنجاح"
 msgstr "تم حفظ الموقع %{site} إلى %{node} بنجاح"
 
 
-#: src/components/Notification/notifications.ts:128
+#: src/components/Notification/notifications.ts:146
 #, fuzzy
 #, fuzzy
 msgid "Save stream %{name} to %{node} failed"
 msgid "Save stream %{name} to %{node} failed"
 msgstr "فشل نشر {conf_name}% إلى {node_name}%"
 msgstr "فشل نشر {conf_name}% إلى {node_name}%"
 
 
-#: src/components/Notification/notifications.ts:132
+#: src/components/Notification/notifications.ts:150
 #, fuzzy
 #, fuzzy
 msgid "Save stream %{name} to %{node} successfully"
 msgid "Save stream %{name} to %{node} successfully"
 msgstr "تم حفظ الموقع %{site} إلى %{node} بنجاح"
 msgstr "تم حفظ الموقع %{site} إلى %{node} بنجاح"
@@ -3099,7 +3148,7 @@ msgstr "تم حفظ الموقع %{site} إلى %{node} بنجاح"
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:47
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:47
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:97
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:97
 #: src/views/certificate/CertificateEditor.vue:49
 #: src/views/certificate/CertificateEditor.vue:49
-#: src/views/preference/Preference.vue:123
+#: src/views/preference/Preference.vue:124
 msgid "Save successfully"
 msgid "Save successfully"
 msgstr "تم الحفظ بنجاح"
 msgstr "تم الحفظ بنجاح"
 
 
@@ -3119,6 +3168,10 @@ msgstr "امسح رمز الاستجابة السريعة بهاتفك المح
 msgid "SDK"
 msgid "SDK"
 msgstr "حزمة تطوير البرمجيات SDK"
 msgstr "حزمة تطوير البرمجيات SDK"
 
 
+#: src/views/preference/components/ExternalNotify/dingtalk.ts:13
+msgid "Secret (Optional)"
+msgstr ""
+
 #: src/views/preference/components/TOTP.vue:109
 #: src/views/preference/components/TOTP.vue:109
 msgid "Secret has been copied"
 msgid "Secret has been copied"
 msgstr "تم نسخ السر"
 msgstr "تم نسخ السر"
@@ -3150,7 +3203,7 @@ msgstr ""
 msgid "Send"
 msgid "Send"
 msgstr "إرسال"
 msgstr "إرسال"
 
 
-#: src/views/preference/Preference.vue:156
+#: src/views/preference/Preference.vue:157
 #, fuzzy
 #, fuzzy
 msgid "Server"
 msgid "Server"
 msgstr "معلومات الخادم"
 msgstr "معلومات الخادم"
@@ -3159,6 +3212,11 @@ msgstr "معلومات الخادم"
 msgid "Server Info"
 msgid "Server Info"
 msgstr "معلومات الخادم"
 msgstr "معلومات الخادم"
 
 
+#: src/views/preference/components/ExternalNotify/bark.ts:13
+#, fuzzy
+msgid "Server URL"
+msgstr "معلومات الخادم"
+
 #: src/views/site/cert/components/ObtainCert.vue:107
 #: src/views/site/cert/components/ObtainCert.vue:107
 msgid "server_name not found in directives"
 msgid "server_name not found in directives"
 msgstr "اسم_الخادم غير موجود في التوجيهات"
 msgstr "اسم_الخادم غير موجود في التوجيهات"
@@ -3335,7 +3393,7 @@ msgstr ""
 #: src/views/certificate/ACMEUser.vue:65
 #: src/views/certificate/ACMEUser.vue:65
 #: src/views/certificate/CertificateList/certColumns.tsx:65
 #: src/views/certificate/CertificateList/certColumns.tsx:65
 #: src/views/environments/list/envColumns.tsx:44
 #: src/views/environments/list/envColumns.tsx:44
-#: src/views/site/site_edit/RightSettings.vue:56
+#: src/views/site/site_edit/RightSettings.vue:55
 #: src/views/site/site_list/columns.tsx:80 src/views/stream/StreamList.vue:47
 #: src/views/site/site_list/columns.tsx:80 src/views/stream/StreamList.vue:47
 msgid "Status"
 msgid "Status"
 msgstr "الحالة"
 msgstr "الحالة"
@@ -3412,38 +3470,38 @@ msgstr "مزامنة"
 msgid "Sync Certificate"
 msgid "Sync Certificate"
 msgstr "مزامنة الشهادة"
 msgstr "مزامنة الشهادة"
 
 
-#: src/components/Notification/notifications.ts:10
+#: src/components/Notification/notifications.ts:28
 #, fuzzy
 #, fuzzy
 msgid "Sync Certificate %{cert_name} to %{env_name} failed"
 msgid "Sync Certificate %{cert_name} to %{env_name} failed"
 msgstr "نجح مزامنة الشهادة %{cert_name} إلى %{env_name}"
 msgstr "نجح مزامنة الشهادة %{cert_name} إلى %{env_name}"
 
 
-#: src/components/Notification/notifications.ts:14
+#: src/components/Notification/notifications.ts:32
 msgid "Sync Certificate %{cert_name} to %{env_name} successfully"
 msgid "Sync Certificate %{cert_name} to %{env_name} successfully"
 msgstr "نجح مزامنة الشهادة %{cert_name} إلى %{env_name}"
 msgstr "نجح مزامنة الشهادة %{cert_name} إلى %{env_name}"
 
 
-#: src/components/Notification/notifications.ts:9 src/language/constants.ts:39
+#: src/components/Notification/notifications.ts:27 src/language/constants.ts:39
 msgid "Sync Certificate Error"
 msgid "Sync Certificate Error"
 msgstr "خطأ في مزامنة الشهادة"
 msgstr "خطأ في مزامنة الشهادة"
 
 
-#: src/components/Notification/notifications.ts:13 src/language/constants.ts:38
+#: src/components/Notification/notifications.ts:31 src/language/constants.ts:38
 msgid "Sync Certificate Success"
 msgid "Sync Certificate Success"
 msgstr "تمت مزامنة الشهادة بنجاح"
 msgstr "تمت مزامنة الشهادة بنجاح"
 
 
-#: src/components/Notification/notifications.ts:20
+#: src/components/Notification/notifications.ts:38
 #, fuzzy
 #, fuzzy
 msgid "Sync config %{config_name} to %{env_name} failed"
 msgid "Sync config %{config_name} to %{env_name} failed"
 msgstr "تمت مزامنة التكوين %{config_name} إلى %{env_name} بنجاح"
 msgstr "تمت مزامنة التكوين %{config_name} إلى %{env_name} بنجاح"
 
 
-#: src/components/Notification/notifications.ts:24
+#: src/components/Notification/notifications.ts:42
 #, fuzzy
 #, fuzzy
 msgid "Sync config %{config_name} to %{env_name} successfully"
 msgid "Sync config %{config_name} to %{env_name} successfully"
 msgstr "تمت مزامنة التكوين %{config_name} إلى %{env_name} بنجاح"
 msgstr "تمت مزامنة التكوين %{config_name} إلى %{env_name} بنجاح"
 
 
-#: src/components/Notification/notifications.ts:19 src/language/constants.ts:45
+#: src/components/Notification/notifications.ts:37 src/language/constants.ts:45
 msgid "Sync Config Error"
 msgid "Sync Config Error"
 msgstr "خطأ في تزامن التكوين"
 msgstr "خطأ في تزامن التكوين"
 
 
-#: src/components/Notification/notifications.ts:23 src/language/constants.ts:44
+#: src/components/Notification/notifications.ts:41 src/language/constants.ts:44
 msgid "Sync Config Success"
 msgid "Sync Config Success"
 msgstr "تمت مزامنة التكوين بنجاح"
 msgstr "تمت مزامنة التكوين بنجاح"
 
 
@@ -3452,8 +3510,8 @@ msgstr "تمت مزامنة التكوين بنجاح"
 msgid "Sync Nodes"
 msgid "Sync Nodes"
 msgstr "مزامنة العقد"
 msgstr "مزامنة العقد"
 
 
-#: src/views/site/site_edit/RightSettings.vue:102
-#: src/views/site/site_edit/RightSettings.vue:89
+#: src/views/site/site_edit/RightSettings.vue:101
+#: src/views/site/site_edit/RightSettings.vue:88
 #: src/views/stream/components/RightSettings.vue:111
 #: src/views/stream/components/RightSettings.vue:111
 #: src/views/stream/components/RightSettings.vue:124
 #: src/views/stream/components/RightSettings.vue:124
 msgid "Sync strategy"
 msgid "Sync strategy"
@@ -3463,7 +3521,7 @@ msgstr "استراتيجية المزامنة"
 msgid "Sync to"
 msgid "Sync to"
 msgstr "مزامنة إلى"
 msgstr "مزامنة إلى"
 
 
-#: src/views/site/site_edit/RightSettings.vue:86
+#: src/views/site/site_edit/RightSettings.vue:85
 #: src/views/stream/components/RightSettings.vue:108
 #: src/views/stream/components/RightSettings.vue:108
 msgid "Synchronization"
 msgid "Synchronization"
 msgstr "مزامنة"
 msgstr "مزامنة"
@@ -3496,7 +3554,11 @@ msgstr "تم إعادة تشغيل Nginx بنجاح"
 msgid "Task not found"
 msgid "Task not found"
 msgstr "غير موجود"
 msgstr "غير موجود"
 
 
-#: src/routes/modules/terminal.ts:10 src/views/preference/Preference.vue:180
+#: src/views/preference/components/ExternalNotify/telegram.ts:5
+msgid "Telegram"
+msgstr ""
+
+#: src/routes/modules/terminal.ts:10 src/views/preference/Preference.vue:187
 #: src/views/terminal/Terminal.vue:129
 #: src/views/terminal/Terminal.vue:129
 msgid "Terminal"
 msgid "Terminal"
 msgstr "محطة"
 msgstr "محطة"
@@ -3767,6 +3829,7 @@ msgstr "يتطلب المصادقة الثنائية"
 #: src/views/certificate/CertificateList/certColumns.tsx:25
 #: src/views/certificate/CertificateList/certColumns.tsx:25
 #: src/views/nginx_log/NginxLogList.vue:21
 #: src/views/nginx_log/NginxLogList.vue:21
 #: src/views/notification/notificationColumns.tsx:9
 #: src/views/notification/notificationColumns.tsx:9
+#: src/views/preference/components/ExternalNotify/columns.ts:17
 msgid "Type"
 msgid "Type"
 msgstr "نوع"
 msgstr "نوع"
 
 
@@ -3783,7 +3846,7 @@ msgstr "تم التحديث بنجاح"
 #: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:325
 #: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:325
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/environments/list/envColumns.tsx:90
-#: src/views/site/site_edit/RightSettings.vue:76
+#: src/views/site/site_edit/RightSettings.vue:75
 #: src/views/site/site_list/columns.tsx:110
 #: src/views/site/site_list/columns.tsx:110
 #: src/views/stream/components/RightSettings.vue:99
 #: src/views/stream/components/RightSettings.vue:99
 #: src/views/stream/StreamList.vue:67 src/views/user/userColumns.tsx:54
 #: src/views/stream/StreamList.vue:67 src/views/user/userColumns.tsx:54
@@ -3946,7 +4009,7 @@ msgstr ""
 "التشغيل. بشكل عام، لا تقم بتمكين هذا إلا إذا كنت في بيئة تطوير وتستخدم "
 "التشغيل. بشكل عام، لا تقم بتمكين هذا إلا إذا كنت في بيئة تطوير وتستخدم "
 "Pebble كسلطة شهادات."
 "Pebble كسلطة شهادات."
 
 
-#: src/views/site/site_edit/RightSettings.vue:92
+#: src/views/site/site_edit/RightSettings.vue:91
 #, fuzzy
 #, fuzzy
 msgid ""
 msgid ""
 "When you enable/disable, delete, or save this site, the nodes set in the "
 "When you enable/disable, delete, or save this site, the nodes set in the "

+ 165 - 102
app/src/language/de_DE/app.po

@@ -30,6 +30,11 @@ msgstr "Zugriffslog"
 msgid "Access Logs"
 msgid "Access Logs"
 msgstr "Zugriffslog"
 msgstr "Zugriffslog"
 
 
+#: src/views/preference/components/ExternalNotify/dingtalk.ts:9
+#, fuzzy
+msgid "Access Token"
+msgstr "Zugriffslog"
+
 #: src/routes/modules/certificates.ts:20 src/views/certificate/ACMEUser.vue:113
 #: src/routes/modules/certificates.ts:20 src/views/certificate/ACMEUser.vue:113
 #: src/views/certificate/ACMEUserSelector.vue:85
 #: src/views/certificate/ACMEUserSelector.vue:85
 #, fuzzy
 #, fuzzy
@@ -45,6 +50,7 @@ msgstr "Benutzername"
 #: src/views/nginx_log/NginxLogList.vue:53
 #: src/views/nginx_log/NginxLogList.vue:53
 #: src/views/notification/notificationColumns.tsx:66
 #: src/views/notification/notificationColumns.tsx:66
 #: src/views/preference/AuthSettings.vue:30
 #: src/views/preference/AuthSettings.vue:30
+#: src/views/preference/components/ExternalNotify/columns.ts:46
 #: src/views/site/site_list/columns.tsx:117 src/views/stream/StreamList.vue:74
 #: src/views/site/site_list/columns.tsx:117 src/views/stream/StreamList.vue:74
 #: src/views/user/userColumns.tsx:60
 #: src/views/user/userColumns.tsx:60
 msgid "Action"
 msgid "Action"
@@ -115,7 +121,7 @@ msgstr ""
 msgid "All"
 msgid "All"
 msgstr "Alle"
 msgstr "Alle"
 
 
-#: src/components/Notification/notifications.ts:137
+#: src/components/Notification/notifications.ts:155
 #: src/language/constants.ts:58
 #: src/language/constants.ts:58
 msgid "All Recovery Codes Have Been Used"
 msgid "All Recovery Codes Have Been Used"
 msgstr ""
 msgstr ""
@@ -140,7 +146,7 @@ msgstr "API-Token"
 msgid "API Type"
 msgid "API Type"
 msgstr "API-Typ"
 msgstr "API-Typ"
 
 
-#: src/views/preference/Preference.vue:162
+#: src/views/preference/Preference.vue:163
 #, fuzzy
 #, fuzzy
 msgid "App"
 msgid "App"
 msgstr "Anwenden"
 msgstr "Anwenden"
@@ -204,7 +210,7 @@ msgstr "Bist du sicher, dass du diese Richtlinie löschen möchtest?"
 msgid "Are you sure you want to delete this item?"
 msgid "Are you sure you want to delete this item?"
 msgstr "Bist du sicher, dass du diese Richtlinie löschen möchtest?"
 msgstr "Bist du sicher, dass du diese Richtlinie löschen möchtest?"
 
 
-#: src/views/site/site_list/SiteList.vue:163
+#: src/views/site/site_list/SiteList.vue:167
 #: src/views/stream/StreamList.vue:227
 #: src/views/stream/StreamList.vue:227
 #, fuzzy
 #, fuzzy
 msgid "Are you sure you want to delete?"
 msgid "Are you sure you want to delete?"
@@ -257,7 +263,7 @@ msgstr "Versuche"
 msgid "Attempts"
 msgid "Attempts"
 msgstr "Versuche"
 msgstr "Versuche"
 
 
-#: src/views/preference/Preference.vue:186
+#: src/views/preference/Preference.vue:193
 msgid "Auth"
 msgid "Auth"
 msgstr "Authentifizierung"
 msgstr "Authentifizierung"
 
 
@@ -342,12 +348,16 @@ msgstr "Gesperrte IPs"
 msgid "Banned Until"
 msgid "Banned Until"
 msgstr "Gesperrt bis"
 msgstr "Gesperrt bis"
 
 
+#: src/views/preference/components/ExternalNotify/bark.ts:5
+msgid "Bark"
+msgstr ""
+
 #: src/views/site/site_add/SiteAdd.vue:95
 #: src/views/site/site_add/SiteAdd.vue:95
 msgid "Base information"
 msgid "Base information"
 msgstr "Basisinformationen"
 msgstr "Basisinformationen"
 
 
 #: src/views/config/ConfigEditor.vue:290
 #: src/views/config/ConfigEditor.vue:290
-#: src/views/site/site_edit/RightSettings.vue:53
+#: src/views/site/site_edit/RightSettings.vue:52
 #: src/views/stream/components/RightSettings.vue:79
 #: src/views/stream/components/RightSettings.vue:79
 #, fuzzy
 #, fuzzy
 msgid "Basic"
 msgid "Basic"
@@ -382,6 +392,11 @@ msgstr ""
 msgid "Block is nil"
 msgid "Block is nil"
 msgstr ""
 msgstr ""
 
 
+#: src/views/preference/components/ExternalNotify/telegram.ts:9
+#, fuzzy
+msgid "Bot Token"
+msgstr "API-Token"
+
 #: src/views/system/About.vue:55
 #: src/views/system/About.vue:55
 msgid "Build with"
 msgid "Build with"
 msgstr "Build mit"
 msgstr "Build mit"
@@ -423,7 +438,7 @@ msgstr ""
 msgid "Cannot remove initial user"
 msgid "Cannot remove initial user"
 msgstr "System-Startbenutzer"
 msgstr "System-Startbenutzer"
 
 
-#: src/views/preference/Preference.vue:192
+#: src/views/preference/Preference.vue:199
 msgid "Cert"
 msgid "Cert"
 msgstr "Zertifikat"
 msgstr "Zertifikat"
 
 
@@ -502,6 +517,10 @@ msgstr "Zertifikat ist gültig"
 msgid "Channel"
 msgid "Channel"
 msgstr "Kanal"
 msgstr "Kanal"
 
 
+#: src/views/preference/components/ExternalNotify/telegram.ts:13
+msgid "Chat ID"
+msgstr ""
+
 #: src/views/system/Upgrade.vue:185
 #: src/views/system/Upgrade.vue:185
 msgid "Check again"
 msgid "Check again"
 msgstr "Erneut prüfen"
 msgstr "Erneut prüfen"
@@ -704,6 +723,7 @@ msgstr ""
 
 
 #: src/views/environments/group/columns.ts:31
 #: src/views/environments/group/columns.ts:31
 #: src/views/notification/notificationColumns.tsx:59
 #: src/views/notification/notificationColumns.tsx:59
+#: src/views/preference/components/ExternalNotify/columns.ts:41
 #: src/views/preference/components/Passkey.vue:95
 #: src/views/preference/components/Passkey.vue:95
 #: src/views/user/userColumns.tsx:48
 #: src/views/user/userColumns.tsx:48
 msgid "Created at"
 msgid "Created at"
@@ -777,7 +797,7 @@ msgstr "Beschreibung"
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/views/site/ngx_conf/NgxServer.vue:110
 #: src/views/site/ngx_conf/NgxServer.vue:110
 #: src/views/site/ngx_conf/NgxUpstream.vue:128
 #: src/views/site/ngx_conf/NgxUpstream.vue:128
-#: src/views/site/site_list/SiteList.vue:172
+#: src/views/site/site_list/SiteList.vue:176
 #: src/views/stream/StreamList.vue:236
 #: src/views/stream/StreamList.vue:236
 msgid "Delete"
 msgid "Delete"
 msgstr "Löschen"
 msgstr "Löschen"
@@ -787,46 +807,46 @@ msgstr "Löschen"
 msgid "Delete Permanently"
 msgid "Delete Permanently"
 msgstr "Permanent löschen"
 msgstr "Permanent löschen"
 
 
-#: src/components/Notification/notifications.ts:37 src/language/constants.ts:50
+#: src/components/Notification/notifications.ts:55 src/language/constants.ts:50
 #, fuzzy
 #, fuzzy
 msgid "Delete Remote Site Error"
 msgid "Delete Remote Site Error"
 msgstr "Zertifikat ist gültig"
 msgstr "Zertifikat ist gültig"
 
 
-#: src/components/Notification/notifications.ts:41 src/language/constants.ts:49
+#: src/components/Notification/notifications.ts:59 src/language/constants.ts:49
 #, fuzzy
 #, fuzzy
 msgid "Delete Remote Site Success"
 msgid "Delete Remote Site Success"
 msgstr "Zertifikat ist gültig"
 msgstr "Zertifikat ist gültig"
 
 
-#: src/components/Notification/notifications.ts:95
+#: src/components/Notification/notifications.ts:113
 #, fuzzy
 #, fuzzy
 msgid "Delete Remote Stream Error"
 msgid "Delete Remote Stream Error"
 msgstr "Zertifikat ist gültig"
 msgstr "Zertifikat ist gültig"
 
 
-#: src/components/Notification/notifications.ts:99
+#: src/components/Notification/notifications.ts:117
 #, fuzzy
 #, fuzzy
 msgid "Delete Remote Stream Success"
 msgid "Delete Remote Stream Success"
 msgstr "Zertifikat ist gültig"
 msgstr "Zertifikat ist gültig"
 
 
-#: src/components/Notification/notifications.ts:38
+#: src/components/Notification/notifications.ts:56
 #, fuzzy
 #, fuzzy
 msgid "Delete site %{name} from %{node} failed"
 msgid "Delete site %{name} from %{node} failed"
 msgstr "Ausführen von %{conf_name} auf %{node_name} fehlgeschlagen"
 msgstr "Ausführen von %{conf_name} auf %{node_name} fehlgeschlagen"
 
 
-#: src/components/Notification/notifications.ts:42
+#: src/components/Notification/notifications.ts:60
 #, fuzzy
 #, fuzzy
 msgid "Delete site %{name} from %{node} successfully"
 msgid "Delete site %{name} from %{node} successfully"
 msgstr "Speichern erfolgreich"
 msgstr "Speichern erfolgreich"
 
 
-#: src/views/site/site_list/SiteList.vue:94
+#: src/views/site/site_list/SiteList.vue:98
 msgid "Delete site: %{site_name}"
 msgid "Delete site: %{site_name}"
 msgstr "Seite löschen: %{site_name}"
 msgstr "Seite löschen: %{site_name}"
 
 
-#: src/components/Notification/notifications.ts:96
+#: src/components/Notification/notifications.ts:114
 #, fuzzy
 #, fuzzy
 msgid "Delete stream %{name} from %{node} failed"
 msgid "Delete stream %{name} from %{node} failed"
 msgstr "Ausführen von %{conf_name} auf %{node_name} fehlgeschlagen"
 msgstr "Ausführen von %{conf_name} auf %{node_name} fehlgeschlagen"
 
 
-#: src/components/Notification/notifications.ts:100
+#: src/components/Notification/notifications.ts:118
 #, fuzzy
 #, fuzzy
 msgid "Delete stream %{name} from %{node} successfully"
 msgid "Delete stream %{name} from %{node} successfully"
 msgstr "Speichern erfolgreich"
 msgstr "Speichern erfolgreich"
@@ -865,6 +885,14 @@ msgstr "Details"
 msgid "Development Mode"
 msgid "Development Mode"
 msgstr "Entwicklungsmodus"
 msgstr "Entwicklungsmodus"
 
 
+#: src/views/preference/components/ExternalNotify/bark.ts:9
+msgid "Device Key"
+msgstr ""
+
+#: src/views/preference/components/ExternalNotify/dingtalk.ts:5
+msgid "DingTalk"
+msgstr ""
+
 #: src/views/site/ngx_conf/directive/DirectiveAdd.vue:89
 #: src/views/site/ngx_conf/directive/DirectiveAdd.vue:89
 msgid "Directive"
 msgid "Directive"
 msgstr "Anweisung"
 msgstr "Anweisung"
@@ -899,62 +927,62 @@ msgstr "Deaktiviert"
 msgid "Disable auto-renewal failed for %{name}"
 msgid "Disable auto-renewal failed for %{name}"
 msgstr "Automatische Verlängerung deaktiviert für %{name}"
 msgstr "Automatische Verlängerung deaktiviert für %{name}"
 
 
-#: src/components/Notification/notifications.ts:45 src/language/constants.ts:52
+#: src/components/Notification/notifications.ts:63 src/language/constants.ts:52
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Site Error"
 msgid "Disable Remote Site Error"
 msgstr "Zertifikat ist gültig"
 msgstr "Zertifikat ist gültig"
 
 
-#: src/components/Notification/notifications.ts:69
+#: src/components/Notification/notifications.ts:87
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Site Maintenance Error"
 msgid "Disable Remote Site Maintenance Error"
 msgstr "Zertifikat ist gültig"
 msgstr "Zertifikat ist gültig"
 
 
-#: src/components/Notification/notifications.ts:73
+#: src/components/Notification/notifications.ts:91
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Site Maintenance Success"
 msgid "Disable Remote Site Maintenance Success"
 msgstr "Zertifikat ist gültig"
 msgstr "Zertifikat ist gültig"
 
 
-#: src/components/Notification/notifications.ts:49 src/language/constants.ts:51
+#: src/components/Notification/notifications.ts:67 src/language/constants.ts:51
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Site Success"
 msgid "Disable Remote Site Success"
 msgstr "Zertifikat ist gültig"
 msgstr "Zertifikat ist gültig"
 
 
-#: src/components/Notification/notifications.ts:103
+#: src/components/Notification/notifications.ts:121
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Stream Error"
 msgid "Disable Remote Stream Error"
 msgstr "Zertifikat ist gültig"
 msgstr "Zertifikat ist gültig"
 
 
-#: src/components/Notification/notifications.ts:107
+#: src/components/Notification/notifications.ts:125
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Stream Success"
 msgid "Disable Remote Stream Success"
 msgstr "Zertifikat ist gültig"
 msgstr "Zertifikat ist gültig"
 
 
-#: src/components/Notification/notifications.ts:46
+#: src/components/Notification/notifications.ts:64
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} from %{node} failed"
 msgid "Disable site %{name} from %{node} failed"
 msgstr "Speichern erfolgreich"
 msgstr "Speichern erfolgreich"
 
 
-#: src/components/Notification/notifications.ts:50
+#: src/components/Notification/notifications.ts:68
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} from %{node} successfully"
 msgid "Disable site %{name} from %{node} successfully"
 msgstr "Speichern erfolgreich"
 msgstr "Speichern erfolgreich"
 
 
-#: src/components/Notification/notifications.ts:70
+#: src/components/Notification/notifications.ts:88
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} maintenance on %{node} failed"
 msgid "Disable site %{name} maintenance on %{node} failed"
 msgstr "Speichern erfolgreich"
 msgstr "Speichern erfolgreich"
 
 
-#: src/components/Notification/notifications.ts:74
+#: src/components/Notification/notifications.ts:92
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} maintenance on %{node} successfully"
 msgid "Disable site %{name} maintenance on %{node} successfully"
 msgstr "Speichern erfolgreich"
 msgstr "Speichern erfolgreich"
 
 
-#: src/components/Notification/notifications.ts:104
+#: src/components/Notification/notifications.ts:122
 #, fuzzy
 #, fuzzy
 msgid "Disable stream %{name} from %{node} failed"
 msgid "Disable stream %{name} from %{node} failed"
 msgstr "Aktivieren von %{conf_name} in %{node_name} fehlgeschlagen"
 msgstr "Aktivieren von %{conf_name} in %{node_name} fehlgeschlagen"
 
 
-#: src/components/Notification/notifications.ts:108
+#: src/components/Notification/notifications.ts:126
 #, fuzzy
 #, fuzzy
 msgid "Disable stream %{name} from %{node} successfully"
 msgid "Disable stream %{name} from %{node} successfully"
 msgstr "Speichern erfolgreich"
 msgstr "Speichern erfolgreich"
@@ -1076,7 +1104,7 @@ msgstr ""
 "werden."
 "werden."
 
 
 #: src/views/site/site_list/SiteDuplicate.vue:72
 #: src/views/site/site_list/SiteDuplicate.vue:72
-#: src/views/site/site_list/SiteList.vue:158
+#: src/views/site/site_list/SiteList.vue:162
 #: src/views/stream/components/StreamDuplicate.vue:64
 #: src/views/stream/components/StreamDuplicate.vue:64
 #: src/views/stream/StreamList.vue:222
 #: src/views/stream/StreamList.vue:222
 msgid "Duplicate"
 msgid "Duplicate"
@@ -1149,62 +1177,62 @@ msgstr "Aktivieren fehlgeschlagen"
 msgid "Enable HTTPS"
 msgid "Enable HTTPS"
 msgstr "Aktiviere TLS"
 msgstr "Aktiviere TLS"
 
 
-#: src/components/Notification/notifications.ts:53 src/language/constants.ts:54
+#: src/components/Notification/notifications.ts:71 src/language/constants.ts:54
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Site Error"
 msgid "Enable Remote Site Error"
 msgstr "Zertifikat ist gültig"
 msgstr "Zertifikat ist gültig"
 
 
-#: src/components/Notification/notifications.ts:61
+#: src/components/Notification/notifications.ts:79
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Site Maintenance Error"
 msgid "Enable Remote Site Maintenance Error"
 msgstr "Zertifikat ist gültig"
 msgstr "Zertifikat ist gültig"
 
 
-#: src/components/Notification/notifications.ts:65
+#: src/components/Notification/notifications.ts:83
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Site Maintenance Success"
 msgid "Enable Remote Site Maintenance Success"
 msgstr "Zertifikat ist gültig"
 msgstr "Zertifikat ist gültig"
 
 
-#: src/components/Notification/notifications.ts:57 src/language/constants.ts:53
+#: src/components/Notification/notifications.ts:75 src/language/constants.ts:53
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Site Success"
 msgid "Enable Remote Site Success"
 msgstr "Zertifikat ist gültig"
 msgstr "Zertifikat ist gültig"
 
 
-#: src/components/Notification/notifications.ts:111
+#: src/components/Notification/notifications.ts:129
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Stream Error"
 msgid "Enable Remote Stream Error"
 msgstr "Zertifikat ist gültig"
 msgstr "Zertifikat ist gültig"
 
 
-#: src/components/Notification/notifications.ts:115
+#: src/components/Notification/notifications.ts:133
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Stream Success"
 msgid "Enable Remote Stream Success"
 msgstr "Zertifikat ist gültig"
 msgstr "Zertifikat ist gültig"
 
 
-#: src/components/Notification/notifications.ts:62
+#: src/components/Notification/notifications.ts:80
 #, fuzzy
 #, fuzzy
 msgid "Enable site %{name} maintenance on %{node} failed"
 msgid "Enable site %{name} maintenance on %{node} failed"
 msgstr "Aktivieren von %{conf_name} in %{node_name} fehlgeschlagen"
 msgstr "Aktivieren von %{conf_name} in %{node_name} fehlgeschlagen"
 
 
-#: src/components/Notification/notifications.ts:66
+#: src/components/Notification/notifications.ts:84
 #, fuzzy
 #, fuzzy
 msgid "Enable site %{name} maintenance on %{node} successfully"
 msgid "Enable site %{name} maintenance on %{node} successfully"
 msgstr "Erfolgreich gespeichert"
 msgstr "Erfolgreich gespeichert"
 
 
-#: src/components/Notification/notifications.ts:54
+#: src/components/Notification/notifications.ts:72
 #, fuzzy
 #, fuzzy
 msgid "Enable site %{name} on %{node} failed"
 msgid "Enable site %{name} on %{node} failed"
 msgstr "Aktivieren von %{conf_name} in %{node_name} fehlgeschlagen"
 msgstr "Aktivieren von %{conf_name} in %{node_name} fehlgeschlagen"
 
 
-#: src/components/Notification/notifications.ts:58
+#: src/components/Notification/notifications.ts:76
 #, fuzzy
 #, fuzzy
 msgid "Enable site %{name} on %{node} successfully"
 msgid "Enable site %{name} on %{node} successfully"
 msgstr "Erfolgreich gespeichert"
 msgstr "Erfolgreich gespeichert"
 
 
-#: src/components/Notification/notifications.ts:112
+#: src/components/Notification/notifications.ts:130
 #, fuzzy
 #, fuzzy
 msgid "Enable stream %{name} on %{node} failed"
 msgid "Enable stream %{name} on %{node} failed"
 msgstr "Aktivieren von %{conf_name} in %{node_name} fehlgeschlagen"
 msgstr "Aktivieren von %{conf_name} in %{node_name} fehlgeschlagen"
 
 
-#: src/components/Notification/notifications.ts:116
+#: src/components/Notification/notifications.ts:134
 #, fuzzy
 #, fuzzy
 msgid "Enable stream %{name} on %{node} successfully"
 msgid "Enable stream %{name} on %{node} successfully"
 msgstr "Erfolgreich gespeichert"
 msgstr "Erfolgreich gespeichert"
@@ -1295,6 +1323,11 @@ msgstr "Ablaufdatum: %{date}"
 msgid "Export"
 msgid "Export"
 msgstr "Exportieren"
 msgstr "Exportieren"
 
 
+#: src/views/preference/ExternalNotify.vue:10
+#: src/views/preference/Preference.vue:169
+msgid "External Notify"
+msgstr ""
+
 #: src/views/site/cert/components/ObtainCertLive.vue:94
 #: src/views/site/cert/components/ObtainCertLive.vue:94
 #, fuzzy
 #, fuzzy
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
@@ -1700,7 +1733,7 @@ msgstr "Startseite"
 msgid "Host"
 msgid "Host"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/Preference.vue:174
+#: src/views/preference/Preference.vue:181
 msgid "HTTP"
 msgid "HTTP"
 msgstr ""
 msgstr ""
 
 
@@ -1764,12 +1797,12 @@ msgid "Import Certificate"
 msgstr "Zertifikatsstatus"
 msgstr "Zertifikatsstatus"
 
 
 #: src/views/nginx_log/NginxLogList.vue:137
 #: src/views/nginx_log/NginxLogList.vue:137
-#: src/views/site/site_list/SiteList.vue:128
+#: src/views/site/site_list/SiteList.vue:132
 msgid "Indexed"
 msgid "Indexed"
 msgstr ""
 msgstr ""
 
 
 #: src/views/nginx_log/NginxLogList.vue:134
 #: src/views/nginx_log/NginxLogList.vue:134
-#: src/views/site/site_list/SiteList.vue:125
+#: src/views/site/site_list/SiteList.vue:129
 msgid "Indexing..."
 msgid "Indexing..."
 msgstr ""
 msgstr ""
 
 
@@ -1854,6 +1887,11 @@ msgstr "Ungültige E-Mail!"
 msgid "Invalid folder name"
 msgid "Invalid folder name"
 msgstr "Ungültiger Ordnername"
 msgstr "Ungültiger Ordnername"
 
 
+#: src/constants/errors/notification.ts:3
+#, fuzzy
+msgid "Invalid notifier config"
+msgstr "Ungültiger 2FA- oder Wiederherstellungscode"
+
 #: src/constants/errors/user.ts:4
 #: src/constants/errors/user.ts:4
 #, fuzzy
 #, fuzzy
 msgid "Invalid otp code"
 msgid "Invalid otp code"
@@ -1919,6 +1957,10 @@ msgstr ""
 msgid "Key Type"
 msgid "Key Type"
 msgstr "Schlüsseltyp"
 msgstr "Schlüsseltyp"
 
 
+#: src/views/preference/components/ExternalNotify/columns.ts:29
+msgid "Language"
+msgstr ""
+
 #: src/views/system/Upgrade.vue:179
 #: src/views/system/Upgrade.vue:179
 msgid "Last checked at"
 msgid "Last checked at"
 msgstr "Zuletzt überprüft am"
 msgstr "Zuletzt überprüft am"
@@ -2024,7 +2066,7 @@ msgstr "Login erfolgreich"
 msgid "Logout successful"
 msgid "Logout successful"
 msgstr "Logout erfolgreich"
 msgstr "Logout erfolgreich"
 
 
-#: src/views/preference/Preference.vue:210
+#: src/views/preference/Preference.vue:217
 msgid "Logrotate"
 msgid "Logrotate"
 msgstr "Logrotate"
 msgstr "Logrotate"
 
 
@@ -2074,7 +2116,7 @@ msgstr ""
 msgid "Manage Configs"
 msgid "Manage Configs"
 msgstr "Verwalte Konfigurationen"
 msgstr "Verwalte Konfigurationen"
 
 
-#: src/routes/modules/sites.ts:10 src/views/site/site_list/SiteList.vue:121
+#: src/routes/modules/sites.ts:10 src/views/site/site_list/SiteList.vue:125
 msgid "Manage Sites"
 msgid "Manage Sites"
 msgstr "Verwalte Seiten"
 msgstr "Verwalte Seiten"
 
 
@@ -2157,7 +2199,7 @@ msgstr "Einzelne Anweisung"
 #: src/views/nginx_log/NginxLogList.vue:37
 #: src/views/nginx_log/NginxLogList.vue:37
 #: src/views/preference/components/AddPasskey.vue:75
 #: src/views/preference/components/AddPasskey.vue:75
 #: src/views/site/ngx_conf/NgxUpstream.vue:177
 #: src/views/site/ngx_conf/NgxUpstream.vue:177
-#: src/views/site/site_edit/RightSettings.vue:64
+#: src/views/site/site_edit/RightSettings.vue:63
 #: src/views/site/site_list/columns.tsx:17
 #: src/views/site/site_list/columns.tsx:17
 #: src/views/site/site_list/SiteDuplicate.vue:79
 #: src/views/site/site_list/SiteDuplicate.vue:79
 #: src/views/stream/components/RightSettings.vue:87
 #: src/views/stream/components/RightSettings.vue:87
@@ -2207,7 +2249,7 @@ msgstr "Neue Version veröffentlicht"
 msgid "Next"
 msgid "Next"
 msgstr "Nächster"
 msgstr "Nächster"
 
 
-#: src/views/preference/Preference.vue:198
+#: src/views/preference/Preference.vue:205
 msgid "Nginx"
 msgid "Nginx"
 msgstr ""
 msgstr ""
 
 
@@ -2351,7 +2393,7 @@ msgstr "Name der Konfiguration"
 #: src/views/preference/CertSettings.vue:73
 #: src/views/preference/CertSettings.vue:73
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:97
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:97
 #: src/views/site/ngx_conf/LocationEditor.vue:88
 #: src/views/site/ngx_conf/LocationEditor.vue:88
-#: src/views/site/site_list/SiteList.vue:161
+#: src/views/site/site_list/SiteList.vue:165
 #: src/views/stream/StreamList.vue:225
 #: src/views/stream/StreamList.vue:225
 msgid "No"
 msgid "No"
 msgstr "Nein"
 msgstr "Nein"
@@ -2366,12 +2408,12 @@ msgstr "Aktion"
 msgid "No records selected"
 msgid "No records selected"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/Preference.vue:168
+#: src/views/preference/Preference.vue:175
 #, fuzzy
 #, fuzzy
 msgid "Node"
 msgid "Node"
 msgstr "Benuztername"
 msgstr "Benuztername"
 
 
-#: src/views/site/site_edit/RightSettings.vue:67
+#: src/views/site/site_edit/RightSettings.vue:66
 #: src/views/site/site_list/columns.tsx:63
 #: src/views/site/site_list/columns.tsx:63
 #: src/views/stream/components/RightSettings.vue:90
 #: src/views/stream/components/RightSettings.vue:90
 #: src/views/stream/StreamList.vue:30
 #: src/views/stream/StreamList.vue:30
@@ -2416,7 +2458,7 @@ msgstr "Nich gültig vor: %{date}"
 msgid "Note"
 msgid "Note"
 msgstr "Notiz"
 msgstr "Notiz"
 
 
-#: src/views/site/site_edit/RightSettings.vue:96
+#: src/views/site/site_edit/RightSettings.vue:95
 #: src/views/stream/components/RightSettings.vue:118
 #: src/views/stream/components/RightSettings.vue:118
 msgid ""
 msgid ""
 "Note, if the configuration file include other configurations or "
 "Note, if the configuration file include other configurations or "
@@ -2437,6 +2479,11 @@ msgstr "Zertifikat ist gültig"
 msgid "Notifications"
 msgid "Notifications"
 msgstr "Zertifikat ist gültig"
 msgstr "Zertifikat ist gültig"
 
 
+#: src/constants/errors/notification.ts:2
+#, fuzzy
+msgid "Notifier not found"
+msgstr "File Not Found"
+
 #: src/views/site/cert/components/ObtainCert.vue:182
 #: src/views/site/cert/components/ObtainCert.vue:182
 #, fuzzy
 #, fuzzy
 msgid "Obtain certificate"
 msgid "Obtain certificate"
@@ -2482,7 +2529,7 @@ msgstr "OK"
 #: src/views/site/ngx_conf/NgxServer.vue:79
 #: src/views/site/ngx_conf/NgxServer.vue:79
 #: src/views/site/ngx_conf/NgxUpstream.vue:33
 #: src/views/site/ngx_conf/NgxUpstream.vue:33
 #: src/views/site/site_edit/components/SiteStatusSegmented.vue:121
 #: src/views/site/site_edit/components/SiteStatusSegmented.vue:121
-#: src/views/site/site_list/SiteList.vue:162
+#: src/views/site/site_list/SiteList.vue:166
 #: src/views/stream/components/RightSettings.vue:54
 #: src/views/stream/components/RightSettings.vue:54
 #: src/views/stream/StreamList.vue:226
 #: src/views/stream/StreamList.vue:226
 #: src/views/system/Backup/BackupCreator.vue:149
 #: src/views/system/Backup/BackupCreator.vue:149
@@ -2506,7 +2553,7 @@ msgstr ""
 msgid "Only zip files are allowed"
 msgid "Only zip files are allowed"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/Preference.vue:204
+#: src/views/preference/Preference.vue:211
 msgid "OpenAI"
 msgid "OpenAI"
 msgstr ""
 msgstr ""
 
 
@@ -2658,7 +2705,7 @@ msgstr ""
 "Anmeldeinformationen hinzu und wähle dann eine der unten aufgeführten "
 "Anmeldeinformationen hinzu und wähle dann eine der unten aufgeführten "
 "Anmeldeinformationen aus, um die API des DNS-Anbieters anzufordern."
 "Anmeldeinformationen aus, um die API des DNS-Anbieters anzufordern."
 
 
-#: src/components/Notification/notifications.ts:138
+#: src/components/Notification/notifications.ts:156
 #: src/language/constants.ts:59
 #: src/language/constants.ts:59
 msgid ""
 msgid ""
 "Please generate new recovery codes in the preferences immediately to prevent "
 "Please generate new recovery codes in the preferences immediately to prevent "
@@ -2756,7 +2803,7 @@ msgstr "Aktionen"
 msgid "Pre-release"
 msgid "Pre-release"
 msgstr "Vorabversion"
 msgstr "Vorabversion"
 
 
-#: src/routes/modules/preference.ts:10 src/views/preference/Preference.vue:151
+#: src/routes/modules/preference.ts:10 src/views/preference/Preference.vue:152
 msgid "Preference"
 msgid "Preference"
 msgstr "Einstellungen"
 msgstr "Einstellungen"
 
 
@@ -2898,22 +2945,22 @@ msgstr "Neu laden"
 msgid "Reload Nginx"
 msgid "Reload Nginx"
 msgstr "Lade Nginx neu"
 msgstr "Lade Nginx neu"
 
 
-#: src/components/Notification/notifications.ts:144
+#: src/components/Notification/notifications.ts:10
 #, fuzzy
 #, fuzzy
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgstr "Speichern erfolgreich"
 msgstr "Speichern erfolgreich"
 
 
-#: src/components/Notification/notifications.ts:148
+#: src/components/Notification/notifications.ts:14
 #, fuzzy
 #, fuzzy
 msgid "Reload Nginx on %{node} successfully"
 msgid "Reload Nginx on %{node} successfully"
 msgstr "Speichern erfolgreich"
 msgstr "Speichern erfolgreich"
 
 
-#: src/components/Notification/notifications.ts:143
+#: src/components/Notification/notifications.ts:9
 #, fuzzy
 #, fuzzy
 msgid "Reload Remote Nginx Error"
 msgid "Reload Remote Nginx Error"
 msgstr "Zertifikat ist gültig"
 msgstr "Zertifikat ist gültig"
 
 
-#: src/components/Notification/notifications.ts:147
+#: src/components/Notification/notifications.ts:13
 #, fuzzy
 #, fuzzy
 msgid "Reload Remote Nginx Success"
 msgid "Reload Remote Nginx Success"
 msgstr "Zertifikat ist gültig"
 msgstr "Zertifikat ist gültig"
@@ -2955,62 +3002,62 @@ msgstr "Speichern erfolgreich"
 msgid "Rename"
 msgid "Rename"
 msgstr "Benuztername"
 msgstr "Benuztername"
 
 
-#: src/components/Notification/notifications.ts:28
+#: src/components/Notification/notifications.ts:46
 #, fuzzy
 #, fuzzy
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} failed"
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} failed"
 msgstr "Speichern erfolgreich"
 msgstr "Speichern erfolgreich"
 
 
-#: src/components/Notification/notifications.ts:32
+#: src/components/Notification/notifications.ts:50
 #, fuzzy
 #, fuzzy
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} successfully"
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} successfully"
 msgstr "Speichern erfolgreich"
 msgstr "Speichern erfolgreich"
 
 
-#: src/components/Notification/notifications.ts:27 src/language/constants.ts:42
+#: src/components/Notification/notifications.ts:45 src/language/constants.ts:42
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Config Error"
 msgid "Rename Remote Config Error"
 msgstr "Zertifikat ist gültig"
 msgstr "Zertifikat ist gültig"
 
 
-#: src/components/Notification/notifications.ts:31 src/language/constants.ts:41
+#: src/components/Notification/notifications.ts:49 src/language/constants.ts:41
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Config Success"
 msgid "Rename Remote Config Success"
 msgstr "Zertifikat ist gültig"
 msgstr "Zertifikat ist gültig"
 
 
-#: src/components/Notification/notifications.ts:77 src/language/constants.ts:56
+#: src/components/Notification/notifications.ts:95 src/language/constants.ts:56
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Site Error"
 msgid "Rename Remote Site Error"
 msgstr "Zertifikat ist gültig"
 msgstr "Zertifikat ist gültig"
 
 
-#: src/components/Notification/notifications.ts:81 src/language/constants.ts:55
+#: src/components/Notification/notifications.ts:99 src/language/constants.ts:55
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Site Success"
 msgid "Rename Remote Site Success"
 msgstr "Zertifikat ist gültig"
 msgstr "Zertifikat ist gültig"
 
 
-#: src/components/Notification/notifications.ts:119
+#: src/components/Notification/notifications.ts:137
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Stream Error"
 msgid "Rename Remote Stream Error"
 msgstr "Zertifikat ist gültig"
 msgstr "Zertifikat ist gültig"
 
 
-#: src/components/Notification/notifications.ts:123
+#: src/components/Notification/notifications.ts:141
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Stream Success"
 msgid "Rename Remote Stream Success"
 msgstr "Zertifikat ist gültig"
 msgstr "Zertifikat ist gültig"
 
 
-#: src/components/Notification/notifications.ts:78
+#: src/components/Notification/notifications.ts:96
 #, fuzzy
 #, fuzzy
 msgid "Rename site %{name} to %{new_name} on %{node} failed"
 msgid "Rename site %{name} to %{new_name} on %{node} failed"
 msgstr "Speichern erfolgreich"
 msgstr "Speichern erfolgreich"
 
 
-#: src/components/Notification/notifications.ts:82
+#: src/components/Notification/notifications.ts:100
 #, fuzzy
 #, fuzzy
 msgid "Rename site %{name} to %{new_name} on %{node} successfully"
 msgid "Rename site %{name} to %{new_name} on %{node} successfully"
 msgstr "Speichern erfolgreich"
 msgstr "Speichern erfolgreich"
 
 
-#: src/components/Notification/notifications.ts:120
+#: src/components/Notification/notifications.ts:138
 #, fuzzy
 #, fuzzy
 msgid "Rename stream %{name} to %{new_name} on %{node} failed"
 msgid "Rename stream %{name} to %{new_name} on %{node} failed"
 msgstr "Speichern erfolgreich"
 msgstr "Speichern erfolgreich"
 
 
-#: src/components/Notification/notifications.ts:124
+#: src/components/Notification/notifications.ts:142
 #, fuzzy
 #, fuzzy
 msgid "Rename stream %{name} to %{new_name} on %{node} successfully"
 msgid "Rename stream %{name} to %{new_name} on %{node} successfully"
 msgstr "Speichern erfolgreich"
 msgstr "Speichern erfolgreich"
@@ -3076,22 +3123,22 @@ msgstr "Neustart"
 msgid "Restart Nginx"
 msgid "Restart Nginx"
 msgstr "Starte neu"
 msgstr "Starte neu"
 
 
-#: src/components/Notification/notifications.ts:152
+#: src/components/Notification/notifications.ts:18
 #, fuzzy
 #, fuzzy
 msgid "Restart Nginx on %{node} failed, response: %{resp}"
 msgid "Restart Nginx on %{node} failed, response: %{resp}"
 msgstr "Erfolgreich gespeichert"
 msgstr "Erfolgreich gespeichert"
 
 
-#: src/components/Notification/notifications.ts:156
+#: src/components/Notification/notifications.ts:22
 #, fuzzy
 #, fuzzy
 msgid "Restart Nginx on %{node} successfully"
 msgid "Restart Nginx on %{node} successfully"
 msgstr "Speichern erfolgreich"
 msgstr "Speichern erfolgreich"
 
 
-#: src/components/Notification/notifications.ts:151
+#: src/components/Notification/notifications.ts:17
 #, fuzzy
 #, fuzzy
 msgid "Restart Remote Nginx Error"
 msgid "Restart Remote Nginx Error"
 msgstr "Zertifikat ist gültig"
 msgstr "Zertifikat ist gültig"
 
 
-#: src/components/Notification/notifications.ts:155
+#: src/components/Notification/notifications.ts:21
 #, fuzzy
 #, fuzzy
 msgid "Restart Remote Nginx Success"
 msgid "Restart Remote Nginx Success"
 msgstr "Zertifikat ist gültig"
 msgstr "Zertifikat ist gültig"
@@ -3159,7 +3206,7 @@ msgstr "Arbeite"
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/ConfigEditor.vue:271
 #: src/views/config/ConfigEditor.vue:271
 #: src/views/preference/components/Passkey.vue:130
 #: src/views/preference/components/Passkey.vue:130
-#: src/views/preference/Preference.vue:221
+#: src/views/preference/Preference.vue:228
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:127
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:127
 #: src/views/site/site_edit/components/ConfigName.vue:52
 #: src/views/site/site_edit/components/ConfigName.vue:52
 #: src/views/site/site_edit/SiteEdit.vue:292
 #: src/views/site/site_edit/SiteEdit.vue:292
@@ -3177,42 +3224,44 @@ msgstr "Anweisung speichern"
 msgid "Save error %{msg}"
 msgid "Save error %{msg}"
 msgstr "Fehler beim Speichern %{msg}"
 msgstr "Fehler beim Speichern %{msg}"
 
 
-#: src/components/Notification/notifications.ts:85 src/language/constants.ts:48
+#: src/components/Notification/notifications.ts:103
+#: src/language/constants.ts:48
 #, fuzzy
 #, fuzzy
 msgid "Save Remote Site Error"
 msgid "Save Remote Site Error"
 msgstr "Zertifikat ist gültig"
 msgstr "Zertifikat ist gültig"
 
 
-#: src/components/Notification/notifications.ts:89 src/language/constants.ts:47
+#: src/components/Notification/notifications.ts:107
+#: src/language/constants.ts:47
 #, fuzzy
 #, fuzzy
 msgid "Save Remote Site Success"
 msgid "Save Remote Site Success"
 msgstr "Zertifikat ist gültig"
 msgstr "Zertifikat ist gültig"
 
 
-#: src/components/Notification/notifications.ts:127
+#: src/components/Notification/notifications.ts:145
 #, fuzzy
 #, fuzzy
 msgid "Save Remote Stream Error"
 msgid "Save Remote Stream Error"
 msgstr "Zertifikat ist gültig"
 msgstr "Zertifikat ist gültig"
 
 
-#: src/components/Notification/notifications.ts:131
+#: src/components/Notification/notifications.ts:149
 #, fuzzy
 #, fuzzy
 msgid "Save Remote Stream Success"
 msgid "Save Remote Stream Success"
 msgstr "Zertifikat ist gültig"
 msgstr "Zertifikat ist gültig"
 
 
-#: src/components/Notification/notifications.ts:86
+#: src/components/Notification/notifications.ts:104
 #, fuzzy
 #, fuzzy
 msgid "Save site %{name} to %{node} failed"
 msgid "Save site %{name} to %{node} failed"
 msgstr "Speichern erfolgreich"
 msgstr "Speichern erfolgreich"
 
 
-#: src/components/Notification/notifications.ts:90
+#: src/components/Notification/notifications.ts:108
 #, fuzzy
 #, fuzzy
 msgid "Save site %{name} to %{node} successfully"
 msgid "Save site %{name} to %{node} successfully"
 msgstr "Speichern erfolgreich"
 msgstr "Speichern erfolgreich"
 
 
-#: src/components/Notification/notifications.ts:128
+#: src/components/Notification/notifications.ts:146
 #, fuzzy
 #, fuzzy
 msgid "Save stream %{name} to %{node} failed"
 msgid "Save stream %{name} to %{node} failed"
 msgstr "Ausführen von %{conf_name} auf %{node_name} fehlgeschlagen"
 msgstr "Ausführen von %{conf_name} auf %{node_name} fehlgeschlagen"
 
 
-#: src/components/Notification/notifications.ts:132
+#: src/components/Notification/notifications.ts:150
 #, fuzzy
 #, fuzzy
 msgid "Save stream %{name} to %{node} successfully"
 msgid "Save stream %{name} to %{node} successfully"
 msgstr "Speichern erfolgreich"
 msgstr "Speichern erfolgreich"
@@ -3220,7 +3269,7 @@ msgstr "Speichern erfolgreich"
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:47
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:47
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:97
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:97
 #: src/views/certificate/CertificateEditor.vue:49
 #: src/views/certificate/CertificateEditor.vue:49
-#: src/views/preference/Preference.vue:123
+#: src/views/preference/Preference.vue:124
 #, fuzzy
 #, fuzzy
 msgid "Save successfully"
 msgid "Save successfully"
 msgstr "Speichern erfolgreich"
 msgstr "Speichern erfolgreich"
@@ -3242,6 +3291,10 @@ msgstr ""
 msgid "SDK"
 msgid "SDK"
 msgstr "SDK"
 msgstr "SDK"
 
 
+#: src/views/preference/components/ExternalNotify/dingtalk.ts:13
+msgid "Secret (Optional)"
+msgstr ""
+
 #: src/views/preference/components/TOTP.vue:109
 #: src/views/preference/components/TOTP.vue:109
 msgid "Secret has been copied"
 msgid "Secret has been copied"
 msgstr "Schlüssel wurde kopiert"
 msgstr "Schlüssel wurde kopiert"
@@ -3273,7 +3326,7 @@ msgstr ""
 msgid "Send"
 msgid "Send"
 msgstr "Senden"
 msgstr "Senden"
 
 
-#: src/views/preference/Preference.vue:156
+#: src/views/preference/Preference.vue:157
 #, fuzzy
 #, fuzzy
 msgid "Server"
 msgid "Server"
 msgstr "Serverinformationen"
 msgstr "Serverinformationen"
@@ -3282,6 +3335,11 @@ msgstr "Serverinformationen"
 msgid "Server Info"
 msgid "Server Info"
 msgstr "Serverinformationen"
 msgstr "Serverinformationen"
 
 
+#: src/views/preference/components/ExternalNotify/bark.ts:13
+#, fuzzy
+msgid "Server URL"
+msgstr "Serverinformationen"
+
 #: src/views/site/cert/components/ObtainCert.vue:107
 #: src/views/site/cert/components/ObtainCert.vue:107
 msgid "server_name not found in directives"
 msgid "server_name not found in directives"
 msgstr "server_name wurde in den Anweisungen nicht gefunden"
 msgstr "server_name wurde in den Anweisungen nicht gefunden"
@@ -3463,7 +3521,7 @@ msgstr ""
 #: src/views/certificate/ACMEUser.vue:65
 #: src/views/certificate/ACMEUser.vue:65
 #: src/views/certificate/CertificateList/certColumns.tsx:65
 #: src/views/certificate/CertificateList/certColumns.tsx:65
 #: src/views/environments/list/envColumns.tsx:44
 #: src/views/environments/list/envColumns.tsx:44
-#: src/views/site/site_edit/RightSettings.vue:56
+#: src/views/site/site_edit/RightSettings.vue:55
 #: src/views/site/site_list/columns.tsx:80 src/views/stream/StreamList.vue:47
 #: src/views/site/site_list/columns.tsx:80 src/views/stream/StreamList.vue:47
 msgid "Status"
 msgid "Status"
 msgstr "Status"
 msgstr "Status"
@@ -3539,42 +3597,42 @@ msgstr "Synchronisieren"
 msgid "Sync Certificate"
 msgid "Sync Certificate"
 msgstr "Zertifikat ist gültig"
 msgstr "Zertifikat ist gültig"
 
 
-#: src/components/Notification/notifications.ts:10
+#: src/components/Notification/notifications.ts:28
 #, fuzzy
 #, fuzzy
 msgid "Sync Certificate %{cert_name} to %{env_name} failed"
 msgid "Sync Certificate %{cert_name} to %{env_name} failed"
 msgstr "Speichern erfolgreich"
 msgstr "Speichern erfolgreich"
 
 
-#: src/components/Notification/notifications.ts:14
+#: src/components/Notification/notifications.ts:32
 #, fuzzy
 #, fuzzy
 msgid "Sync Certificate %{cert_name} to %{env_name} successfully"
 msgid "Sync Certificate %{cert_name} to %{env_name} successfully"
 msgstr "Speichern erfolgreich"
 msgstr "Speichern erfolgreich"
 
 
-#: src/components/Notification/notifications.ts:9 src/language/constants.ts:39
+#: src/components/Notification/notifications.ts:27 src/language/constants.ts:39
 #, fuzzy
 #, fuzzy
 msgid "Sync Certificate Error"
 msgid "Sync Certificate Error"
 msgstr "Zertifikat ist gültig"
 msgstr "Zertifikat ist gültig"
 
 
-#: src/components/Notification/notifications.ts:13 src/language/constants.ts:38
+#: src/components/Notification/notifications.ts:31 src/language/constants.ts:38
 #, fuzzy
 #, fuzzy
 msgid "Sync Certificate Success"
 msgid "Sync Certificate Success"
 msgstr "Zertifikat ist gültig"
 msgstr "Zertifikat ist gültig"
 
 
-#: src/components/Notification/notifications.ts:20
+#: src/components/Notification/notifications.ts:38
 #, fuzzy
 #, fuzzy
 msgid "Sync config %{config_name} to %{env_name} failed"
 msgid "Sync config %{config_name} to %{env_name} failed"
 msgstr "Speichern erfolgreich"
 msgstr "Speichern erfolgreich"
 
 
-#: src/components/Notification/notifications.ts:24
+#: src/components/Notification/notifications.ts:42
 #, fuzzy
 #, fuzzy
 msgid "Sync config %{config_name} to %{env_name} successfully"
 msgid "Sync config %{config_name} to %{env_name} successfully"
 msgstr "Speichern erfolgreich"
 msgstr "Speichern erfolgreich"
 
 
-#: src/components/Notification/notifications.ts:19 src/language/constants.ts:45
+#: src/components/Notification/notifications.ts:37 src/language/constants.ts:45
 #, fuzzy
 #, fuzzy
 msgid "Sync Config Error"
 msgid "Sync Config Error"
 msgstr "Zertifikat ist gültig"
 msgstr "Zertifikat ist gültig"
 
 
-#: src/components/Notification/notifications.ts:23 src/language/constants.ts:44
+#: src/components/Notification/notifications.ts:41 src/language/constants.ts:44
 #, fuzzy
 #, fuzzy
 msgid "Sync Config Success"
 msgid "Sync Config Success"
 msgstr "Zertifikat ist gültig"
 msgstr "Zertifikat ist gültig"
@@ -3584,8 +3642,8 @@ msgstr "Zertifikat ist gültig"
 msgid "Sync Nodes"
 msgid "Sync Nodes"
 msgstr "Synchrone Knoten"
 msgstr "Synchrone Knoten"
 
 
-#: src/views/site/site_edit/RightSettings.vue:102
-#: src/views/site/site_edit/RightSettings.vue:89
+#: src/views/site/site_edit/RightSettings.vue:101
+#: src/views/site/site_edit/RightSettings.vue:88
 #: src/views/stream/components/RightSettings.vue:111
 #: src/views/stream/components/RightSettings.vue:111
 #: src/views/stream/components/RightSettings.vue:124
 #: src/views/stream/components/RightSettings.vue:124
 #, fuzzy
 #, fuzzy
@@ -3596,7 +3654,7 @@ msgstr "Zertifikat ist gültig"
 msgid "Sync to"
 msgid "Sync to"
 msgstr "Synchronisieren mit"
 msgstr "Synchronisieren mit"
 
 
-#: src/views/site/site_edit/RightSettings.vue:86
+#: src/views/site/site_edit/RightSettings.vue:85
 #: src/views/stream/components/RightSettings.vue:108
 #: src/views/stream/components/RightSettings.vue:108
 msgid "Synchronization"
 msgid "Synchronization"
 msgstr "Synchronisation"
 msgstr "Synchronisation"
@@ -3629,7 +3687,11 @@ msgstr "Speichern erfolgreich"
 msgid "Task not found"
 msgid "Task not found"
 msgstr "File Not Found"
 msgstr "File Not Found"
 
 
-#: src/routes/modules/terminal.ts:10 src/views/preference/Preference.vue:180
+#: src/views/preference/components/ExternalNotify/telegram.ts:5
+msgid "Telegram"
+msgstr ""
+
+#: src/routes/modules/terminal.ts:10 src/views/preference/Preference.vue:187
 #: src/views/terminal/Terminal.vue:129
 #: src/views/terminal/Terminal.vue:129
 msgid "Terminal"
 msgid "Terminal"
 msgstr "Terminal"
 msgstr "Terminal"
@@ -3902,6 +3964,7 @@ msgstr "Zwei-Faktor-Authentifizierung erforderlich"
 #: src/views/certificate/CertificateList/certColumns.tsx:25
 #: src/views/certificate/CertificateList/certColumns.tsx:25
 #: src/views/nginx_log/NginxLogList.vue:21
 #: src/views/nginx_log/NginxLogList.vue:21
 #: src/views/notification/notificationColumns.tsx:9
 #: src/views/notification/notificationColumns.tsx:9
+#: src/views/preference/components/ExternalNotify/columns.ts:17
 msgid "Type"
 msgid "Type"
 msgstr "Typ"
 msgstr "Typ"
 
 
@@ -3919,7 +3982,7 @@ msgstr "Speichern erfolgreich"
 #: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:325
 #: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:325
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/environments/list/envColumns.tsx:90
-#: src/views/site/site_edit/RightSettings.vue:76
+#: src/views/site/site_edit/RightSettings.vue:75
 #: src/views/site/site_list/columns.tsx:110
 #: src/views/site/site_list/columns.tsx:110
 #: src/views/stream/components/RightSettings.vue:99
 #: src/views/stream/components/RightSettings.vue:99
 #: src/views/stream/StreamList.vue:67 src/views/user/userColumns.tsx:54
 #: src/views/stream/StreamList.vue:67 src/views/user/userColumns.tsx:54
@@ -4091,7 +4154,7 @@ msgstr ""
 "denn, du befindest dich in einer Entwicklerumgebung und verwendest Pebble "
 "denn, du befindest dich in einer Entwicklerumgebung und verwendest Pebble "
 "als CA."
 "als CA."
 
 
-#: src/views/site/site_edit/RightSettings.vue:92
+#: src/views/site/site_edit/RightSettings.vue:91
 #, fuzzy
 #, fuzzy
 msgid ""
 msgid ""
 "When you enable/disable, delete, or save this site, the nodes set in the "
 "When you enable/disable, delete, or save this site, the nodes set in the "

+ 164 - 102
app/src/language/en/app.po

@@ -31,6 +31,11 @@ msgstr "Sites List"
 msgid "Access Logs"
 msgid "Access Logs"
 msgstr "Sites List"
 msgstr "Sites List"
 
 
+#: src/views/preference/components/ExternalNotify/dingtalk.ts:9
+#, fuzzy
+msgid "Access Token"
+msgstr "Sites List"
+
 #: src/routes/modules/certificates.ts:20 src/views/certificate/ACMEUser.vue:113
 #: src/routes/modules/certificates.ts:20 src/views/certificate/ACMEUser.vue:113
 #: src/views/certificate/ACMEUserSelector.vue:85
 #: src/views/certificate/ACMEUserSelector.vue:85
 #, fuzzy
 #, fuzzy
@@ -46,6 +51,7 @@ msgstr "Username"
 #: src/views/nginx_log/NginxLogList.vue:53
 #: src/views/nginx_log/NginxLogList.vue:53
 #: src/views/notification/notificationColumns.tsx:66
 #: src/views/notification/notificationColumns.tsx:66
 #: src/views/preference/AuthSettings.vue:30
 #: src/views/preference/AuthSettings.vue:30
+#: src/views/preference/components/ExternalNotify/columns.ts:46
 #: src/views/site/site_list/columns.tsx:117 src/views/stream/StreamList.vue:74
 #: src/views/site/site_list/columns.tsx:117 src/views/stream/StreamList.vue:74
 #: src/views/user/userColumns.tsx:60
 #: src/views/user/userColumns.tsx:60
 msgid "Action"
 msgid "Action"
@@ -114,7 +120,7 @@ msgstr ""
 msgid "All"
 msgid "All"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:137
+#: src/components/Notification/notifications.ts:155
 #: src/language/constants.ts:58
 #: src/language/constants.ts:58
 msgid "All Recovery Codes Have Been Used"
 msgid "All Recovery Codes Have Been Used"
 msgstr ""
 msgstr ""
@@ -140,7 +146,7 @@ msgstr ""
 msgid "API Type"
 msgid "API Type"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/Preference.vue:162
+#: src/views/preference/Preference.vue:163
 msgid "App"
 msgid "App"
 msgstr ""
 msgstr ""
 
 
@@ -203,7 +209,7 @@ msgstr "Are you sure you want to remove this directive?"
 msgid "Are you sure you want to delete this item?"
 msgid "Are you sure you want to delete this item?"
 msgstr "Are you sure you want to remove this directive?"
 msgstr "Are you sure you want to remove this directive?"
 
 
-#: src/views/site/site_list/SiteList.vue:163
+#: src/views/site/site_list/SiteList.vue:167
 #: src/views/stream/StreamList.vue:227
 #: src/views/stream/StreamList.vue:227
 #, fuzzy
 #, fuzzy
 msgid "Are you sure you want to delete?"
 msgid "Are you sure you want to delete?"
@@ -254,7 +260,7 @@ msgstr ""
 msgid "Attempts"
 msgid "Attempts"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/Preference.vue:186
+#: src/views/preference/Preference.vue:193
 msgid "Auth"
 msgid "Auth"
 msgstr ""
 msgstr ""
 
 
@@ -339,12 +345,16 @@ msgstr ""
 msgid "Banned Until"
 msgid "Banned Until"
 msgstr ""
 msgstr ""
 
 
+#: src/views/preference/components/ExternalNotify/bark.ts:5
+msgid "Bark"
+msgstr ""
+
 #: src/views/site/site_add/SiteAdd.vue:95
 #: src/views/site/site_add/SiteAdd.vue:95
 msgid "Base information"
 msgid "Base information"
 msgstr "Base information"
 msgstr "Base information"
 
 
 #: src/views/config/ConfigEditor.vue:290
 #: src/views/config/ConfigEditor.vue:290
-#: src/views/site/site_edit/RightSettings.vue:53
+#: src/views/site/site_edit/RightSettings.vue:52
 #: src/views/stream/components/RightSettings.vue:79
 #: src/views/stream/components/RightSettings.vue:79
 #, fuzzy
 #, fuzzy
 msgid "Basic"
 msgid "Basic"
@@ -378,6 +388,10 @@ msgstr ""
 msgid "Block is nil"
 msgid "Block is nil"
 msgstr ""
 msgstr ""
 
 
+#: src/views/preference/components/ExternalNotify/telegram.ts:9
+msgid "Bot Token"
+msgstr ""
+
 #: src/views/system/About.vue:55
 #: src/views/system/About.vue:55
 msgid "Build with"
 msgid "Build with"
 msgstr "Build with"
 msgstr "Build with"
@@ -417,7 +431,7 @@ msgstr ""
 msgid "Cannot remove initial user"
 msgid "Cannot remove initial user"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/Preference.vue:192
+#: src/views/preference/Preference.vue:199
 msgid "Cert"
 msgid "Cert"
 msgstr ""
 msgstr ""
 
 
@@ -496,6 +510,10 @@ msgstr "Certificate is valid"
 msgid "Channel"
 msgid "Channel"
 msgstr ""
 msgstr ""
 
 
+#: src/views/preference/components/ExternalNotify/telegram.ts:13
+msgid "Chat ID"
+msgstr ""
+
 #: src/views/system/Upgrade.vue:185
 #: src/views/system/Upgrade.vue:185
 msgid "Check again"
 msgid "Check again"
 msgstr ""
 msgstr ""
@@ -696,6 +714,7 @@ msgstr ""
 
 
 #: src/views/environments/group/columns.ts:31
 #: src/views/environments/group/columns.ts:31
 #: src/views/notification/notificationColumns.tsx:59
 #: src/views/notification/notificationColumns.tsx:59
+#: src/views/preference/components/ExternalNotify/columns.ts:41
 #: src/views/preference/components/Passkey.vue:95
 #: src/views/preference/components/Passkey.vue:95
 #: src/views/user/userColumns.tsx:48
 #: src/views/user/userColumns.tsx:48
 msgid "Created at"
 msgid "Created at"
@@ -768,7 +787,7 @@ msgstr "Enable failed"
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/views/site/ngx_conf/NgxServer.vue:110
 #: src/views/site/ngx_conf/NgxServer.vue:110
 #: src/views/site/ngx_conf/NgxUpstream.vue:128
 #: src/views/site/ngx_conf/NgxUpstream.vue:128
-#: src/views/site/site_list/SiteList.vue:172
+#: src/views/site/site_list/SiteList.vue:176
 #: src/views/stream/StreamList.vue:236
 #: src/views/stream/StreamList.vue:236
 msgid "Delete"
 msgid "Delete"
 msgstr ""
 msgstr ""
@@ -778,46 +797,46 @@ msgstr ""
 msgid "Delete Permanently"
 msgid "Delete Permanently"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:37 src/language/constants.ts:50
+#: src/components/Notification/notifications.ts:55 src/language/constants.ts:50
 #, fuzzy
 #, fuzzy
 msgid "Delete Remote Site Error"
 msgid "Delete Remote Site Error"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
 
 
-#: src/components/Notification/notifications.ts:41 src/language/constants.ts:49
+#: src/components/Notification/notifications.ts:59 src/language/constants.ts:49
 #, fuzzy
 #, fuzzy
 msgid "Delete Remote Site Success"
 msgid "Delete Remote Site Success"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
 
 
-#: src/components/Notification/notifications.ts:95
+#: src/components/Notification/notifications.ts:113
 #, fuzzy
 #, fuzzy
 msgid "Delete Remote Stream Error"
 msgid "Delete Remote Stream Error"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
 
 
-#: src/components/Notification/notifications.ts:99
+#: src/components/Notification/notifications.ts:117
 #, fuzzy
 #, fuzzy
 msgid "Delete Remote Stream Success"
 msgid "Delete Remote Stream Success"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
 
 
-#: src/components/Notification/notifications.ts:38
+#: src/components/Notification/notifications.ts:56
 #, fuzzy
 #, fuzzy
 msgid "Delete site %{name} from %{node} failed"
 msgid "Delete site %{name} from %{node} failed"
 msgstr "Saved successfully"
 msgstr "Saved successfully"
 
 
-#: src/components/Notification/notifications.ts:42
+#: src/components/Notification/notifications.ts:60
 #, fuzzy
 #, fuzzy
 msgid "Delete site %{name} from %{node} successfully"
 msgid "Delete site %{name} from %{node} successfully"
 msgstr "Saved successfully"
 msgstr "Saved successfully"
 
 
-#: src/views/site/site_list/SiteList.vue:94
+#: src/views/site/site_list/SiteList.vue:98
 msgid "Delete site: %{site_name}"
 msgid "Delete site: %{site_name}"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:96
+#: src/components/Notification/notifications.ts:114
 #, fuzzy
 #, fuzzy
 msgid "Delete stream %{name} from %{node} failed"
 msgid "Delete stream %{name} from %{node} failed"
 msgstr "Saved successfully"
 msgstr "Saved successfully"
 
 
-#: src/components/Notification/notifications.ts:100
+#: src/components/Notification/notifications.ts:118
 #, fuzzy
 #, fuzzy
 msgid "Delete stream %{name} from %{node} successfully"
 msgid "Delete stream %{name} from %{node} successfully"
 msgstr "Saved successfully"
 msgstr "Saved successfully"
@@ -856,6 +875,14 @@ msgstr ""
 msgid "Development Mode"
 msgid "Development Mode"
 msgstr "Development Mode"
 msgstr "Development Mode"
 
 
+#: src/views/preference/components/ExternalNotify/bark.ts:9
+msgid "Device Key"
+msgstr ""
+
+#: src/views/preference/components/ExternalNotify/dingtalk.ts:5
+msgid "DingTalk"
+msgstr ""
+
 #: src/views/site/ngx_conf/directive/DirectiveAdd.vue:89
 #: src/views/site/ngx_conf/directive/DirectiveAdd.vue:89
 msgid "Directive"
 msgid "Directive"
 msgstr "Directive"
 msgstr "Directive"
@@ -890,62 +917,62 @@ msgstr "Disabled"
 msgid "Disable auto-renewal failed for %{name}"
 msgid "Disable auto-renewal failed for %{name}"
 msgstr "Disable auto-renewal failed for %{name}"
 msgstr "Disable auto-renewal failed for %{name}"
 
 
-#: src/components/Notification/notifications.ts:45 src/language/constants.ts:52
+#: src/components/Notification/notifications.ts:63 src/language/constants.ts:52
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Site Error"
 msgid "Disable Remote Site Error"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
 
 
-#: src/components/Notification/notifications.ts:69
+#: src/components/Notification/notifications.ts:87
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Site Maintenance Error"
 msgid "Disable Remote Site Maintenance Error"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
 
 
-#: src/components/Notification/notifications.ts:73
+#: src/components/Notification/notifications.ts:91
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Site Maintenance Success"
 msgid "Disable Remote Site Maintenance Success"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
 
 
-#: src/components/Notification/notifications.ts:49 src/language/constants.ts:51
+#: src/components/Notification/notifications.ts:67 src/language/constants.ts:51
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Site Success"
 msgid "Disable Remote Site Success"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
 
 
-#: src/components/Notification/notifications.ts:103
+#: src/components/Notification/notifications.ts:121
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Stream Error"
 msgid "Disable Remote Stream Error"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
 
 
-#: src/components/Notification/notifications.ts:107
+#: src/components/Notification/notifications.ts:125
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Stream Success"
 msgid "Disable Remote Stream Success"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
 
 
-#: src/components/Notification/notifications.ts:46
+#: src/components/Notification/notifications.ts:64
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} from %{node} failed"
 msgid "Disable site %{name} from %{node} failed"
 msgstr "Saved successfully"
 msgstr "Saved successfully"
 
 
-#: src/components/Notification/notifications.ts:50
+#: src/components/Notification/notifications.ts:68
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} from %{node} successfully"
 msgid "Disable site %{name} from %{node} successfully"
 msgstr "Saved successfully"
 msgstr "Saved successfully"
 
 
-#: src/components/Notification/notifications.ts:70
+#: src/components/Notification/notifications.ts:88
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} maintenance on %{node} failed"
 msgid "Disable site %{name} maintenance on %{node} failed"
 msgstr "Saved successfully"
 msgstr "Saved successfully"
 
 
-#: src/components/Notification/notifications.ts:74
+#: src/components/Notification/notifications.ts:92
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} maintenance on %{node} successfully"
 msgid "Disable site %{name} maintenance on %{node} successfully"
 msgstr "Saved successfully"
 msgstr "Saved successfully"
 
 
-#: src/components/Notification/notifications.ts:104
+#: src/components/Notification/notifications.ts:122
 #, fuzzy
 #, fuzzy
 msgid "Disable stream %{name} from %{node} failed"
 msgid "Disable stream %{name} from %{node} failed"
 msgstr "Saved successfully"
 msgstr "Saved successfully"
 
 
-#: src/components/Notification/notifications.ts:108
+#: src/components/Notification/notifications.ts:126
 #, fuzzy
 #, fuzzy
 msgid "Disable stream %{name} from %{node} successfully"
 msgid "Disable stream %{name} from %{node} successfully"
 msgstr "Saved successfully"
 msgstr "Saved successfully"
@@ -1061,7 +1088,7 @@ msgid ""
 msgstr ""
 msgstr ""
 
 
 #: src/views/site/site_list/SiteDuplicate.vue:72
 #: src/views/site/site_list/SiteDuplicate.vue:72
-#: src/views/site/site_list/SiteList.vue:158
+#: src/views/site/site_list/SiteList.vue:162
 #: src/views/stream/components/StreamDuplicate.vue:64
 #: src/views/stream/components/StreamDuplicate.vue:64
 #: src/views/stream/StreamList.vue:222
 #: src/views/stream/StreamList.vue:222
 #, fuzzy
 #, fuzzy
@@ -1135,62 +1162,62 @@ msgstr "Enable failed"
 msgid "Enable HTTPS"
 msgid "Enable HTTPS"
 msgstr "Enable TLS"
 msgstr "Enable TLS"
 
 
-#: src/components/Notification/notifications.ts:53 src/language/constants.ts:54
+#: src/components/Notification/notifications.ts:71 src/language/constants.ts:54
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Site Error"
 msgid "Enable Remote Site Error"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
 
 
-#: src/components/Notification/notifications.ts:61
+#: src/components/Notification/notifications.ts:79
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Site Maintenance Error"
 msgid "Enable Remote Site Maintenance Error"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
 
 
-#: src/components/Notification/notifications.ts:65
+#: src/components/Notification/notifications.ts:83
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Site Maintenance Success"
 msgid "Enable Remote Site Maintenance Success"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
 
 
-#: src/components/Notification/notifications.ts:57 src/language/constants.ts:53
+#: src/components/Notification/notifications.ts:75 src/language/constants.ts:53
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Site Success"
 msgid "Enable Remote Site Success"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
 
 
-#: src/components/Notification/notifications.ts:111
+#: src/components/Notification/notifications.ts:129
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Stream Error"
 msgid "Enable Remote Stream Error"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
 
 
-#: src/components/Notification/notifications.ts:115
+#: src/components/Notification/notifications.ts:133
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Stream Success"
 msgid "Enable Remote Stream Success"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
 
 
-#: src/components/Notification/notifications.ts:62
+#: src/components/Notification/notifications.ts:80
 #, fuzzy
 #, fuzzy
 msgid "Enable site %{name} maintenance on %{node} failed"
 msgid "Enable site %{name} maintenance on %{node} failed"
 msgstr "Saved successfully"
 msgstr "Saved successfully"
 
 
-#: src/components/Notification/notifications.ts:66
+#: src/components/Notification/notifications.ts:84
 #, fuzzy
 #, fuzzy
 msgid "Enable site %{name} maintenance on %{node} successfully"
 msgid "Enable site %{name} maintenance on %{node} successfully"
 msgstr "Saved successfully"
 msgstr "Saved successfully"
 
 
-#: src/components/Notification/notifications.ts:54
+#: src/components/Notification/notifications.ts:72
 #, fuzzy
 #, fuzzy
 msgid "Enable site %{name} on %{node} failed"
 msgid "Enable site %{name} on %{node} failed"
 msgstr "Saved successfully"
 msgstr "Saved successfully"
 
 
-#: src/components/Notification/notifications.ts:58
+#: src/components/Notification/notifications.ts:76
 #, fuzzy
 #, fuzzy
 msgid "Enable site %{name} on %{node} successfully"
 msgid "Enable site %{name} on %{node} successfully"
 msgstr "Saved successfully"
 msgstr "Saved successfully"
 
 
-#: src/components/Notification/notifications.ts:112
+#: src/components/Notification/notifications.ts:130
 #, fuzzy
 #, fuzzy
 msgid "Enable stream %{name} on %{node} failed"
 msgid "Enable stream %{name} on %{node} failed"
 msgstr "Saved successfully"
 msgstr "Saved successfully"
 
 
-#: src/components/Notification/notifications.ts:116
+#: src/components/Notification/notifications.ts:134
 #, fuzzy
 #, fuzzy
 msgid "Enable stream %{name} on %{node} successfully"
 msgid "Enable stream %{name} on %{node} successfully"
 msgstr "Saved successfully"
 msgstr "Saved successfully"
@@ -1280,6 +1307,11 @@ msgstr "Expiration Date: %{date}"
 msgid "Export"
 msgid "Export"
 msgstr ""
 msgstr ""
 
 
+#: src/views/preference/ExternalNotify.vue:10
+#: src/views/preference/Preference.vue:169
+msgid "External Notify"
+msgstr ""
+
 #: src/views/site/cert/components/ObtainCertLive.vue:94
 #: src/views/site/cert/components/ObtainCertLive.vue:94
 #, fuzzy
 #, fuzzy
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
@@ -1688,7 +1720,7 @@ msgstr "Home"
 msgid "Host"
 msgid "Host"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/Preference.vue:174
+#: src/views/preference/Preference.vue:181
 msgid "HTTP"
 msgid "HTTP"
 msgstr ""
 msgstr ""
 
 
@@ -1745,12 +1777,12 @@ msgid "Import Certificate"
 msgstr "Certificate Status"
 msgstr "Certificate Status"
 
 
 #: src/views/nginx_log/NginxLogList.vue:137
 #: src/views/nginx_log/NginxLogList.vue:137
-#: src/views/site/site_list/SiteList.vue:128
+#: src/views/site/site_list/SiteList.vue:132
 msgid "Indexed"
 msgid "Indexed"
 msgstr ""
 msgstr ""
 
 
 #: src/views/nginx_log/NginxLogList.vue:134
 #: src/views/nginx_log/NginxLogList.vue:134
-#: src/views/site/site_list/SiteList.vue:125
+#: src/views/site/site_list/SiteList.vue:129
 msgid "Indexing..."
 msgid "Indexing..."
 msgstr ""
 msgstr ""
 
 
@@ -1838,6 +1870,11 @@ msgstr "Invalid E-mail!"
 msgid "Invalid folder name"
 msgid "Invalid folder name"
 msgstr "Invalid E-mail!"
 msgstr "Invalid E-mail!"
 
 
+#: src/constants/errors/notification.ts:3
+#, fuzzy
+msgid "Invalid notifier config"
+msgstr "Invalid E-mail!"
+
 #: src/constants/errors/user.ts:4
 #: src/constants/errors/user.ts:4
 #, fuzzy
 #, fuzzy
 msgid "Invalid otp code"
 msgid "Invalid otp code"
@@ -1904,6 +1941,10 @@ msgstr ""
 msgid "Key Type"
 msgid "Key Type"
 msgstr ""
 msgstr ""
 
 
+#: src/views/preference/components/ExternalNotify/columns.ts:29
+msgid "Language"
+msgstr ""
+
 #: src/views/system/Upgrade.vue:179
 #: src/views/system/Upgrade.vue:179
 #, fuzzy
 #, fuzzy
 msgid "Last checked at"
 msgid "Last checked at"
@@ -2009,7 +2050,7 @@ msgstr "Login successful"
 msgid "Logout successful"
 msgid "Logout successful"
 msgstr "Logout successful"
 msgstr "Logout successful"
 
 
-#: src/views/preference/Preference.vue:210
+#: src/views/preference/Preference.vue:217
 msgid "Logrotate"
 msgid "Logrotate"
 msgstr ""
 msgstr ""
 
 
@@ -2052,7 +2093,7 @@ msgstr ""
 msgid "Manage Configs"
 msgid "Manage Configs"
 msgstr "Manage Configs"
 msgstr "Manage Configs"
 
 
-#: src/routes/modules/sites.ts:10 src/views/site/site_list/SiteList.vue:121
+#: src/routes/modules/sites.ts:10 src/views/site/site_list/SiteList.vue:125
 msgid "Manage Sites"
 msgid "Manage Sites"
 msgstr "Manage Sites"
 msgstr "Manage Sites"
 
 
@@ -2135,7 +2176,7 @@ msgstr "Single Directive"
 #: src/views/nginx_log/NginxLogList.vue:37
 #: src/views/nginx_log/NginxLogList.vue:37
 #: src/views/preference/components/AddPasskey.vue:75
 #: src/views/preference/components/AddPasskey.vue:75
 #: src/views/site/ngx_conf/NgxUpstream.vue:177
 #: src/views/site/ngx_conf/NgxUpstream.vue:177
-#: src/views/site/site_edit/RightSettings.vue:64
+#: src/views/site/site_edit/RightSettings.vue:63
 #: src/views/site/site_list/columns.tsx:17
 #: src/views/site/site_list/columns.tsx:17
 #: src/views/site/site_list/SiteDuplicate.vue:79
 #: src/views/site/site_list/SiteDuplicate.vue:79
 #: src/views/stream/components/RightSettings.vue:87
 #: src/views/stream/components/RightSettings.vue:87
@@ -2185,7 +2226,7 @@ msgstr ""
 msgid "Next"
 msgid "Next"
 msgstr "Next"
 msgstr "Next"
 
 
-#: src/views/preference/Preference.vue:198
+#: src/views/preference/Preference.vue:205
 msgid "Nginx"
 msgid "Nginx"
 msgstr ""
 msgstr ""
 
 
@@ -2328,7 +2369,7 @@ msgstr "Configuration Name"
 #: src/views/preference/CertSettings.vue:73
 #: src/views/preference/CertSettings.vue:73
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:97
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:97
 #: src/views/site/ngx_conf/LocationEditor.vue:88
 #: src/views/site/ngx_conf/LocationEditor.vue:88
-#: src/views/site/site_list/SiteList.vue:161
+#: src/views/site/site_list/SiteList.vue:165
 #: src/views/stream/StreamList.vue:225
 #: src/views/stream/StreamList.vue:225
 msgid "No"
 msgid "No"
 msgstr "No"
 msgstr "No"
@@ -2343,12 +2384,12 @@ msgstr "Action"
 msgid "No records selected"
 msgid "No records selected"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/Preference.vue:168
+#: src/views/preference/Preference.vue:175
 #, fuzzy
 #, fuzzy
 msgid "Node"
 msgid "Node"
 msgstr "Username"
 msgstr "Username"
 
 
-#: src/views/site/site_edit/RightSettings.vue:67
+#: src/views/site/site_edit/RightSettings.vue:66
 #: src/views/site/site_list/columns.tsx:63
 #: src/views/site/site_list/columns.tsx:63
 #: src/views/stream/components/RightSettings.vue:90
 #: src/views/stream/components/RightSettings.vue:90
 #: src/views/stream/StreamList.vue:30
 #: src/views/stream/StreamList.vue:30
@@ -2394,7 +2435,7 @@ msgstr "Not Valid Before: %{date}"
 msgid "Note"
 msgid "Note"
 msgstr ""
 msgstr ""
 
 
-#: src/views/site/site_edit/RightSettings.vue:96
+#: src/views/site/site_edit/RightSettings.vue:95
 #: src/views/stream/components/RightSettings.vue:118
 #: src/views/stream/components/RightSettings.vue:118
 msgid ""
 msgid ""
 "Note, if the configuration file include other configurations or "
 "Note, if the configuration file include other configurations or "
@@ -2412,6 +2453,11 @@ msgstr "Certificate is valid"
 msgid "Notifications"
 msgid "Notifications"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
 
 
+#: src/constants/errors/notification.ts:2
+#, fuzzy
+msgid "Notifier not found"
+msgstr "File Not Found"
+
 #: src/views/site/cert/components/ObtainCert.vue:182
 #: src/views/site/cert/components/ObtainCert.vue:182
 #, fuzzy
 #, fuzzy
 msgid "Obtain certificate"
 msgid "Obtain certificate"
@@ -2456,7 +2502,7 @@ msgstr ""
 #: src/views/site/ngx_conf/NgxServer.vue:79
 #: src/views/site/ngx_conf/NgxServer.vue:79
 #: src/views/site/ngx_conf/NgxUpstream.vue:33
 #: src/views/site/ngx_conf/NgxUpstream.vue:33
 #: src/views/site/site_edit/components/SiteStatusSegmented.vue:121
 #: src/views/site/site_edit/components/SiteStatusSegmented.vue:121
-#: src/views/site/site_list/SiteList.vue:162
+#: src/views/site/site_list/SiteList.vue:166
 #: src/views/stream/components/RightSettings.vue:54
 #: src/views/stream/components/RightSettings.vue:54
 #: src/views/stream/StreamList.vue:226
 #: src/views/stream/StreamList.vue:226
 #: src/views/system/Backup/BackupCreator.vue:149
 #: src/views/system/Backup/BackupCreator.vue:149
@@ -2479,7 +2525,7 @@ msgstr ""
 msgid "Only zip files are allowed"
 msgid "Only zip files are allowed"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/Preference.vue:204
+#: src/views/preference/Preference.vue:211
 msgid "OpenAI"
 msgid "OpenAI"
 msgstr ""
 msgstr ""
 
 
@@ -2620,7 +2666,7 @@ msgid ""
 "select one of the credentialsbelow to request the API of the DNS provider."
 "select one of the credentialsbelow to request the API of the DNS provider."
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:138
+#: src/components/Notification/notifications.ts:156
 #: src/language/constants.ts:59
 #: src/language/constants.ts:59
 msgid ""
 msgid ""
 "Please generate new recovery codes in the preferences immediately to prevent "
 "Please generate new recovery codes in the preferences immediately to prevent "
@@ -2710,7 +2756,7 @@ msgstr "Action"
 msgid "Pre-release"
 msgid "Pre-release"
 msgstr ""
 msgstr ""
 
 
-#: src/routes/modules/preference.ts:10 src/views/preference/Preference.vue:151
+#: src/routes/modules/preference.ts:10 src/views/preference/Preference.vue:152
 msgid "Preference"
 msgid "Preference"
 msgstr ""
 msgstr ""
 
 
@@ -2851,22 +2897,22 @@ msgstr ""
 msgid "Reload Nginx"
 msgid "Reload Nginx"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:144
+#: src/components/Notification/notifications.ts:10
 #, fuzzy
 #, fuzzy
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgstr "Saved successfully"
 msgstr "Saved successfully"
 
 
-#: src/components/Notification/notifications.ts:148
+#: src/components/Notification/notifications.ts:14
 #, fuzzy
 #, fuzzy
 msgid "Reload Nginx on %{node} successfully"
 msgid "Reload Nginx on %{node} successfully"
 msgstr "Saved successfully"
 msgstr "Saved successfully"
 
 
-#: src/components/Notification/notifications.ts:143
+#: src/components/Notification/notifications.ts:9
 #, fuzzy
 #, fuzzy
 msgid "Reload Remote Nginx Error"
 msgid "Reload Remote Nginx Error"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
 
 
-#: src/components/Notification/notifications.ts:147
+#: src/components/Notification/notifications.ts:13
 #, fuzzy
 #, fuzzy
 msgid "Reload Remote Nginx Success"
 msgid "Reload Remote Nginx Success"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
@@ -2908,62 +2954,62 @@ msgstr "Saved successfully"
 msgid "Rename"
 msgid "Rename"
 msgstr "Username"
 msgstr "Username"
 
 
-#: src/components/Notification/notifications.ts:28
+#: src/components/Notification/notifications.ts:46
 #, fuzzy
 #, fuzzy
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} failed"
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} failed"
 msgstr "Saved successfully"
 msgstr "Saved successfully"
 
 
-#: src/components/Notification/notifications.ts:32
+#: src/components/Notification/notifications.ts:50
 #, fuzzy
 #, fuzzy
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} successfully"
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} successfully"
 msgstr "Saved successfully"
 msgstr "Saved successfully"
 
 
-#: src/components/Notification/notifications.ts:27 src/language/constants.ts:42
+#: src/components/Notification/notifications.ts:45 src/language/constants.ts:42
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Config Error"
 msgid "Rename Remote Config Error"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
 
 
-#: src/components/Notification/notifications.ts:31 src/language/constants.ts:41
+#: src/components/Notification/notifications.ts:49 src/language/constants.ts:41
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Config Success"
 msgid "Rename Remote Config Success"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
 
 
-#: src/components/Notification/notifications.ts:77 src/language/constants.ts:56
+#: src/components/Notification/notifications.ts:95 src/language/constants.ts:56
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Site Error"
 msgid "Rename Remote Site Error"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
 
 
-#: src/components/Notification/notifications.ts:81 src/language/constants.ts:55
+#: src/components/Notification/notifications.ts:99 src/language/constants.ts:55
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Site Success"
 msgid "Rename Remote Site Success"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
 
 
-#: src/components/Notification/notifications.ts:119
+#: src/components/Notification/notifications.ts:137
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Stream Error"
 msgid "Rename Remote Stream Error"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
 
 
-#: src/components/Notification/notifications.ts:123
+#: src/components/Notification/notifications.ts:141
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Stream Success"
 msgid "Rename Remote Stream Success"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
 
 
-#: src/components/Notification/notifications.ts:78
+#: src/components/Notification/notifications.ts:96
 #, fuzzy
 #, fuzzy
 msgid "Rename site %{name} to %{new_name} on %{node} failed"
 msgid "Rename site %{name} to %{new_name} on %{node} failed"
 msgstr "Saved successfully"
 msgstr "Saved successfully"
 
 
-#: src/components/Notification/notifications.ts:82
+#: src/components/Notification/notifications.ts:100
 #, fuzzy
 #, fuzzy
 msgid "Rename site %{name} to %{new_name} on %{node} successfully"
 msgid "Rename site %{name} to %{new_name} on %{node} successfully"
 msgstr "Saved successfully"
 msgstr "Saved successfully"
 
 
-#: src/components/Notification/notifications.ts:120
+#: src/components/Notification/notifications.ts:138
 #, fuzzy
 #, fuzzy
 msgid "Rename stream %{name} to %{new_name} on %{node} failed"
 msgid "Rename stream %{name} to %{new_name} on %{node} failed"
 msgstr "Saved successfully"
 msgstr "Saved successfully"
 
 
-#: src/components/Notification/notifications.ts:124
+#: src/components/Notification/notifications.ts:142
 #, fuzzy
 #, fuzzy
 msgid "Rename stream %{name} to %{new_name} on %{node} successfully"
 msgid "Rename stream %{name} to %{new_name} on %{node} successfully"
 msgstr "Saved successfully"
 msgstr "Saved successfully"
@@ -3028,22 +3074,22 @@ msgstr ""
 msgid "Restart Nginx"
 msgid "Restart Nginx"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:152
+#: src/components/Notification/notifications.ts:18
 #, fuzzy
 #, fuzzy
 msgid "Restart Nginx on %{node} failed, response: %{resp}"
 msgid "Restart Nginx on %{node} failed, response: %{resp}"
 msgstr "Saved successfully"
 msgstr "Saved successfully"
 
 
-#: src/components/Notification/notifications.ts:156
+#: src/components/Notification/notifications.ts:22
 #, fuzzy
 #, fuzzy
 msgid "Restart Nginx on %{node} successfully"
 msgid "Restart Nginx on %{node} successfully"
 msgstr "Saved successfully"
 msgstr "Saved successfully"
 
 
-#: src/components/Notification/notifications.ts:151
+#: src/components/Notification/notifications.ts:17
 #, fuzzy
 #, fuzzy
 msgid "Restart Remote Nginx Error"
 msgid "Restart Remote Nginx Error"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
 
 
-#: src/components/Notification/notifications.ts:155
+#: src/components/Notification/notifications.ts:21
 #, fuzzy
 #, fuzzy
 msgid "Restart Remote Nginx Success"
 msgid "Restart Remote Nginx Success"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
@@ -3111,7 +3157,7 @@ msgstr ""
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/ConfigEditor.vue:271
 #: src/views/config/ConfigEditor.vue:271
 #: src/views/preference/components/Passkey.vue:130
 #: src/views/preference/components/Passkey.vue:130
-#: src/views/preference/Preference.vue:221
+#: src/views/preference/Preference.vue:228
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:127
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:127
 #: src/views/site/site_edit/components/ConfigName.vue:52
 #: src/views/site/site_edit/components/ConfigName.vue:52
 #: src/views/site/site_edit/SiteEdit.vue:292
 #: src/views/site/site_edit/SiteEdit.vue:292
@@ -3129,42 +3175,44 @@ msgstr "Save Directive"
 msgid "Save error %{msg}"
 msgid "Save error %{msg}"
 msgstr "Save error %{msg}"
 msgstr "Save error %{msg}"
 
 
-#: src/components/Notification/notifications.ts:85 src/language/constants.ts:48
+#: src/components/Notification/notifications.ts:103
+#: src/language/constants.ts:48
 #, fuzzy
 #, fuzzy
 msgid "Save Remote Site Error"
 msgid "Save Remote Site Error"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
 
 
-#: src/components/Notification/notifications.ts:89 src/language/constants.ts:47
+#: src/components/Notification/notifications.ts:107
+#: src/language/constants.ts:47
 #, fuzzy
 #, fuzzy
 msgid "Save Remote Site Success"
 msgid "Save Remote Site Success"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
 
 
-#: src/components/Notification/notifications.ts:127
+#: src/components/Notification/notifications.ts:145
 #, fuzzy
 #, fuzzy
 msgid "Save Remote Stream Error"
 msgid "Save Remote Stream Error"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
 
 
-#: src/components/Notification/notifications.ts:131
+#: src/components/Notification/notifications.ts:149
 #, fuzzy
 #, fuzzy
 msgid "Save Remote Stream Success"
 msgid "Save Remote Stream Success"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
 
 
-#: src/components/Notification/notifications.ts:86
+#: src/components/Notification/notifications.ts:104
 #, fuzzy
 #, fuzzy
 msgid "Save site %{name} to %{node} failed"
 msgid "Save site %{name} to %{node} failed"
 msgstr "Saved successfully"
 msgstr "Saved successfully"
 
 
-#: src/components/Notification/notifications.ts:90
+#: src/components/Notification/notifications.ts:108
 #, fuzzy
 #, fuzzy
 msgid "Save site %{name} to %{node} successfully"
 msgid "Save site %{name} to %{node} successfully"
 msgstr "Saved successfully"
 msgstr "Saved successfully"
 
 
-#: src/components/Notification/notifications.ts:128
+#: src/components/Notification/notifications.ts:146
 #, fuzzy
 #, fuzzy
 msgid "Save stream %{name} to %{node} failed"
 msgid "Save stream %{name} to %{node} failed"
 msgstr "Saved successfully"
 msgstr "Saved successfully"
 
 
-#: src/components/Notification/notifications.ts:132
+#: src/components/Notification/notifications.ts:150
 #, fuzzy
 #, fuzzy
 msgid "Save stream %{name} to %{node} successfully"
 msgid "Save stream %{name} to %{node} successfully"
 msgstr "Saved successfully"
 msgstr "Saved successfully"
@@ -3172,7 +3220,7 @@ msgstr "Saved successfully"
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:47
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:47
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:97
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:97
 #: src/views/certificate/CertificateEditor.vue:49
 #: src/views/certificate/CertificateEditor.vue:49
-#: src/views/preference/Preference.vue:123
+#: src/views/preference/Preference.vue:124
 #, fuzzy
 #, fuzzy
 msgid "Save successfully"
 msgid "Save successfully"
 msgstr "Saved successfully"
 msgstr "Saved successfully"
@@ -3193,6 +3241,10 @@ msgstr ""
 msgid "SDK"
 msgid "SDK"
 msgstr ""
 msgstr ""
 
 
+#: src/views/preference/components/ExternalNotify/dingtalk.ts:13
+msgid "Secret (Optional)"
+msgstr ""
+
 #: src/views/preference/components/TOTP.vue:109
 #: src/views/preference/components/TOTP.vue:109
 msgid "Secret has been copied"
 msgid "Secret has been copied"
 msgstr ""
 msgstr ""
@@ -3225,7 +3277,7 @@ msgstr ""
 msgid "Send"
 msgid "Send"
 msgstr "Send"
 msgstr "Send"
 
 
-#: src/views/preference/Preference.vue:156
+#: src/views/preference/Preference.vue:157
 #, fuzzy
 #, fuzzy
 msgid "Server"
 msgid "Server"
 msgstr "Server Info"
 msgstr "Server Info"
@@ -3234,6 +3286,11 @@ msgstr "Server Info"
 msgid "Server Info"
 msgid "Server Info"
 msgstr "Server Info"
 msgstr "Server Info"
 
 
+#: src/views/preference/components/ExternalNotify/bark.ts:13
+#, fuzzy
+msgid "Server URL"
+msgstr "Server Info"
+
 #: src/views/site/cert/components/ObtainCert.vue:107
 #: src/views/site/cert/components/ObtainCert.vue:107
 msgid "server_name not found in directives"
 msgid "server_name not found in directives"
 msgstr "server_name not found in directives"
 msgstr "server_name not found in directives"
@@ -3415,7 +3472,7 @@ msgstr ""
 #: src/views/certificate/ACMEUser.vue:65
 #: src/views/certificate/ACMEUser.vue:65
 #: src/views/certificate/CertificateList/certColumns.tsx:65
 #: src/views/certificate/CertificateList/certColumns.tsx:65
 #: src/views/environments/list/envColumns.tsx:44
 #: src/views/environments/list/envColumns.tsx:44
-#: src/views/site/site_edit/RightSettings.vue:56
+#: src/views/site/site_edit/RightSettings.vue:55
 #: src/views/site/site_list/columns.tsx:80 src/views/stream/StreamList.vue:47
 #: src/views/site/site_list/columns.tsx:80 src/views/stream/StreamList.vue:47
 msgid "Status"
 msgid "Status"
 msgstr "Status"
 msgstr "Status"
@@ -3493,42 +3550,42 @@ msgstr ""
 msgid "Sync Certificate"
 msgid "Sync Certificate"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
 
 
-#: src/components/Notification/notifications.ts:10
+#: src/components/Notification/notifications.ts:28
 #, fuzzy
 #, fuzzy
 msgid "Sync Certificate %{cert_name} to %{env_name} failed"
 msgid "Sync Certificate %{cert_name} to %{env_name} failed"
 msgstr "Saved successfully"
 msgstr "Saved successfully"
 
 
-#: src/components/Notification/notifications.ts:14
+#: src/components/Notification/notifications.ts:32
 #, fuzzy
 #, fuzzy
 msgid "Sync Certificate %{cert_name} to %{env_name} successfully"
 msgid "Sync Certificate %{cert_name} to %{env_name} successfully"
 msgstr "Saved successfully"
 msgstr "Saved successfully"
 
 
-#: src/components/Notification/notifications.ts:9 src/language/constants.ts:39
+#: src/components/Notification/notifications.ts:27 src/language/constants.ts:39
 #, fuzzy
 #, fuzzy
 msgid "Sync Certificate Error"
 msgid "Sync Certificate Error"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
 
 
-#: src/components/Notification/notifications.ts:13 src/language/constants.ts:38
+#: src/components/Notification/notifications.ts:31 src/language/constants.ts:38
 #, fuzzy
 #, fuzzy
 msgid "Sync Certificate Success"
 msgid "Sync Certificate Success"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
 
 
-#: src/components/Notification/notifications.ts:20
+#: src/components/Notification/notifications.ts:38
 #, fuzzy
 #, fuzzy
 msgid "Sync config %{config_name} to %{env_name} failed"
 msgid "Sync config %{config_name} to %{env_name} failed"
 msgstr "Saved successfully"
 msgstr "Saved successfully"
 
 
-#: src/components/Notification/notifications.ts:24
+#: src/components/Notification/notifications.ts:42
 #, fuzzy
 #, fuzzy
 msgid "Sync config %{config_name} to %{env_name} successfully"
 msgid "Sync config %{config_name} to %{env_name} successfully"
 msgstr "Saved successfully"
 msgstr "Saved successfully"
 
 
-#: src/components/Notification/notifications.ts:19 src/language/constants.ts:45
+#: src/components/Notification/notifications.ts:37 src/language/constants.ts:45
 #, fuzzy
 #, fuzzy
 msgid "Sync Config Error"
 msgid "Sync Config Error"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
 
 
-#: src/components/Notification/notifications.ts:23 src/language/constants.ts:44
+#: src/components/Notification/notifications.ts:41 src/language/constants.ts:44
 #, fuzzy
 #, fuzzy
 msgid "Sync Config Success"
 msgid "Sync Config Success"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
@@ -3538,8 +3595,8 @@ msgstr "Certificate is valid"
 msgid "Sync Nodes"
 msgid "Sync Nodes"
 msgstr ""
 msgstr ""
 
 
-#: src/views/site/site_edit/RightSettings.vue:102
-#: src/views/site/site_edit/RightSettings.vue:89
+#: src/views/site/site_edit/RightSettings.vue:101
+#: src/views/site/site_edit/RightSettings.vue:88
 #: src/views/stream/components/RightSettings.vue:111
 #: src/views/stream/components/RightSettings.vue:111
 #: src/views/stream/components/RightSettings.vue:124
 #: src/views/stream/components/RightSettings.vue:124
 #, fuzzy
 #, fuzzy
@@ -3551,7 +3608,7 @@ msgstr "Certificate is valid"
 msgid "Sync to"
 msgid "Sync to"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
 
 
-#: src/views/site/site_edit/RightSettings.vue:86
+#: src/views/site/site_edit/RightSettings.vue:85
 #: src/views/stream/components/RightSettings.vue:108
 #: src/views/stream/components/RightSettings.vue:108
 msgid "Synchronization"
 msgid "Synchronization"
 msgstr ""
 msgstr ""
@@ -3582,7 +3639,11 @@ msgstr "Saved successfully"
 msgid "Task not found"
 msgid "Task not found"
 msgstr "File Not Found"
 msgstr "File Not Found"
 
 
-#: src/routes/modules/terminal.ts:10 src/views/preference/Preference.vue:180
+#: src/views/preference/components/ExternalNotify/telegram.ts:5
+msgid "Telegram"
+msgstr ""
+
+#: src/routes/modules/terminal.ts:10 src/views/preference/Preference.vue:187
 #: src/views/terminal/Terminal.vue:129
 #: src/views/terminal/Terminal.vue:129
 msgid "Terminal"
 msgid "Terminal"
 msgstr "Terminal"
 msgstr "Terminal"
@@ -3832,6 +3893,7 @@ msgstr ""
 #: src/views/certificate/CertificateList/certColumns.tsx:25
 #: src/views/certificate/CertificateList/certColumns.tsx:25
 #: src/views/nginx_log/NginxLogList.vue:21
 #: src/views/nginx_log/NginxLogList.vue:21
 #: src/views/notification/notificationColumns.tsx:9
 #: src/views/notification/notificationColumns.tsx:9
+#: src/views/preference/components/ExternalNotify/columns.ts:17
 msgid "Type"
 msgid "Type"
 msgstr ""
 msgstr ""
 
 
@@ -3849,7 +3911,7 @@ msgstr "Saved successfully"
 #: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:325
 #: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:325
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/environments/list/envColumns.tsx:90
-#: src/views/site/site_edit/RightSettings.vue:76
+#: src/views/site/site_edit/RightSettings.vue:75
 #: src/views/site/site_list/columns.tsx:110
 #: src/views/site/site_list/columns.tsx:110
 #: src/views/stream/components/RightSettings.vue:99
 #: src/views/stream/components/RightSettings.vue:99
 #: src/views/stream/StreamList.vue:67 src/views/user/userColumns.tsx:54
 #: src/views/stream/StreamList.vue:67 src/views/user/userColumns.tsx:54
@@ -4015,7 +4077,7 @@ msgid ""
 "Pebble as CA."
 "Pebble as CA."
 msgstr ""
 msgstr ""
 
 
-#: src/views/site/site_edit/RightSettings.vue:92
+#: src/views/site/site_edit/RightSettings.vue:91
 msgid ""
 msgid ""
 "When you enable/disable, delete, or save this site, the nodes set in the "
 "When you enable/disable, delete, or save this site, the nodes set in the "
 "Node Group and the nodes selected below will be synchronized."
 "Node Group and the nodes selected below will be synchronized."

+ 165 - 105
app/src/language/es/app.po

@@ -37,6 +37,11 @@ msgstr "Logs de acceso"
 msgid "Access Logs"
 msgid "Access Logs"
 msgstr "Logs de acceso"
 msgstr "Logs de acceso"
 
 
+#: src/views/preference/components/ExternalNotify/dingtalk.ts:9
+#, fuzzy
+msgid "Access Token"
+msgstr "Logs de acceso"
+
 #: src/routes/modules/certificates.ts:20 src/views/certificate/ACMEUser.vue:113
 #: src/routes/modules/certificates.ts:20 src/views/certificate/ACMEUser.vue:113
 #: src/views/certificate/ACMEUserSelector.vue:85
 #: src/views/certificate/ACMEUserSelector.vue:85
 msgid "ACME User"
 msgid "ACME User"
@@ -51,6 +56,7 @@ msgstr "Usuario ACME"
 #: src/views/nginx_log/NginxLogList.vue:53
 #: src/views/nginx_log/NginxLogList.vue:53
 #: src/views/notification/notificationColumns.tsx:66
 #: src/views/notification/notificationColumns.tsx:66
 #: src/views/preference/AuthSettings.vue:30
 #: src/views/preference/AuthSettings.vue:30
+#: src/views/preference/components/ExternalNotify/columns.ts:46
 #: src/views/site/site_list/columns.tsx:117 src/views/stream/StreamList.vue:74
 #: src/views/site/site_list/columns.tsx:117 src/views/stream/StreamList.vue:74
 #: src/views/user/userColumns.tsx:60
 #: src/views/user/userColumns.tsx:60
 msgid "Action"
 msgid "Action"
@@ -117,7 +123,7 @@ msgstr ""
 msgid "All"
 msgid "All"
 msgstr "Todo"
 msgstr "Todo"
 
 
-#: src/components/Notification/notifications.ts:137
+#: src/components/Notification/notifications.ts:155
 #: src/language/constants.ts:58
 #: src/language/constants.ts:58
 msgid "All Recovery Codes Have Been Used"
 msgid "All Recovery Codes Have Been Used"
 msgstr ""
 msgstr ""
@@ -143,7 +149,7 @@ msgstr "Token de la API"
 msgid "API Type"
 msgid "API Type"
 msgstr "Token de la API"
 msgstr "Token de la API"
 
 
-#: src/views/preference/Preference.vue:162
+#: src/views/preference/Preference.vue:163
 msgid "App"
 msgid "App"
 msgstr ""
 msgstr ""
 
 
@@ -200,7 +206,7 @@ msgstr "¿Está seguro de que desea eliminar este elemento de forma permanente?"
 msgid "Are you sure you want to delete this item?"
 msgid "Are you sure you want to delete this item?"
 msgstr "¿Está seguro de que quiere borrar este elemento?"
 msgstr "¿Está seguro de que quiere borrar este elemento?"
 
 
-#: src/views/site/site_list/SiteList.vue:163
+#: src/views/site/site_list/SiteList.vue:167
 #: src/views/stream/StreamList.vue:227
 #: src/views/stream/StreamList.vue:227
 msgid "Are you sure you want to delete?"
 msgid "Are you sure you want to delete?"
 msgstr "¿Está seguro de que quiere borrar?"
 msgstr "¿Está seguro de que quiere borrar?"
@@ -248,7 +254,7 @@ msgstr "Intentos"
 msgid "Attempts"
 msgid "Attempts"
 msgstr "Intentos"
 msgstr "Intentos"
 
 
-#: src/views/preference/Preference.vue:186
+#: src/views/preference/Preference.vue:193
 msgid "Auth"
 msgid "Auth"
 msgstr "Autenticación"
 msgstr "Autenticación"
 
 
@@ -332,12 +338,16 @@ msgstr "IPs prohibidas"
 msgid "Banned Until"
 msgid "Banned Until"
 msgstr "Bloqueado hasta"
 msgstr "Bloqueado hasta"
 
 
+#: src/views/preference/components/ExternalNotify/bark.ts:5
+msgid "Bark"
+msgstr ""
+
 #: src/views/site/site_add/SiteAdd.vue:95
 #: src/views/site/site_add/SiteAdd.vue:95
 msgid "Base information"
 msgid "Base information"
 msgstr "Información general"
 msgstr "Información general"
 
 
 #: src/views/config/ConfigEditor.vue:290
 #: src/views/config/ConfigEditor.vue:290
-#: src/views/site/site_edit/RightSettings.vue:53
+#: src/views/site/site_edit/RightSettings.vue:52
 #: src/views/stream/components/RightSettings.vue:79
 #: src/views/stream/components/RightSettings.vue:79
 msgid "Basic"
 msgid "Basic"
 msgstr "Básico"
 msgstr "Básico"
@@ -371,6 +381,11 @@ msgstr ""
 msgid "Block is nil"
 msgid "Block is nil"
 msgstr ""
 msgstr ""
 
 
+#: src/views/preference/components/ExternalNotify/telegram.ts:9
+#, fuzzy
+msgid "Bot Token"
+msgstr "Token"
+
 #: src/views/system/About.vue:55
 #: src/views/system/About.vue:55
 msgid "Build with"
 msgid "Build with"
 msgstr "Desarrollado con"
 msgstr "Desarrollado con"
@@ -412,7 +427,7 @@ msgstr ""
 msgid "Cannot remove initial user"
 msgid "Cannot remove initial user"
 msgstr "Usuario inicial del sistema"
 msgstr "Usuario inicial del sistema"
 
 
-#: src/views/preference/Preference.vue:192
+#: src/views/preference/Preference.vue:199
 msgid "Cert"
 msgid "Cert"
 msgstr "Certificado"
 msgstr "Certificado"
 
 
@@ -484,6 +499,10 @@ msgstr "Ruta cambiada"
 msgid "Channel"
 msgid "Channel"
 msgstr "Canal"
 msgstr "Canal"
 
 
+#: src/views/preference/components/ExternalNotify/telegram.ts:13
+msgid "Chat ID"
+msgstr ""
+
 #: src/views/system/Upgrade.vue:185
 #: src/views/system/Upgrade.vue:185
 msgid "Check again"
 msgid "Check again"
 msgstr "Intentar nuevamente"
 msgstr "Intentar nuevamente"
@@ -680,6 +699,7 @@ msgstr ""
 
 
 #: src/views/environments/group/columns.ts:31
 #: src/views/environments/group/columns.ts:31
 #: src/views/notification/notificationColumns.tsx:59
 #: src/views/notification/notificationColumns.tsx:59
+#: src/views/preference/components/ExternalNotify/columns.ts:41
 #: src/views/preference/components/Passkey.vue:95
 #: src/views/preference/components/Passkey.vue:95
 #: src/views/user/userColumns.tsx:48
 #: src/views/user/userColumns.tsx:48
 msgid "Created at"
 msgid "Created at"
@@ -753,7 +773,7 @@ msgstr "Descripción"
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/views/site/ngx_conf/NgxServer.vue:110
 #: src/views/site/ngx_conf/NgxServer.vue:110
 #: src/views/site/ngx_conf/NgxUpstream.vue:128
 #: src/views/site/ngx_conf/NgxUpstream.vue:128
-#: src/views/site/site_list/SiteList.vue:172
+#: src/views/site/site_list/SiteList.vue:176
 #: src/views/stream/StreamList.vue:236
 #: src/views/stream/StreamList.vue:236
 msgid "Delete"
 msgid "Delete"
 msgstr "Eliminar"
 msgstr "Eliminar"
@@ -763,44 +783,44 @@ msgstr "Eliminar"
 msgid "Delete Permanently"
 msgid "Delete Permanently"
 msgstr "Eliminar Permanentemente"
 msgstr "Eliminar Permanentemente"
 
 
-#: src/components/Notification/notifications.ts:37 src/language/constants.ts:50
+#: src/components/Notification/notifications.ts:55 src/language/constants.ts:50
 msgid "Delete Remote Site Error"
 msgid "Delete Remote Site Error"
 msgstr "Error al eliminar sitio remoto"
 msgstr "Error al eliminar sitio remoto"
 
 
-#: src/components/Notification/notifications.ts:41 src/language/constants.ts:49
+#: src/components/Notification/notifications.ts:59 src/language/constants.ts:49
 msgid "Delete Remote Site Success"
 msgid "Delete Remote Site Success"
 msgstr "Borrado del sitio remoto correcto"
 msgstr "Borrado del sitio remoto correcto"
 
 
-#: src/components/Notification/notifications.ts:95
+#: src/components/Notification/notifications.ts:113
 #, fuzzy
 #, fuzzy
 msgid "Delete Remote Stream Error"
 msgid "Delete Remote Stream Error"
 msgstr "Error al eliminar sitio remoto"
 msgstr "Error al eliminar sitio remoto"
 
 
-#: src/components/Notification/notifications.ts:99
+#: src/components/Notification/notifications.ts:117
 #, fuzzy
 #, fuzzy
 msgid "Delete Remote Stream Success"
 msgid "Delete Remote Stream Success"
 msgstr "Borrado del sitio remoto correcto"
 msgstr "Borrado del sitio remoto correcto"
 
 
-#: src/components/Notification/notifications.ts:38
+#: src/components/Notification/notifications.ts:56
 #, fuzzy
 #, fuzzy
 msgid "Delete site %{name} from %{node} failed"
 msgid "Delete site %{name} from %{node} failed"
 msgstr "Falló el desplegado de %{conf_name} a %{node_name}"
 msgstr "Falló el desplegado de %{conf_name} a %{node_name}"
 
 
-#: src/components/Notification/notifications.ts:42
+#: src/components/Notification/notifications.ts:60
 #, fuzzy
 #, fuzzy
 msgid "Delete site %{name} from %{node} successfully"
 msgid "Delete site %{name} from %{node} successfully"
 msgstr "Duplicado con éxito de %{conf_name} a %{node_name}"
 msgstr "Duplicado con éxito de %{conf_name} a %{node_name}"
 
 
-#: src/views/site/site_list/SiteList.vue:94
+#: src/views/site/site_list/SiteList.vue:98
 msgid "Delete site: %{site_name}"
 msgid "Delete site: %{site_name}"
 msgstr "Eliminar sitio: %{site_name}"
 msgstr "Eliminar sitio: %{site_name}"
 
 
-#: src/components/Notification/notifications.ts:96
+#: src/components/Notification/notifications.ts:114
 #, fuzzy
 #, fuzzy
 msgid "Delete stream %{name} from %{node} failed"
 msgid "Delete stream %{name} from %{node} failed"
 msgstr "Falló el desplegado de %{conf_name} a %{node_name}"
 msgstr "Falló el desplegado de %{conf_name} a %{node_name}"
 
 
-#: src/components/Notification/notifications.ts:100
+#: src/components/Notification/notifications.ts:118
 #, fuzzy
 #, fuzzy
 msgid "Delete stream %{name} from %{node} successfully"
 msgid "Delete stream %{name} from %{node} successfully"
 msgstr "Duplicado con éxito de %{conf_name} a %{node_name}"
 msgstr "Duplicado con éxito de %{conf_name} a %{node_name}"
@@ -838,6 +858,14 @@ msgstr "Detalles"
 msgid "Development Mode"
 msgid "Development Mode"
 msgstr "Modo de desarrollo"
 msgstr "Modo de desarrollo"
 
 
+#: src/views/preference/components/ExternalNotify/bark.ts:9
+msgid "Device Key"
+msgstr ""
+
+#: src/views/preference/components/ExternalNotify/dingtalk.ts:5
+msgid "DingTalk"
+msgstr ""
+
 #: src/views/site/ngx_conf/directive/DirectiveAdd.vue:89
 #: src/views/site/ngx_conf/directive/DirectiveAdd.vue:89
 msgid "Directive"
 msgid "Directive"
 msgstr "Directiva"
 msgstr "Directiva"
@@ -871,60 +899,60 @@ msgstr "Desactivar"
 msgid "Disable auto-renewal failed for %{name}"
 msgid "Disable auto-renewal failed for %{name}"
 msgstr "No se pudo desactivar la renovación automática por %{name}"
 msgstr "No se pudo desactivar la renovación automática por %{name}"
 
 
-#: src/components/Notification/notifications.ts:45 src/language/constants.ts:52
+#: src/components/Notification/notifications.ts:63 src/language/constants.ts:52
 msgid "Disable Remote Site Error"
 msgid "Disable Remote Site Error"
 msgstr "Error al deshabilitar el sitio remoto"
 msgstr "Error al deshabilitar el sitio remoto"
 
 
-#: src/components/Notification/notifications.ts:69
+#: src/components/Notification/notifications.ts:87
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Site Maintenance Error"
 msgid "Disable Remote Site Maintenance Error"
 msgstr "Error al deshabilitar el sitio remoto"
 msgstr "Error al deshabilitar el sitio remoto"
 
 
-#: src/components/Notification/notifications.ts:73
+#: src/components/Notification/notifications.ts:91
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Site Maintenance Success"
 msgid "Disable Remote Site Maintenance Success"
 msgstr "Deshabilitado de sitio remoto exitoso"
 msgstr "Deshabilitado de sitio remoto exitoso"
 
 
-#: src/components/Notification/notifications.ts:49 src/language/constants.ts:51
+#: src/components/Notification/notifications.ts:67 src/language/constants.ts:51
 msgid "Disable Remote Site Success"
 msgid "Disable Remote Site Success"
 msgstr "Deshabilitado de sitio remoto exitoso"
 msgstr "Deshabilitado de sitio remoto exitoso"
 
 
-#: src/components/Notification/notifications.ts:103
+#: src/components/Notification/notifications.ts:121
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Stream Error"
 msgid "Disable Remote Stream Error"
 msgstr "Error al deshabilitar el sitio remoto"
 msgstr "Error al deshabilitar el sitio remoto"
 
 
-#: src/components/Notification/notifications.ts:107
+#: src/components/Notification/notifications.ts:125
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Stream Success"
 msgid "Disable Remote Stream Success"
 msgstr "Deshabilitado de sitio remoto exitoso"
 msgstr "Deshabilitado de sitio remoto exitoso"
 
 
-#: src/components/Notification/notifications.ts:46
+#: src/components/Notification/notifications.ts:64
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} from %{node} failed"
 msgid "Disable site %{name} from %{node} failed"
 msgstr "Habilitado exitoso de %{conf_name} en %{node_name}"
 msgstr "Habilitado exitoso de %{conf_name} en %{node_name}"
 
 
-#: src/components/Notification/notifications.ts:50
+#: src/components/Notification/notifications.ts:68
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} from %{node} successfully"
 msgid "Disable site %{name} from %{node} successfully"
 msgstr "Habilitado exitoso de %{conf_name} en %{node_name}"
 msgstr "Habilitado exitoso de %{conf_name} en %{node_name}"
 
 
-#: src/components/Notification/notifications.ts:70
+#: src/components/Notification/notifications.ts:88
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} maintenance on %{node} failed"
 msgid "Disable site %{name} maintenance on %{node} failed"
 msgstr "Habilitado exitoso de %{conf_name} en %{node_name}"
 msgstr "Habilitado exitoso de %{conf_name} en %{node_name}"
 
 
-#: src/components/Notification/notifications.ts:74
+#: src/components/Notification/notifications.ts:92
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} maintenance on %{node} successfully"
 msgid "Disable site %{name} maintenance on %{node} successfully"
 msgstr "Habilitado exitoso de %{conf_name} en %{node_name}"
 msgstr "Habilitado exitoso de %{conf_name} en %{node_name}"
 
 
-#: src/components/Notification/notifications.ts:104
+#: src/components/Notification/notifications.ts:122
 #, fuzzy
 #, fuzzy
 msgid "Disable stream %{name} from %{node} failed"
 msgid "Disable stream %{name} from %{node} failed"
 msgstr "Falló el habilitado de %{conf_name} en %{node_name}"
 msgstr "Falló el habilitado de %{conf_name} en %{node_name}"
 
 
-#: src/components/Notification/notifications.ts:108
+#: src/components/Notification/notifications.ts:126
 #, fuzzy
 #, fuzzy
 msgid "Disable stream %{name} from %{node} successfully"
 msgid "Disable stream %{name} from %{node} successfully"
 msgstr "Habilitado exitoso de %{conf_name} en %{node_name}"
 msgstr "Habilitado exitoso de %{conf_name} en %{node_name}"
@@ -1039,7 +1067,7 @@ msgstr ""
 "ejecutan en el host local."
 "ejecutan en el host local."
 
 
 #: src/views/site/site_list/SiteDuplicate.vue:72
 #: src/views/site/site_list/SiteDuplicate.vue:72
-#: src/views/site/site_list/SiteList.vue:158
+#: src/views/site/site_list/SiteList.vue:162
 #: src/views/stream/components/StreamDuplicate.vue:64
 #: src/views/stream/components/StreamDuplicate.vue:64
 #: src/views/stream/StreamList.vue:222
 #: src/views/stream/StreamList.vue:222
 msgid "Duplicate"
 msgid "Duplicate"
@@ -1107,62 +1135,62 @@ msgstr "Falló la habilitación"
 msgid "Enable HTTPS"
 msgid "Enable HTTPS"
 msgstr "Habilitar TLS"
 msgstr "Habilitar TLS"
 
 
-#: src/components/Notification/notifications.ts:53 src/language/constants.ts:54
+#: src/components/Notification/notifications.ts:71 src/language/constants.ts:54
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Site Error"
 msgid "Enable Remote Site Error"
 msgstr "Error al renombrar la configuración remota"
 msgstr "Error al renombrar la configuración remota"
 
 
-#: src/components/Notification/notifications.ts:61
+#: src/components/Notification/notifications.ts:79
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Site Maintenance Error"
 msgid "Enable Remote Site Maintenance Error"
 msgstr "Error al renombrar la configuración remota"
 msgstr "Error al renombrar la configuración remota"
 
 
-#: src/components/Notification/notifications.ts:65
+#: src/components/Notification/notifications.ts:83
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Site Maintenance Success"
 msgid "Enable Remote Site Maintenance Success"
 msgstr "Renombrar Configuración Remota Exitosa"
 msgstr "Renombrar Configuración Remota Exitosa"
 
 
-#: src/components/Notification/notifications.ts:57 src/language/constants.ts:53
+#: src/components/Notification/notifications.ts:75 src/language/constants.ts:53
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Site Success"
 msgid "Enable Remote Site Success"
 msgstr "Renombrar Configuración Remota Exitosa"
 msgstr "Renombrar Configuración Remota Exitosa"
 
 
-#: src/components/Notification/notifications.ts:111
+#: src/components/Notification/notifications.ts:129
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Stream Error"
 msgid "Enable Remote Stream Error"
 msgstr "Error al renombrar la configuración remota"
 msgstr "Error al renombrar la configuración remota"
 
 
-#: src/components/Notification/notifications.ts:115
+#: src/components/Notification/notifications.ts:133
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Stream Success"
 msgid "Enable Remote Stream Success"
 msgstr "Renombrar Configuración Remota Exitosa"
 msgstr "Renombrar Configuración Remota Exitosa"
 
 
-#: src/components/Notification/notifications.ts:62
+#: src/components/Notification/notifications.ts:80
 #, fuzzy
 #, fuzzy
 msgid "Enable site %{name} maintenance on %{node} failed"
 msgid "Enable site %{name} maintenance on %{node} failed"
 msgstr "Falló el habilitado de %{conf_name} en %{node_name}"
 msgstr "Falló el habilitado de %{conf_name} en %{node_name}"
 
 
-#: src/components/Notification/notifications.ts:66
+#: src/components/Notification/notifications.ts:84
 #, fuzzy
 #, fuzzy
 msgid "Enable site %{name} maintenance on %{node} successfully"
 msgid "Enable site %{name} maintenance on %{node} successfully"
 msgstr "Habilitado exitoso de %{conf_name} en %{node_name}"
 msgstr "Habilitado exitoso de %{conf_name} en %{node_name}"
 
 
-#: src/components/Notification/notifications.ts:54
+#: src/components/Notification/notifications.ts:72
 #, fuzzy
 #, fuzzy
 msgid "Enable site %{name} on %{node} failed"
 msgid "Enable site %{name} on %{node} failed"
 msgstr "Falló el habilitado de %{conf_name} en %{node_name}"
 msgstr "Falló el habilitado de %{conf_name} en %{node_name}"
 
 
-#: src/components/Notification/notifications.ts:58
+#: src/components/Notification/notifications.ts:76
 #, fuzzy
 #, fuzzy
 msgid "Enable site %{name} on %{node} successfully"
 msgid "Enable site %{name} on %{node} successfully"
 msgstr "Habilitado exitoso de %{conf_name} en %{node_name}"
 msgstr "Habilitado exitoso de %{conf_name} en %{node_name}"
 
 
-#: src/components/Notification/notifications.ts:112
+#: src/components/Notification/notifications.ts:130
 #, fuzzy
 #, fuzzy
 msgid "Enable stream %{name} on %{node} failed"
 msgid "Enable stream %{name} on %{node} failed"
 msgstr "Falló el habilitado de %{conf_name} en %{node_name}"
 msgstr "Falló el habilitado de %{conf_name} en %{node_name}"
 
 
-#: src/components/Notification/notifications.ts:116
+#: src/components/Notification/notifications.ts:134
 #, fuzzy
 #, fuzzy
 msgid "Enable stream %{name} on %{node} successfully"
 msgid "Enable stream %{name} on %{node} successfully"
 msgstr "Habilitado exitoso de %{conf_name} en %{node_name}"
 msgstr "Habilitado exitoso de %{conf_name} en %{node_name}"
@@ -1251,6 +1279,11 @@ msgstr "Vencido el: %{date}"
 msgid "Export"
 msgid "Export"
 msgstr "Exportar"
 msgstr "Exportar"
 
 
+#: src/views/preference/ExternalNotify.vue:10
+#: src/views/preference/Preference.vue:169
+msgid "External Notify"
+msgstr ""
+
 #: src/views/site/cert/components/ObtainCertLive.vue:94
 #: src/views/site/cert/components/ObtainCertLive.vue:94
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
 msgstr "Falla al obtener el certificado"
 msgstr "Falla al obtener el certificado"
@@ -1653,7 +1686,7 @@ msgstr "Inicio"
 msgid "Host"
 msgid "Host"
 msgstr "Host HTTP"
 msgstr "Host HTTP"
 
 
-#: src/views/preference/Preference.vue:174
+#: src/views/preference/Preference.vue:181
 #, fuzzy
 #, fuzzy
 msgid "HTTP"
 msgid "HTTP"
 msgstr "HTTP01"
 msgstr "HTTP01"
@@ -1716,12 +1749,12 @@ msgid "Import Certificate"
 msgstr "Importar Certificado"
 msgstr "Importar Certificado"
 
 
 #: src/views/nginx_log/NginxLogList.vue:137
 #: src/views/nginx_log/NginxLogList.vue:137
-#: src/views/site/site_list/SiteList.vue:128
+#: src/views/site/site_list/SiteList.vue:132
 msgid "Indexed"
 msgid "Indexed"
 msgstr ""
 msgstr ""
 
 
 #: src/views/nginx_log/NginxLogList.vue:134
 #: src/views/nginx_log/NginxLogList.vue:134
-#: src/views/site/site_list/SiteList.vue:125
+#: src/views/site/site_list/SiteList.vue:129
 msgid "Indexing..."
 msgid "Indexing..."
 msgstr ""
 msgstr ""
 
 
@@ -1803,6 +1836,11 @@ msgstr "Nombre de archivo inválido"
 msgid "Invalid folder name"
 msgid "Invalid folder name"
 msgstr "Nombre de carpeta inválido"
 msgstr "Nombre de carpeta inválido"
 
 
+#: src/constants/errors/notification.ts:3
+#, fuzzy
+msgid "Invalid notifier config"
+msgstr "Código 2FA o de recuperación inválido"
+
 #: src/constants/errors/user.ts:4
 #: src/constants/errors/user.ts:4
 #, fuzzy
 #, fuzzy
 msgid "Invalid otp code"
 msgid "Invalid otp code"
@@ -1865,6 +1903,10 @@ msgstr ""
 msgid "Key Type"
 msgid "Key Type"
 msgstr "Tipo llave"
 msgstr "Tipo llave"
 
 
+#: src/views/preference/components/ExternalNotify/columns.ts:29
+msgid "Language"
+msgstr ""
+
 #: src/views/system/Upgrade.vue:179
 #: src/views/system/Upgrade.vue:179
 msgid "Last checked at"
 msgid "Last checked at"
 msgstr "Comprobado por última vez el"
 msgstr "Comprobado por última vez el"
@@ -1963,7 +2005,7 @@ msgstr "Acceso exitoso"
 msgid "Logout successful"
 msgid "Logout successful"
 msgstr "Cierre de sesión exitoso"
 msgstr "Cierre de sesión exitoso"
 
 
-#: src/views/preference/Preference.vue:210
+#: src/views/preference/Preference.vue:217
 msgid "Logrotate"
 msgid "Logrotate"
 msgstr "Rotación de logs"
 msgstr "Rotación de logs"
 
 
@@ -2012,7 +2054,7 @@ msgstr ""
 msgid "Manage Configs"
 msgid "Manage Configs"
 msgstr "Administrar configuraciones"
 msgstr "Administrar configuraciones"
 
 
-#: src/routes/modules/sites.ts:10 src/views/site/site_list/SiteList.vue:121
+#: src/routes/modules/sites.ts:10 src/views/site/site_list/SiteList.vue:125
 msgid "Manage Sites"
 msgid "Manage Sites"
 msgstr "Administrar sitios"
 msgstr "Administrar sitios"
 
 
@@ -2088,7 +2130,7 @@ msgstr "Directiva multilínea"
 #: src/views/nginx_log/NginxLogList.vue:37
 #: src/views/nginx_log/NginxLogList.vue:37
 #: src/views/preference/components/AddPasskey.vue:75
 #: src/views/preference/components/AddPasskey.vue:75
 #: src/views/site/ngx_conf/NgxUpstream.vue:177
 #: src/views/site/ngx_conf/NgxUpstream.vue:177
-#: src/views/site/site_edit/RightSettings.vue:64
+#: src/views/site/site_edit/RightSettings.vue:63
 #: src/views/site/site_list/columns.tsx:17
 #: src/views/site/site_list/columns.tsx:17
 #: src/views/site/site_list/SiteDuplicate.vue:79
 #: src/views/site/site_list/SiteDuplicate.vue:79
 #: src/views/stream/components/RightSettings.vue:87
 #: src/views/stream/components/RightSettings.vue:87
@@ -2136,7 +2178,7 @@ msgstr "Se liberó una nueva versión"
 msgid "Next"
 msgid "Next"
 msgstr "Siguiente"
 msgstr "Siguiente"
 
 
-#: src/views/preference/Preference.vue:198
+#: src/views/preference/Preference.vue:205
 msgid "Nginx"
 msgid "Nginx"
 msgstr "Nginx"
 msgstr "Nginx"
 
 
@@ -2279,7 +2321,7 @@ msgstr "Error de análisis de configuración de Nginx"
 #: src/views/preference/CertSettings.vue:73
 #: src/views/preference/CertSettings.vue:73
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:97
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:97
 #: src/views/site/ngx_conf/LocationEditor.vue:88
 #: src/views/site/ngx_conf/LocationEditor.vue:88
-#: src/views/site/site_list/SiteList.vue:161
+#: src/views/site/site_list/SiteList.vue:165
 #: src/views/stream/StreamList.vue:225
 #: src/views/stream/StreamList.vue:225
 msgid "No"
 msgid "No"
 msgstr "No"
 msgstr "No"
@@ -2294,12 +2336,12 @@ msgstr "Acción"
 msgid "No records selected"
 msgid "No records selected"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/Preference.vue:168
+#: src/views/preference/Preference.vue:175
 #, fuzzy
 #, fuzzy
 msgid "Node"
 msgid "Node"
 msgstr "Nuevo nombre"
 msgstr "Nuevo nombre"
 
 
-#: src/views/site/site_edit/RightSettings.vue:67
+#: src/views/site/site_edit/RightSettings.vue:66
 #: src/views/site/site_list/columns.tsx:63
 #: src/views/site/site_list/columns.tsx:63
 #: src/views/stream/components/RightSettings.vue:90
 #: src/views/stream/components/RightSettings.vue:90
 #: src/views/stream/StreamList.vue:30
 #: src/views/stream/StreamList.vue:30
@@ -2344,7 +2386,7 @@ msgstr "No válido antes: %{date}"
 msgid "Note"
 msgid "Note"
 msgstr "Nota"
 msgstr "Nota"
 
 
-#: src/views/site/site_edit/RightSettings.vue:96
+#: src/views/site/site_edit/RightSettings.vue:95
 #: src/views/stream/components/RightSettings.vue:118
 #: src/views/stream/components/RightSettings.vue:118
 msgid ""
 msgid ""
 "Note, if the configuration file include other configurations or "
 "Note, if the configuration file include other configurations or "
@@ -2363,6 +2405,11 @@ msgstr "Notificación"
 msgid "Notifications"
 msgid "Notifications"
 msgstr "Notificaciones"
 msgstr "Notificaciones"
 
 
+#: src/constants/errors/notification.ts:2
+#, fuzzy
+msgid "Notifier not found"
+msgstr "Archivo no Encontrado"
+
 #: src/views/site/cert/components/ObtainCert.vue:182
 #: src/views/site/cert/components/ObtainCert.vue:182
 msgid "Obtain certificate"
 msgid "Obtain certificate"
 msgstr "Obtener certificado"
 msgstr "Obtener certificado"
@@ -2407,7 +2454,7 @@ msgstr "Ok"
 #: src/views/site/ngx_conf/NgxServer.vue:79
 #: src/views/site/ngx_conf/NgxServer.vue:79
 #: src/views/site/ngx_conf/NgxUpstream.vue:33
 #: src/views/site/ngx_conf/NgxUpstream.vue:33
 #: src/views/site/site_edit/components/SiteStatusSegmented.vue:121
 #: src/views/site/site_edit/components/SiteStatusSegmented.vue:121
-#: src/views/site/site_list/SiteList.vue:162
+#: src/views/site/site_list/SiteList.vue:166
 #: src/views/stream/components/RightSettings.vue:54
 #: src/views/stream/components/RightSettings.vue:54
 #: src/views/stream/StreamList.vue:226
 #: src/views/stream/StreamList.vue:226
 #: src/views/system/Backup/BackupCreator.vue:149
 #: src/views/system/Backup/BackupCreator.vue:149
@@ -2430,7 +2477,7 @@ msgstr "En línea"
 msgid "Only zip files are allowed"
 msgid "Only zip files are allowed"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/Preference.vue:204
+#: src/views/preference/Preference.vue:211
 msgid "OpenAI"
 msgid "OpenAI"
 msgstr "OpenAI"
 msgstr "OpenAI"
 
 
@@ -2583,7 +2630,7 @@ msgstr ""
 "luego seleccione una de las credenciales de aquí debajo para llamar a la API "
 "luego seleccione una de las credenciales de aquí debajo para llamar a la API "
 "del proveedor de DNS."
 "del proveedor de DNS."
 
 
-#: src/components/Notification/notifications.ts:138
+#: src/components/Notification/notifications.ts:156
 #: src/language/constants.ts:59
 #: src/language/constants.ts:59
 msgid ""
 msgid ""
 "Please generate new recovery codes in the preferences immediately to prevent "
 "Please generate new recovery codes in the preferences immediately to prevent "
@@ -2680,7 +2727,7 @@ msgstr "Acción"
 msgid "Pre-release"
 msgid "Pre-release"
 msgstr "Prelanzamiento"
 msgstr "Prelanzamiento"
 
 
-#: src/routes/modules/preference.ts:10 src/views/preference/Preference.vue:151
+#: src/routes/modules/preference.ts:10 src/views/preference/Preference.vue:152
 msgid "Preference"
 msgid "Preference"
 msgstr "Configuración"
 msgstr "Configuración"
 
 
@@ -2819,22 +2866,22 @@ msgstr "Recargar"
 msgid "Reload Nginx"
 msgid "Reload Nginx"
 msgstr "Recargando Nginx"
 msgstr "Recargando Nginx"
 
 
-#: src/components/Notification/notifications.ts:144
+#: src/components/Notification/notifications.ts:10
 #, fuzzy
 #, fuzzy
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgstr "Eliminar sitio: %{site_name}"
 msgstr "Eliminar sitio: %{site_name}"
 
 
-#: src/components/Notification/notifications.ts:148
+#: src/components/Notification/notifications.ts:14
 #, fuzzy
 #, fuzzy
 msgid "Reload Nginx on %{node} successfully"
 msgid "Reload Nginx on %{node} successfully"
 msgstr "Interfaz de usuario de Nginx actualizada en %{node} con éxito 🎉"
 msgstr "Interfaz de usuario de Nginx actualizada en %{node} con éxito 🎉"
 
 
-#: src/components/Notification/notifications.ts:143
+#: src/components/Notification/notifications.ts:9
 #, fuzzy
 #, fuzzy
 msgid "Reload Remote Nginx Error"
 msgid "Reload Remote Nginx Error"
 msgstr "Error al renombrar la configuración remota"
 msgstr "Error al renombrar la configuración remota"
 
 
-#: src/components/Notification/notifications.ts:147
+#: src/components/Notification/notifications.ts:13
 #, fuzzy
 #, fuzzy
 msgid "Reload Remote Nginx Success"
 msgid "Reload Remote Nginx Success"
 msgstr "Renombrar Configuración Remota Exitosa"
 msgstr "Renombrar Configuración Remota Exitosa"
@@ -2873,59 +2920,59 @@ msgstr "Eliminado con éxito"
 msgid "Rename"
 msgid "Rename"
 msgstr "Renombrar"
 msgstr "Renombrar"
 
 
-#: src/components/Notification/notifications.ts:28
+#: src/components/Notification/notifications.ts:46
 #, fuzzy
 #, fuzzy
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} failed"
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} failed"
 msgstr "Renombrar %{orig_path} a %{new_path} en %{env_name} con éxito"
 msgstr "Renombrar %{orig_path} a %{new_path} en %{env_name} con éxito"
 
 
-#: src/components/Notification/notifications.ts:32
+#: src/components/Notification/notifications.ts:50
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} successfully"
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} successfully"
 msgstr "Renombrar %{orig_path} a %{new_path} en %{env_name} con éxito"
 msgstr "Renombrar %{orig_path} a %{new_path} en %{env_name} con éxito"
 
 
-#: src/components/Notification/notifications.ts:27 src/language/constants.ts:42
+#: src/components/Notification/notifications.ts:45 src/language/constants.ts:42
 msgid "Rename Remote Config Error"
 msgid "Rename Remote Config Error"
 msgstr "Error al renombrar la configuración remota"
 msgstr "Error al renombrar la configuración remota"
 
 
-#: src/components/Notification/notifications.ts:31 src/language/constants.ts:41
+#: src/components/Notification/notifications.ts:49 src/language/constants.ts:41
 msgid "Rename Remote Config Success"
 msgid "Rename Remote Config Success"
 msgstr "Renombrar Configuración Remota Exitosa"
 msgstr "Renombrar Configuración Remota Exitosa"
 
 
-#: src/components/Notification/notifications.ts:77 src/language/constants.ts:56
+#: src/components/Notification/notifications.ts:95 src/language/constants.ts:56
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Site Error"
 msgid "Rename Remote Site Error"
 msgstr "Error al renombrar la configuración remota"
 msgstr "Error al renombrar la configuración remota"
 
 
-#: src/components/Notification/notifications.ts:81 src/language/constants.ts:55
+#: src/components/Notification/notifications.ts:99 src/language/constants.ts:55
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Site Success"
 msgid "Rename Remote Site Success"
 msgstr "Renombrar Configuración Remota Exitosa"
 msgstr "Renombrar Configuración Remota Exitosa"
 
 
-#: src/components/Notification/notifications.ts:119
+#: src/components/Notification/notifications.ts:137
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Stream Error"
 msgid "Rename Remote Stream Error"
 msgstr "Error al renombrar la configuración remota"
 msgstr "Error al renombrar la configuración remota"
 
 
-#: src/components/Notification/notifications.ts:123
+#: src/components/Notification/notifications.ts:141
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Stream Success"
 msgid "Rename Remote Stream Success"
 msgstr "Renombrar Configuración Remota Exitosa"
 msgstr "Renombrar Configuración Remota Exitosa"
 
 
-#: src/components/Notification/notifications.ts:78
+#: src/components/Notification/notifications.ts:96
 #, fuzzy
 #, fuzzy
 msgid "Rename site %{name} to %{new_name} on %{node} failed"
 msgid "Rename site %{name} to %{new_name} on %{node} failed"
 msgstr "Renombrar %{orig_path} a %{new_path} en %{env_name} con éxito"
 msgstr "Renombrar %{orig_path} a %{new_path} en %{env_name} con éxito"
 
 
-#: src/components/Notification/notifications.ts:82
+#: src/components/Notification/notifications.ts:100
 #, fuzzy
 #, fuzzy
 msgid "Rename site %{name} to %{new_name} on %{node} successfully"
 msgid "Rename site %{name} to %{new_name} on %{node} successfully"
 msgstr "Renombrar %{orig_path} a %{new_path} en %{env_name} con éxito"
 msgstr "Renombrar %{orig_path} a %{new_path} en %{env_name} con éxito"
 
 
-#: src/components/Notification/notifications.ts:120
+#: src/components/Notification/notifications.ts:138
 #, fuzzy
 #, fuzzy
 msgid "Rename stream %{name} to %{new_name} on %{node} failed"
 msgid "Rename stream %{name} to %{new_name} on %{node} failed"
 msgstr "Renombrar %{orig_path} a %{new_path} en %{env_name} con éxito"
 msgstr "Renombrar %{orig_path} a %{new_path} en %{env_name} con éxito"
 
 
-#: src/components/Notification/notifications.ts:124
+#: src/components/Notification/notifications.ts:142
 #, fuzzy
 #, fuzzy
 msgid "Rename stream %{name} to %{new_name} on %{node} successfully"
 msgid "Rename stream %{name} to %{new_name} on %{node} successfully"
 msgstr "Renombrar %{orig_path} a %{new_path} en %{env_name} con éxito"
 msgstr "Renombrar %{orig_path} a %{new_path} en %{env_name} con éxito"
@@ -2986,22 +3033,22 @@ msgstr "Reiniciar"
 msgid "Restart Nginx"
 msgid "Restart Nginx"
 msgstr "Reiniciando"
 msgstr "Reiniciando"
 
 
-#: src/components/Notification/notifications.ts:152
+#: src/components/Notification/notifications.ts:18
 #, fuzzy
 #, fuzzy
 msgid "Restart Nginx on %{node} failed, response: %{resp}"
 msgid "Restart Nginx on %{node} failed, response: %{resp}"
 msgstr "Habilitado exitoso de %{conf_name} en %{node_name}"
 msgstr "Habilitado exitoso de %{conf_name} en %{node_name}"
 
 
-#: src/components/Notification/notifications.ts:156
+#: src/components/Notification/notifications.ts:22
 #, fuzzy
 #, fuzzy
 msgid "Restart Nginx on %{node} successfully"
 msgid "Restart Nginx on %{node} successfully"
 msgstr "Interfaz de usuario de Nginx actualizada en %{node} con éxito 🎉"
 msgstr "Interfaz de usuario de Nginx actualizada en %{node} con éxito 🎉"
 
 
-#: src/components/Notification/notifications.ts:151
+#: src/components/Notification/notifications.ts:17
 #, fuzzy
 #, fuzzy
 msgid "Restart Remote Nginx Error"
 msgid "Restart Remote Nginx Error"
 msgstr "Error al renombrar la configuración remota"
 msgstr "Error al renombrar la configuración remota"
 
 
-#: src/components/Notification/notifications.ts:155
+#: src/components/Notification/notifications.ts:21
 #, fuzzy
 #, fuzzy
 msgid "Restart Remote Nginx Success"
 msgid "Restart Remote Nginx Success"
 msgstr "Renombrar Configuración Remota Exitosa"
 msgstr "Renombrar Configuración Remota Exitosa"
@@ -3068,7 +3115,7 @@ msgstr "Corriendo"
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/ConfigEditor.vue:271
 #: src/views/config/ConfigEditor.vue:271
 #: src/views/preference/components/Passkey.vue:130
 #: src/views/preference/components/Passkey.vue:130
-#: src/views/preference/Preference.vue:221
+#: src/views/preference/Preference.vue:228
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:127
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:127
 #: src/views/site/site_edit/components/ConfigName.vue:52
 #: src/views/site/site_edit/components/ConfigName.vue:52
 #: src/views/site/site_edit/SiteEdit.vue:292
 #: src/views/site/site_edit/SiteEdit.vue:292
@@ -3086,42 +3133,44 @@ msgstr "Guardar Directiva"
 msgid "Save error %{msg}"
 msgid "Save error %{msg}"
 msgstr "Error al guardar %{msg}"
 msgstr "Error al guardar %{msg}"
 
 
-#: src/components/Notification/notifications.ts:85 src/language/constants.ts:48
+#: src/components/Notification/notifications.ts:103
+#: src/language/constants.ts:48
 #, fuzzy
 #, fuzzy
 msgid "Save Remote Site Error"
 msgid "Save Remote Site Error"
 msgstr "Error al renombrar la configuración remota"
 msgstr "Error al renombrar la configuración remota"
 
 
-#: src/components/Notification/notifications.ts:89 src/language/constants.ts:47
+#: src/components/Notification/notifications.ts:107
+#: src/language/constants.ts:47
 #, fuzzy
 #, fuzzy
 msgid "Save Remote Site Success"
 msgid "Save Remote Site Success"
 msgstr "Renombrar Configuración Remota Exitosa"
 msgstr "Renombrar Configuración Remota Exitosa"
 
 
-#: src/components/Notification/notifications.ts:127
+#: src/components/Notification/notifications.ts:145
 #, fuzzy
 #, fuzzy
 msgid "Save Remote Stream Error"
 msgid "Save Remote Stream Error"
 msgstr "Error al renombrar la configuración remota"
 msgstr "Error al renombrar la configuración remota"
 
 
-#: src/components/Notification/notifications.ts:131
+#: src/components/Notification/notifications.ts:149
 #, fuzzy
 #, fuzzy
 msgid "Save Remote Stream Success"
 msgid "Save Remote Stream Success"
 msgstr "Renombrar Configuración Remota Exitosa"
 msgstr "Renombrar Configuración Remota Exitosa"
 
 
-#: src/components/Notification/notifications.ts:86
+#: src/components/Notification/notifications.ts:104
 #, fuzzy
 #, fuzzy
 msgid "Save site %{name} to %{node} failed"
 msgid "Save site %{name} to %{node} failed"
 msgstr "Duplicado con éxito de %{conf_name} a %{node_name}"
 msgstr "Duplicado con éxito de %{conf_name} a %{node_name}"
 
 
-#: src/components/Notification/notifications.ts:90
+#: src/components/Notification/notifications.ts:108
 #, fuzzy
 #, fuzzy
 msgid "Save site %{name} to %{node} successfully"
 msgid "Save site %{name} to %{node} successfully"
 msgstr "Duplicado con éxito de %{conf_name} a %{node_name}"
 msgstr "Duplicado con éxito de %{conf_name} a %{node_name}"
 
 
-#: src/components/Notification/notifications.ts:128
+#: src/components/Notification/notifications.ts:146
 #, fuzzy
 #, fuzzy
 msgid "Save stream %{name} to %{node} failed"
 msgid "Save stream %{name} to %{node} failed"
 msgstr "Falló el desplegado de %{conf_name} a %{node_name}"
 msgstr "Falló el desplegado de %{conf_name} a %{node_name}"
 
 
-#: src/components/Notification/notifications.ts:132
+#: src/components/Notification/notifications.ts:150
 #, fuzzy
 #, fuzzy
 msgid "Save stream %{name} to %{node} successfully"
 msgid "Save stream %{name} to %{node} successfully"
 msgstr "Duplicado con éxito de %{conf_name} a %{node_name}"
 msgstr "Duplicado con éxito de %{conf_name} a %{node_name}"
@@ -3129,7 +3178,7 @@ msgstr "Duplicado con éxito de %{conf_name} a %{node_name}"
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:47
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:47
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:97
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:97
 #: src/views/certificate/CertificateEditor.vue:49
 #: src/views/certificate/CertificateEditor.vue:49
-#: src/views/preference/Preference.vue:123
+#: src/views/preference/Preference.vue:124
 msgid "Save successfully"
 msgid "Save successfully"
 msgstr "Guardado con éxito"
 msgstr "Guardado con éxito"
 
 
@@ -3151,6 +3200,10 @@ msgstr ""
 msgid "SDK"
 msgid "SDK"
 msgstr "SDK"
 msgstr "SDK"
 
 
+#: src/views/preference/components/ExternalNotify/dingtalk.ts:13
+msgid "Secret (Optional)"
+msgstr ""
+
 #: src/views/preference/components/TOTP.vue:109
 #: src/views/preference/components/TOTP.vue:109
 msgid "Secret has been copied"
 msgid "Secret has been copied"
 msgstr "El secreto ha sido copiado"
 msgstr "El secreto ha sido copiado"
@@ -3182,7 +3235,7 @@ msgstr ""
 msgid "Send"
 msgid "Send"
 msgstr "Enviado"
 msgstr "Enviado"
 
 
-#: src/views/preference/Preference.vue:156
+#: src/views/preference/Preference.vue:157
 #, fuzzy
 #, fuzzy
 msgid "Server"
 msgid "Server"
 msgstr "Información del servidor"
 msgstr "Información del servidor"
@@ -3191,6 +3244,11 @@ msgstr "Información del servidor"
 msgid "Server Info"
 msgid "Server Info"
 msgstr "Información del servidor"
 msgstr "Información del servidor"
 
 
+#: src/views/preference/components/ExternalNotify/bark.ts:13
+#, fuzzy
+msgid "Server URL"
+msgstr "Información del servidor"
+
 #: src/views/site/cert/components/ObtainCert.vue:107
 #: src/views/site/cert/components/ObtainCert.vue:107
 msgid "server_name not found in directives"
 msgid "server_name not found in directives"
 msgstr "No se encuentra server_name en las directivas"
 msgstr "No se encuentra server_name en las directivas"
@@ -3365,7 +3423,7 @@ msgstr ""
 #: src/views/certificate/ACMEUser.vue:65
 #: src/views/certificate/ACMEUser.vue:65
 #: src/views/certificate/CertificateList/certColumns.tsx:65
 #: src/views/certificate/CertificateList/certColumns.tsx:65
 #: src/views/environments/list/envColumns.tsx:44
 #: src/views/environments/list/envColumns.tsx:44
-#: src/views/site/site_edit/RightSettings.vue:56
+#: src/views/site/site_edit/RightSettings.vue:55
 #: src/views/site/site_list/columns.tsx:80 src/views/stream/StreamList.vue:47
 #: src/views/site/site_list/columns.tsx:80 src/views/stream/StreamList.vue:47
 msgid "Status"
 msgid "Status"
 msgstr "Estado"
 msgstr "Estado"
@@ -3441,38 +3499,38 @@ msgstr "Sincronizar"
 msgid "Sync Certificate"
 msgid "Sync Certificate"
 msgstr "Sincronizar Certificado"
 msgstr "Sincronizar Certificado"
 
 
-#: src/components/Notification/notifications.ts:10
+#: src/components/Notification/notifications.ts:28
 #, fuzzy
 #, fuzzy
 msgid "Sync Certificate %{cert_name} to %{env_name} failed"
 msgid "Sync Certificate %{cert_name} to %{env_name} failed"
 msgstr "Sincronización del Certificado %{cert_name} a %{env_name} exitosa"
 msgstr "Sincronización del Certificado %{cert_name} a %{env_name} exitosa"
 
 
-#: src/components/Notification/notifications.ts:14
+#: src/components/Notification/notifications.ts:32
 msgid "Sync Certificate %{cert_name} to %{env_name} successfully"
 msgid "Sync Certificate %{cert_name} to %{env_name} successfully"
 msgstr "Sincronización del Certificado %{cert_name} a %{env_name} exitosa"
 msgstr "Sincronización del Certificado %{cert_name} a %{env_name} exitosa"
 
 
-#: src/components/Notification/notifications.ts:9 src/language/constants.ts:39
+#: src/components/Notification/notifications.ts:27 src/language/constants.ts:39
 msgid "Sync Certificate Error"
 msgid "Sync Certificate Error"
 msgstr "Error de Certificado de Sincronización"
 msgstr "Error de Certificado de Sincronización"
 
 
-#: src/components/Notification/notifications.ts:13 src/language/constants.ts:38
+#: src/components/Notification/notifications.ts:31 src/language/constants.ts:38
 msgid "Sync Certificate Success"
 msgid "Sync Certificate Success"
 msgstr "Sincronización del Certificado exitosa"
 msgstr "Sincronización del Certificado exitosa"
 
 
-#: src/components/Notification/notifications.ts:20
+#: src/components/Notification/notifications.ts:38
 #, fuzzy
 #, fuzzy
 msgid "Sync config %{config_name} to %{env_name} failed"
 msgid "Sync config %{config_name} to %{env_name} failed"
 msgstr "Sincronizar configuración %{config_name} con %{env_name} exitosamente"
 msgstr "Sincronizar configuración %{config_name} con %{env_name} exitosamente"
 
 
-#: src/components/Notification/notifications.ts:24
+#: src/components/Notification/notifications.ts:42
 #, fuzzy
 #, fuzzy
 msgid "Sync config %{config_name} to %{env_name} successfully"
 msgid "Sync config %{config_name} to %{env_name} successfully"
 msgstr "Sincronizar configuración %{config_name} con %{env_name} exitosamente"
 msgstr "Sincronizar configuración %{config_name} con %{env_name} exitosamente"
 
 
-#: src/components/Notification/notifications.ts:19 src/language/constants.ts:45
+#: src/components/Notification/notifications.ts:37 src/language/constants.ts:45
 msgid "Sync Config Error"
 msgid "Sync Config Error"
 msgstr "Error de Configuración de Sincronización"
 msgstr "Error de Configuración de Sincronización"
 
 
-#: src/components/Notification/notifications.ts:23 src/language/constants.ts:44
+#: src/components/Notification/notifications.ts:41 src/language/constants.ts:44
 msgid "Sync Config Success"
 msgid "Sync Config Success"
 msgstr "Configuración de sincronización exitosa"
 msgstr "Configuración de sincronización exitosa"
 
 
@@ -3482,8 +3540,8 @@ msgstr "Configuración de sincronización exitosa"
 msgid "Sync Nodes"
 msgid "Sync Nodes"
 msgstr "Sincronizar con"
 msgstr "Sincronizar con"
 
 
-#: src/views/site/site_edit/RightSettings.vue:102
-#: src/views/site/site_edit/RightSettings.vue:89
+#: src/views/site/site_edit/RightSettings.vue:101
+#: src/views/site/site_edit/RightSettings.vue:88
 #: src/views/stream/components/RightSettings.vue:111
 #: src/views/stream/components/RightSettings.vue:111
 #: src/views/stream/components/RightSettings.vue:124
 #: src/views/stream/components/RightSettings.vue:124
 #, fuzzy
 #, fuzzy
@@ -3494,7 +3552,7 @@ msgstr "Sincronizar Certificado"
 msgid "Sync to"
 msgid "Sync to"
 msgstr "Sincronizar con"
 msgstr "Sincronizar con"
 
 
-#: src/views/site/site_edit/RightSettings.vue:86
+#: src/views/site/site_edit/RightSettings.vue:85
 #: src/views/stream/components/RightSettings.vue:108
 #: src/views/stream/components/RightSettings.vue:108
 msgid "Synchronization"
 msgid "Synchronization"
 msgstr "Sincronización"
 msgstr "Sincronización"
@@ -3527,7 +3585,11 @@ msgstr "Nginx reiniciado con éxito"
 msgid "Task not found"
 msgid "Task not found"
 msgstr "Archivo no Encontrado"
 msgstr "Archivo no Encontrado"
 
 
-#: src/routes/modules/terminal.ts:10 src/views/preference/Preference.vue:180
+#: src/views/preference/components/ExternalNotify/telegram.ts:5
+msgid "Telegram"
+msgstr ""
+
+#: src/routes/modules/terminal.ts:10 src/views/preference/Preference.vue:187
 #: src/views/terminal/Terminal.vue:129
 #: src/views/terminal/Terminal.vue:129
 msgid "Terminal"
 msgid "Terminal"
 msgstr "Terminal"
 msgstr "Terminal"
@@ -3808,6 +3870,7 @@ msgstr "Se requiere autenticación de dos factores"
 #: src/views/certificate/CertificateList/certColumns.tsx:25
 #: src/views/certificate/CertificateList/certColumns.tsx:25
 #: src/views/nginx_log/NginxLogList.vue:21
 #: src/views/nginx_log/NginxLogList.vue:21
 #: src/views/notification/notificationColumns.tsx:9
 #: src/views/notification/notificationColumns.tsx:9
+#: src/views/preference/components/ExternalNotify/columns.ts:17
 msgid "Type"
 msgid "Type"
 msgstr "Tipo"
 msgstr "Tipo"
 
 
@@ -3825,7 +3888,7 @@ msgstr "Actualización exitosa"
 #: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:325
 #: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:325
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/environments/list/envColumns.tsx:90
-#: src/views/site/site_edit/RightSettings.vue:76
+#: src/views/site/site_edit/RightSettings.vue:75
 #: src/views/site/site_list/columns.tsx:110
 #: src/views/site/site_list/columns.tsx:110
 #: src/views/stream/components/RightSettings.vue:99
 #: src/views/stream/components/RightSettings.vue:99
 #: src/views/stream/StreamList.vue:67 src/views/user/userColumns.tsx:54
 #: src/views/stream/StreamList.vue:67 src/views/user/userColumns.tsx:54
@@ -3990,7 +4053,7 @@ msgstr ""
 "los usuarios al iniciarse. Por lo general, no habilite esta opción a menos "
 "los usuarios al iniciarse. Por lo general, no habilite esta opción a menos "
 "que se encuentre en un entorno de desarrollo y utilice Pebble como CA."
 "que se encuentre en un entorno de desarrollo y utilice Pebble como CA."
 
 
-#: src/views/site/site_edit/RightSettings.vue:92
+#: src/views/site/site_edit/RightSettings.vue:91
 #, fuzzy
 #, fuzzy
 msgid ""
 msgid ""
 "When you enable/disable, delete, or save this site, the nodes set in the "
 "When you enable/disable, delete, or save this site, the nodes set in the "
@@ -4332,6 +4395,3 @@ msgstr "Sus llaves de acceso"
 #~ msgstr ""
 #~ msgstr ""
 #~ "Si se deben configurar las expresiones regulares de API para que se "
 #~ "Si se deben configurar las expresiones regulares de API para que se "
 #~ "sincronicen con este entorno"
 #~ "sincronicen con este entorno"
-
-#~ msgid "Token"
-#~ msgstr "Token"

+ 165 - 106
app/src/language/fr_FR/app.po

@@ -35,6 +35,11 @@ msgstr "Journaux d'accès"
 msgid "Access Logs"
 msgid "Access Logs"
 msgstr "Journaux d'accès"
 msgstr "Journaux d'accès"
 
 
+#: src/views/preference/components/ExternalNotify/dingtalk.ts:9
+#, fuzzy
+msgid "Access Token"
+msgstr "Journaux d'accès"
+
 #: src/routes/modules/certificates.ts:20 src/views/certificate/ACMEUser.vue:113
 #: src/routes/modules/certificates.ts:20 src/views/certificate/ACMEUser.vue:113
 #: src/views/certificate/ACMEUserSelector.vue:85
 #: src/views/certificate/ACMEUserSelector.vue:85
 #, fuzzy
 #, fuzzy
@@ -50,6 +55,7 @@ msgstr "Nom d'utilisateur"
 #: src/views/nginx_log/NginxLogList.vue:53
 #: src/views/nginx_log/NginxLogList.vue:53
 #: src/views/notification/notificationColumns.tsx:66
 #: src/views/notification/notificationColumns.tsx:66
 #: src/views/preference/AuthSettings.vue:30
 #: src/views/preference/AuthSettings.vue:30
+#: src/views/preference/components/ExternalNotify/columns.ts:46
 #: src/views/site/site_list/columns.tsx:117 src/views/stream/StreamList.vue:74
 #: src/views/site/site_list/columns.tsx:117 src/views/stream/StreamList.vue:74
 #: src/views/user/userColumns.tsx:60
 #: src/views/user/userColumns.tsx:60
 msgid "Action"
 msgid "Action"
@@ -119,7 +125,7 @@ msgstr ""
 msgid "All"
 msgid "All"
 msgstr "Tous"
 msgstr "Tous"
 
 
-#: src/components/Notification/notifications.ts:137
+#: src/components/Notification/notifications.ts:155
 #: src/language/constants.ts:58
 #: src/language/constants.ts:58
 msgid "All Recovery Codes Have Been Used"
 msgid "All Recovery Codes Have Been Used"
 msgstr "Tous les codes de récupération ont été utilisés"
 msgstr "Tous les codes de récupération ont été utilisés"
@@ -146,7 +152,7 @@ msgstr "Jeton d'API"
 msgid "API Type"
 msgid "API Type"
 msgstr "Jeton d'API"
 msgstr "Jeton d'API"
 
 
-#: src/views/preference/Preference.vue:162
+#: src/views/preference/Preference.vue:163
 #, fuzzy
 #, fuzzy
 msgid "App"
 msgid "App"
 msgstr "Appliquer"
 msgstr "Appliquer"
@@ -210,7 +216,7 @@ msgstr "Etes-vous sûr que vous voulez supprimer ?"
 msgid "Are you sure you want to delete this item?"
 msgid "Are you sure you want to delete this item?"
 msgstr "Etes-vous sûr que vous voulez supprimer ?"
 msgstr "Etes-vous sûr que vous voulez supprimer ?"
 
 
-#: src/views/site/site_list/SiteList.vue:163
+#: src/views/site/site_list/SiteList.vue:167
 #: src/views/stream/StreamList.vue:227
 #: src/views/stream/StreamList.vue:227
 msgid "Are you sure you want to delete?"
 msgid "Are you sure you want to delete?"
 msgstr "Etes-vous sûr que vous voulez supprimer ?"
 msgstr "Etes-vous sûr que vous voulez supprimer ?"
@@ -260,7 +266,7 @@ msgstr "Tenter de corriger"
 msgid "Attempts"
 msgid "Attempts"
 msgstr "Tentatives"
 msgstr "Tentatives"
 
 
-#: src/views/preference/Preference.vue:186
+#: src/views/preference/Preference.vue:193
 #, fuzzy
 #, fuzzy
 msgid "Auth"
 msgid "Auth"
 msgstr "Autheur"
 msgstr "Autheur"
@@ -345,12 +351,16 @@ msgstr "IPs bannies"
 msgid "Banned Until"
 msgid "Banned Until"
 msgstr "Banni durant"
 msgstr "Banni durant"
 
 
+#: src/views/preference/components/ExternalNotify/bark.ts:5
+msgid "Bark"
+msgstr ""
+
 #: src/views/site/site_add/SiteAdd.vue:95
 #: src/views/site/site_add/SiteAdd.vue:95
 msgid "Base information"
 msgid "Base information"
 msgstr "Information générale"
 msgstr "Information générale"
 
 
 #: src/views/config/ConfigEditor.vue:290
 #: src/views/config/ConfigEditor.vue:290
-#: src/views/site/site_edit/RightSettings.vue:53
+#: src/views/site/site_edit/RightSettings.vue:52
 #: src/views/stream/components/RightSettings.vue:79
 #: src/views/stream/components/RightSettings.vue:79
 msgid "Basic"
 msgid "Basic"
 msgstr "Basique"
 msgstr "Basique"
@@ -385,6 +395,11 @@ msgstr ""
 msgid "Block is nil"
 msgid "Block is nil"
 msgstr ""
 msgstr ""
 
 
+#: src/views/preference/components/ExternalNotify/telegram.ts:9
+#, fuzzy
+msgid "Bot Token"
+msgstr "Jeton d'API"
+
 #: src/views/system/About.vue:55
 #: src/views/system/About.vue:55
 msgid "Build with"
 msgid "Build with"
 msgstr "Build avec"
 msgstr "Build avec"
@@ -425,7 +440,7 @@ msgstr ""
 msgid "Cannot remove initial user"
 msgid "Cannot remove initial user"
 msgstr "Impossible de retirer l'utilisateur initial"
 msgstr "Impossible de retirer l'utilisateur initial"
 
 
-#: src/views/preference/Preference.vue:192
+#: src/views/preference/Preference.vue:199
 #, fuzzy
 #, fuzzy
 msgid "Cert"
 msgid "Cert"
 msgstr "Auto Cert"
 msgstr "Auto Cert"
@@ -504,6 +519,10 @@ msgstr "Changer de certificat"
 msgid "Channel"
 msgid "Channel"
 msgstr "Canal"
 msgstr "Canal"
 
 
+#: src/views/preference/components/ExternalNotify/telegram.ts:13
+msgid "Chat ID"
+msgstr ""
+
 #: src/views/system/Upgrade.vue:185
 #: src/views/system/Upgrade.vue:185
 msgid "Check again"
 msgid "Check again"
 msgstr "Revérifier"
 msgstr "Revérifier"
@@ -708,6 +727,7 @@ msgstr ""
 
 
 #: src/views/environments/group/columns.ts:31
 #: src/views/environments/group/columns.ts:31
 #: src/views/notification/notificationColumns.tsx:59
 #: src/views/notification/notificationColumns.tsx:59
+#: src/views/preference/components/ExternalNotify/columns.ts:41
 #: src/views/preference/components/Passkey.vue:95
 #: src/views/preference/components/Passkey.vue:95
 #: src/views/user/userColumns.tsx:48
 #: src/views/user/userColumns.tsx:48
 msgid "Created at"
 msgid "Created at"
@@ -782,7 +802,7 @@ msgstr "Description"
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/views/site/ngx_conf/NgxServer.vue:110
 #: src/views/site/ngx_conf/NgxServer.vue:110
 #: src/views/site/ngx_conf/NgxUpstream.vue:128
 #: src/views/site/ngx_conf/NgxUpstream.vue:128
-#: src/views/site/site_list/SiteList.vue:172
+#: src/views/site/site_list/SiteList.vue:176
 #: src/views/stream/StreamList.vue:236
 #: src/views/stream/StreamList.vue:236
 msgid "Delete"
 msgid "Delete"
 msgstr "Supprimer"
 msgstr "Supprimer"
@@ -792,46 +812,46 @@ msgstr "Supprimer"
 msgid "Delete Permanently"
 msgid "Delete Permanently"
 msgstr "Supprimer définitivement"
 msgstr "Supprimer définitivement"
 
 
-#: src/components/Notification/notifications.ts:37 src/language/constants.ts:50
+#: src/components/Notification/notifications.ts:55 src/language/constants.ts:50
 #, fuzzy
 #, fuzzy
 msgid "Delete Remote Site Error"
 msgid "Delete Remote Site Error"
 msgstr "Changer de certificat"
 msgstr "Changer de certificat"
 
 
-#: src/components/Notification/notifications.ts:41 src/language/constants.ts:49
+#: src/components/Notification/notifications.ts:59 src/language/constants.ts:49
 #, fuzzy
 #, fuzzy
 msgid "Delete Remote Site Success"
 msgid "Delete Remote Site Success"
 msgstr "Changer de certificat"
 msgstr "Changer de certificat"
 
 
-#: src/components/Notification/notifications.ts:95
+#: src/components/Notification/notifications.ts:113
 #, fuzzy
 #, fuzzy
 msgid "Delete Remote Stream Error"
 msgid "Delete Remote Stream Error"
 msgstr "Changer de certificat"
 msgstr "Changer de certificat"
 
 
-#: src/components/Notification/notifications.ts:99
+#: src/components/Notification/notifications.ts:117
 #, fuzzy
 #, fuzzy
 msgid "Delete Remote Stream Success"
 msgid "Delete Remote Stream Success"
 msgstr "Changer de certificat"
 msgstr "Changer de certificat"
 
 
-#: src/components/Notification/notifications.ts:38
+#: src/components/Notification/notifications.ts:56
 #, fuzzy
 #, fuzzy
 msgid "Delete site %{name} from %{node} failed"
 msgid "Delete site %{name} from %{node} failed"
 msgstr "Dupliqué avec succès"
 msgstr "Dupliqué avec succès"
 
 
-#: src/components/Notification/notifications.ts:42
+#: src/components/Notification/notifications.ts:60
 #, fuzzy
 #, fuzzy
 msgid "Delete site %{name} from %{node} successfully"
 msgid "Delete site %{name} from %{node} successfully"
 msgstr "Dupliqué avec succès"
 msgstr "Dupliqué avec succès"
 
 
-#: src/views/site/site_list/SiteList.vue:94
+#: src/views/site/site_list/SiteList.vue:98
 msgid "Delete site: %{site_name}"
 msgid "Delete site: %{site_name}"
 msgstr "Supprimer le site : %{site_name}"
 msgstr "Supprimer le site : %{site_name}"
 
 
-#: src/components/Notification/notifications.ts:96
+#: src/components/Notification/notifications.ts:114
 #, fuzzy
 #, fuzzy
 msgid "Delete stream %{name} from %{node} failed"
 msgid "Delete stream %{name} from %{node} failed"
 msgstr "Dupliqué avec succès"
 msgstr "Dupliqué avec succès"
 
 
-#: src/components/Notification/notifications.ts:100
+#: src/components/Notification/notifications.ts:118
 #, fuzzy
 #, fuzzy
 msgid "Delete stream %{name} from %{node} successfully"
 msgid "Delete stream %{name} from %{node} successfully"
 msgstr "Dupliqué avec succès"
 msgstr "Dupliqué avec succès"
@@ -871,6 +891,14 @@ msgstr "Détails"
 msgid "Development Mode"
 msgid "Development Mode"
 msgstr "Mode développement"
 msgstr "Mode développement"
 
 
+#: src/views/preference/components/ExternalNotify/bark.ts:9
+msgid "Device Key"
+msgstr ""
+
+#: src/views/preference/components/ExternalNotify/dingtalk.ts:5
+msgid "DingTalk"
+msgstr ""
+
 #: src/views/site/ngx_conf/directive/DirectiveAdd.vue:89
 #: src/views/site/ngx_conf/directive/DirectiveAdd.vue:89
 msgid "Directive"
 msgid "Directive"
 msgstr "Directive"
 msgstr "Directive"
@@ -906,62 +934,62 @@ msgstr "Désactivé"
 msgid "Disable auto-renewal failed for %{name}"
 msgid "Disable auto-renewal failed for %{name}"
 msgstr "La désactivation du renouvellement automatique a échoué pour %{name}"
 msgstr "La désactivation du renouvellement automatique a échoué pour %{name}"
 
 
-#: src/components/Notification/notifications.ts:45 src/language/constants.ts:52
+#: src/components/Notification/notifications.ts:63 src/language/constants.ts:52
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Site Error"
 msgid "Disable Remote Site Error"
 msgstr "Changer de certificat"
 msgstr "Changer de certificat"
 
 
-#: src/components/Notification/notifications.ts:69
+#: src/components/Notification/notifications.ts:87
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Site Maintenance Error"
 msgid "Disable Remote Site Maintenance Error"
 msgstr "Changer de certificat"
 msgstr "Changer de certificat"
 
 
-#: src/components/Notification/notifications.ts:73
+#: src/components/Notification/notifications.ts:91
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Site Maintenance Success"
 msgid "Disable Remote Site Maintenance Success"
 msgstr "Changer de certificat"
 msgstr "Changer de certificat"
 
 
-#: src/components/Notification/notifications.ts:49 src/language/constants.ts:51
+#: src/components/Notification/notifications.ts:67 src/language/constants.ts:51
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Site Success"
 msgid "Disable Remote Site Success"
 msgstr "Changer de certificat"
 msgstr "Changer de certificat"
 
 
-#: src/components/Notification/notifications.ts:103
+#: src/components/Notification/notifications.ts:121
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Stream Error"
 msgid "Disable Remote Stream Error"
 msgstr "Changer de certificat"
 msgstr "Changer de certificat"
 
 
-#: src/components/Notification/notifications.ts:107
+#: src/components/Notification/notifications.ts:125
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Stream Success"
 msgid "Disable Remote Stream Success"
 msgstr "Changer de certificat"
 msgstr "Changer de certificat"
 
 
-#: src/components/Notification/notifications.ts:46
+#: src/components/Notification/notifications.ts:64
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} from %{node} failed"
 msgid "Disable site %{name} from %{node} failed"
 msgstr "Dupliqué avec succès"
 msgstr "Dupliqué avec succès"
 
 
-#: src/components/Notification/notifications.ts:50
+#: src/components/Notification/notifications.ts:68
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} from %{node} successfully"
 msgid "Disable site %{name} from %{node} successfully"
 msgstr "Dupliqué avec succès"
 msgstr "Dupliqué avec succès"
 
 
-#: src/components/Notification/notifications.ts:70
+#: src/components/Notification/notifications.ts:88
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} maintenance on %{node} failed"
 msgid "Disable site %{name} maintenance on %{node} failed"
 msgstr "Dupliqué avec succès"
 msgstr "Dupliqué avec succès"
 
 
-#: src/components/Notification/notifications.ts:74
+#: src/components/Notification/notifications.ts:92
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} maintenance on %{node} successfully"
 msgid "Disable site %{name} maintenance on %{node} successfully"
 msgstr "Dupliqué avec succès"
 msgstr "Dupliqué avec succès"
 
 
-#: src/components/Notification/notifications.ts:104
+#: src/components/Notification/notifications.ts:122
 #, fuzzy
 #, fuzzy
 msgid "Disable stream %{name} from %{node} failed"
 msgid "Disable stream %{name} from %{node} failed"
 msgstr "Dupliqué avec succès"
 msgstr "Dupliqué avec succès"
 
 
-#: src/components/Notification/notifications.ts:108
+#: src/components/Notification/notifications.ts:126
 #, fuzzy
 #, fuzzy
 msgid "Disable stream %{name} from %{node} successfully"
 msgid "Disable stream %{name} from %{node} successfully"
 msgstr "Dupliqué avec succès"
 msgstr "Dupliqué avec succès"
@@ -1082,7 +1110,7 @@ msgstr ""
 "exécuté sur localhost."
 "exécuté sur localhost."
 
 
 #: src/views/site/site_list/SiteDuplicate.vue:72
 #: src/views/site/site_list/SiteDuplicate.vue:72
-#: src/views/site/site_list/SiteList.vue:158
+#: src/views/site/site_list/SiteList.vue:162
 #: src/views/stream/components/StreamDuplicate.vue:64
 #: src/views/stream/components/StreamDuplicate.vue:64
 #: src/views/stream/StreamList.vue:222
 #: src/views/stream/StreamList.vue:222
 msgid "Duplicate"
 msgid "Duplicate"
@@ -1155,62 +1183,62 @@ msgstr "Échec de l'activation"
 msgid "Enable HTTPS"
 msgid "Enable HTTPS"
 msgstr "Activer TLS"
 msgstr "Activer TLS"
 
 
-#: src/components/Notification/notifications.ts:53 src/language/constants.ts:54
+#: src/components/Notification/notifications.ts:71 src/language/constants.ts:54
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Site Error"
 msgid "Enable Remote Site Error"
 msgstr "Changer de certificat"
 msgstr "Changer de certificat"
 
 
-#: src/components/Notification/notifications.ts:61
+#: src/components/Notification/notifications.ts:79
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Site Maintenance Error"
 msgid "Enable Remote Site Maintenance Error"
 msgstr "Changer de certificat"
 msgstr "Changer de certificat"
 
 
-#: src/components/Notification/notifications.ts:65
+#: src/components/Notification/notifications.ts:83
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Site Maintenance Success"
 msgid "Enable Remote Site Maintenance Success"
 msgstr "Changer de certificat"
 msgstr "Changer de certificat"
 
 
-#: src/components/Notification/notifications.ts:57 src/language/constants.ts:53
+#: src/components/Notification/notifications.ts:75 src/language/constants.ts:53
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Site Success"
 msgid "Enable Remote Site Success"
 msgstr "Changer de certificat"
 msgstr "Changer de certificat"
 
 
-#: src/components/Notification/notifications.ts:111
+#: src/components/Notification/notifications.ts:129
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Stream Error"
 msgid "Enable Remote Stream Error"
 msgstr "Changer de certificat"
 msgstr "Changer de certificat"
 
 
-#: src/components/Notification/notifications.ts:115
+#: src/components/Notification/notifications.ts:133
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Stream Success"
 msgid "Enable Remote Stream Success"
 msgstr "Changer de certificat"
 msgstr "Changer de certificat"
 
 
-#: src/components/Notification/notifications.ts:62
+#: src/components/Notification/notifications.ts:80
 #, fuzzy
 #, fuzzy
 msgid "Enable site %{name} maintenance on %{node} failed"
 msgid "Enable site %{name} maintenance on %{node} failed"
 msgstr "Dupliqué avec succès"
 msgstr "Dupliqué avec succès"
 
 
-#: src/components/Notification/notifications.ts:66
+#: src/components/Notification/notifications.ts:84
 #, fuzzy
 #, fuzzy
 msgid "Enable site %{name} maintenance on %{node} successfully"
 msgid "Enable site %{name} maintenance on %{node} successfully"
 msgstr "Dupliqué avec succès"
 msgstr "Dupliqué avec succès"
 
 
-#: src/components/Notification/notifications.ts:54
+#: src/components/Notification/notifications.ts:72
 #, fuzzy
 #, fuzzy
 msgid "Enable site %{name} on %{node} failed"
 msgid "Enable site %{name} on %{node} failed"
 msgstr "Dupliqué avec succès"
 msgstr "Dupliqué avec succès"
 
 
-#: src/components/Notification/notifications.ts:58
+#: src/components/Notification/notifications.ts:76
 #, fuzzy
 #, fuzzy
 msgid "Enable site %{name} on %{node} successfully"
 msgid "Enable site %{name} on %{node} successfully"
 msgstr "Dupliqué avec succès"
 msgstr "Dupliqué avec succès"
 
 
-#: src/components/Notification/notifications.ts:112
+#: src/components/Notification/notifications.ts:130
 #, fuzzy
 #, fuzzy
 msgid "Enable stream %{name} on %{node} failed"
 msgid "Enable stream %{name} on %{node} failed"
 msgstr "Dupliqué avec succès"
 msgstr "Dupliqué avec succès"
 
 
-#: src/components/Notification/notifications.ts:116
+#: src/components/Notification/notifications.ts:134
 #, fuzzy
 #, fuzzy
 msgid "Enable stream %{name} on %{node} successfully"
 msgid "Enable stream %{name} on %{node} successfully"
 msgstr "Dupliqué avec succès"
 msgstr "Dupliqué avec succès"
@@ -1302,6 +1330,11 @@ msgstr "Date d'expiration : %{date}"
 msgid "Export"
 msgid "Export"
 msgstr "Exporter"
 msgstr "Exporter"
 
 
+#: src/views/preference/ExternalNotify.vue:10
+#: src/views/preference/Preference.vue:169
+msgid "External Notify"
+msgstr ""
+
 #: src/views/site/cert/components/ObtainCertLive.vue:94
 #: src/views/site/cert/components/ObtainCertLive.vue:94
 #, fuzzy
 #, fuzzy
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
@@ -1714,7 +1747,7 @@ msgstr "Menu principal"
 msgid "Host"
 msgid "Host"
 msgstr "Host HTTP"
 msgstr "Host HTTP"
 
 
-#: src/views/preference/Preference.vue:174
+#: src/views/preference/Preference.vue:181
 #, fuzzy
 #, fuzzy
 msgid "HTTP"
 msgid "HTTP"
 msgstr "HTTP01"
 msgstr "HTTP01"
@@ -1782,12 +1815,12 @@ msgid "Import Certificate"
 msgstr "État du certificat"
 msgstr "État du certificat"
 
 
 #: src/views/nginx_log/NginxLogList.vue:137
 #: src/views/nginx_log/NginxLogList.vue:137
-#: src/views/site/site_list/SiteList.vue:128
+#: src/views/site/site_list/SiteList.vue:132
 msgid "Indexed"
 msgid "Indexed"
 msgstr ""
 msgstr ""
 
 
 #: src/views/nginx_log/NginxLogList.vue:134
 #: src/views/nginx_log/NginxLogList.vue:134
-#: src/views/site/site_list/SiteList.vue:125
+#: src/views/site/site_list/SiteList.vue:129
 msgid "Indexing..."
 msgid "Indexing..."
 msgstr ""
 msgstr ""
 
 
@@ -1871,6 +1904,11 @@ msgstr "Nom de fichier invalide"
 msgid "Invalid folder name"
 msgid "Invalid folder name"
 msgstr "Nom du répertoire invalide"
 msgstr "Nom du répertoire invalide"
 
 
+#: src/constants/errors/notification.ts:3
+#, fuzzy
+msgid "Invalid notifier config"
+msgstr "Code otp invalide"
+
 #: src/constants/errors/user.ts:4
 #: src/constants/errors/user.ts:4
 msgid "Invalid otp code"
 msgid "Invalid otp code"
 msgstr "Code otp invalide"
 msgstr "Code otp invalide"
@@ -1937,6 +1975,10 @@ msgstr ""
 msgid "Key Type"
 msgid "Key Type"
 msgstr "Type"
 msgstr "Type"
 
 
+#: src/views/preference/components/ExternalNotify/columns.ts:29
+msgid "Language"
+msgstr ""
+
 #: src/views/system/Upgrade.vue:179
 #: src/views/system/Upgrade.vue:179
 msgid "Last checked at"
 msgid "Last checked at"
 msgstr "Dernière vérification le"
 msgstr "Dernière vérification le"
@@ -2044,7 +2086,7 @@ msgstr "Connexion réussie"
 msgid "Logout successful"
 msgid "Logout successful"
 msgstr "Déconnexion réussie"
 msgstr "Déconnexion réussie"
 
 
-#: src/views/preference/Preference.vue:210
+#: src/views/preference/Preference.vue:217
 msgid "Logrotate"
 msgid "Logrotate"
 msgstr ""
 msgstr ""
 
 
@@ -2087,7 +2129,7 @@ msgstr ""
 msgid "Manage Configs"
 msgid "Manage Configs"
 msgstr "Gérer les configurations"
 msgstr "Gérer les configurations"
 
 
-#: src/routes/modules/sites.ts:10 src/views/site/site_list/SiteList.vue:121
+#: src/routes/modules/sites.ts:10 src/views/site/site_list/SiteList.vue:125
 msgid "Manage Sites"
 msgid "Manage Sites"
 msgstr "Gérer les sites"
 msgstr "Gérer les sites"
 
 
@@ -2168,7 +2210,7 @@ msgstr "Directive multiligne"
 #: src/views/nginx_log/NginxLogList.vue:37
 #: src/views/nginx_log/NginxLogList.vue:37
 #: src/views/preference/components/AddPasskey.vue:75
 #: src/views/preference/components/AddPasskey.vue:75
 #: src/views/site/ngx_conf/NgxUpstream.vue:177
 #: src/views/site/ngx_conf/NgxUpstream.vue:177
-#: src/views/site/site_edit/RightSettings.vue:64
+#: src/views/site/site_edit/RightSettings.vue:63
 #: src/views/site/site_list/columns.tsx:17
 #: src/views/site/site_list/columns.tsx:17
 #: src/views/site/site_list/SiteDuplicate.vue:79
 #: src/views/site/site_list/SiteDuplicate.vue:79
 #: src/views/stream/components/RightSettings.vue:87
 #: src/views/stream/components/RightSettings.vue:87
@@ -2218,7 +2260,7 @@ msgstr "Nouvelle version publiée"
 msgid "Next"
 msgid "Next"
 msgstr "Suivant"
 msgstr "Suivant"
 
 
-#: src/views/preference/Preference.vue:198
+#: src/views/preference/Preference.vue:205
 #, fuzzy
 #, fuzzy
 msgid "Nginx"
 msgid "Nginx"
 msgstr "Journal Nginx"
 msgstr "Journal Nginx"
@@ -2363,7 +2405,7 @@ msgstr "Erreur d'analyse de configuration Nginx"
 #: src/views/preference/CertSettings.vue:73
 #: src/views/preference/CertSettings.vue:73
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:97
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:97
 #: src/views/site/ngx_conf/LocationEditor.vue:88
 #: src/views/site/ngx_conf/LocationEditor.vue:88
-#: src/views/site/site_list/SiteList.vue:161
+#: src/views/site/site_list/SiteList.vue:165
 #: src/views/stream/StreamList.vue:225
 #: src/views/stream/StreamList.vue:225
 msgid "No"
 msgid "No"
 msgstr "Non"
 msgstr "Non"
@@ -2378,12 +2420,12 @@ msgstr "Action"
 msgid "No records selected"
 msgid "No records selected"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/Preference.vue:168
+#: src/views/preference/Preference.vue:175
 #, fuzzy
 #, fuzzy
 msgid "Node"
 msgid "Node"
 msgstr "Nom d'utilisateur"
 msgstr "Nom d'utilisateur"
 
 
-#: src/views/site/site_edit/RightSettings.vue:67
+#: src/views/site/site_edit/RightSettings.vue:66
 #: src/views/site/site_list/columns.tsx:63
 #: src/views/site/site_list/columns.tsx:63
 #: src/views/stream/components/RightSettings.vue:90
 #: src/views/stream/components/RightSettings.vue:90
 #: src/views/stream/StreamList.vue:30
 #: src/views/stream/StreamList.vue:30
@@ -2429,7 +2471,7 @@ msgstr "Non valide avant : %{date}"
 msgid "Note"
 msgid "Note"
 msgstr "Note"
 msgstr "Note"
 
 
-#: src/views/site/site_edit/RightSettings.vue:96
+#: src/views/site/site_edit/RightSettings.vue:95
 #: src/views/stream/components/RightSettings.vue:118
 #: src/views/stream/components/RightSettings.vue:118
 msgid ""
 msgid ""
 "Note, if the configuration file include other configurations or "
 "Note, if the configuration file include other configurations or "
@@ -2447,6 +2489,11 @@ msgstr "Certification"
 msgid "Notifications"
 msgid "Notifications"
 msgstr "Certification"
 msgstr "Certification"
 
 
+#: src/constants/errors/notification.ts:2
+#, fuzzy
+msgid "Notifier not found"
+msgstr "Fichier introuvable"
+
 #: src/views/site/cert/components/ObtainCert.vue:182
 #: src/views/site/cert/components/ObtainCert.vue:182
 msgid "Obtain certificate"
 msgid "Obtain certificate"
 msgstr "Obtenir un certificat"
 msgstr "Obtenir un certificat"
@@ -2489,7 +2536,7 @@ msgstr ""
 #: src/views/site/ngx_conf/NgxServer.vue:79
 #: src/views/site/ngx_conf/NgxServer.vue:79
 #: src/views/site/ngx_conf/NgxUpstream.vue:33
 #: src/views/site/ngx_conf/NgxUpstream.vue:33
 #: src/views/site/site_edit/components/SiteStatusSegmented.vue:121
 #: src/views/site/site_edit/components/SiteStatusSegmented.vue:121
-#: src/views/site/site_list/SiteList.vue:162
+#: src/views/site/site_list/SiteList.vue:166
 #: src/views/stream/components/RightSettings.vue:54
 #: src/views/stream/components/RightSettings.vue:54
 #: src/views/stream/StreamList.vue:226
 #: src/views/stream/StreamList.vue:226
 #: src/views/system/Backup/BackupCreator.vue:149
 #: src/views/system/Backup/BackupCreator.vue:149
@@ -2512,7 +2559,7 @@ msgstr ""
 msgid "Only zip files are allowed"
 msgid "Only zip files are allowed"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/Preference.vue:204
+#: src/views/preference/Preference.vue:211
 msgid "OpenAI"
 msgid "OpenAI"
 msgstr "OpenAI"
 msgstr "OpenAI"
 
 
@@ -2656,7 +2703,7 @@ msgstr ""
 "des informations d'identification ci-dessous pour demander l'API du "
 "des informations d'identification ci-dessous pour demander l'API du "
 "fournisseur DNS."
 "fournisseur DNS."
 
 
-#: src/components/Notification/notifications.ts:138
+#: src/components/Notification/notifications.ts:156
 #: src/language/constants.ts:59
 #: src/language/constants.ts:59
 msgid ""
 msgid ""
 "Please generate new recovery codes in the preferences immediately to prevent "
 "Please generate new recovery codes in the preferences immediately to prevent "
@@ -2749,7 +2796,7 @@ msgstr "Action"
 msgid "Pre-release"
 msgid "Pre-release"
 msgstr ""
 msgstr ""
 
 
-#: src/routes/modules/preference.ts:10 src/views/preference/Preference.vue:151
+#: src/routes/modules/preference.ts:10 src/views/preference/Preference.vue:152
 msgid "Preference"
 msgid "Preference"
 msgstr "Préférence"
 msgstr "Préférence"
 
 
@@ -2893,22 +2940,22 @@ msgstr "Recharger"
 msgid "Reload Nginx"
 msgid "Reload Nginx"
 msgstr "Rechargement de nginx"
 msgstr "Rechargement de nginx"
 
 
-#: src/components/Notification/notifications.ts:144
+#: src/components/Notification/notifications.ts:10
 #, fuzzy
 #, fuzzy
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgstr "Supprimer le site : %{site_name}"
 msgstr "Supprimer le site : %{site_name}"
 
 
-#: src/components/Notification/notifications.ts:148
+#: src/components/Notification/notifications.ts:14
 #, fuzzy
 #, fuzzy
 msgid "Reload Nginx on %{node} successfully"
 msgid "Reload Nginx on %{node} successfully"
 msgstr "Mise à niveau réussie"
 msgstr "Mise à niveau réussie"
 
 
-#: src/components/Notification/notifications.ts:143
+#: src/components/Notification/notifications.ts:9
 #, fuzzy
 #, fuzzy
 msgid "Reload Remote Nginx Error"
 msgid "Reload Remote Nginx Error"
 msgstr "Changer de certificat"
 msgstr "Changer de certificat"
 
 
-#: src/components/Notification/notifications.ts:147
+#: src/components/Notification/notifications.ts:13
 #, fuzzy
 #, fuzzy
 msgid "Reload Remote Nginx Success"
 msgid "Reload Remote Nginx Success"
 msgstr "Changer de certificat"
 msgstr "Changer de certificat"
@@ -2950,62 +2997,62 @@ msgstr "Enregistré avec succès"
 msgid "Rename"
 msgid "Rename"
 msgstr "Nom d'utilisateur"
 msgstr "Nom d'utilisateur"
 
 
-#: src/components/Notification/notifications.ts:28
+#: src/components/Notification/notifications.ts:46
 #, fuzzy
 #, fuzzy
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} failed"
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} failed"
 msgstr "Dupliqué avec succès"
 msgstr "Dupliqué avec succès"
 
 
-#: src/components/Notification/notifications.ts:32
+#: src/components/Notification/notifications.ts:50
 #, fuzzy
 #, fuzzy
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} successfully"
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} successfully"
 msgstr "Dupliqué avec succès"
 msgstr "Dupliqué avec succès"
 
 
-#: src/components/Notification/notifications.ts:27 src/language/constants.ts:42
+#: src/components/Notification/notifications.ts:45 src/language/constants.ts:42
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Config Error"
 msgid "Rename Remote Config Error"
 msgstr "Changer de certificat"
 msgstr "Changer de certificat"
 
 
-#: src/components/Notification/notifications.ts:31 src/language/constants.ts:41
+#: src/components/Notification/notifications.ts:49 src/language/constants.ts:41
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Config Success"
 msgid "Rename Remote Config Success"
 msgstr "Changer de certificat"
 msgstr "Changer de certificat"
 
 
-#: src/components/Notification/notifications.ts:77 src/language/constants.ts:56
+#: src/components/Notification/notifications.ts:95 src/language/constants.ts:56
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Site Error"
 msgid "Rename Remote Site Error"
 msgstr "Changer de certificat"
 msgstr "Changer de certificat"
 
 
-#: src/components/Notification/notifications.ts:81 src/language/constants.ts:55
+#: src/components/Notification/notifications.ts:99 src/language/constants.ts:55
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Site Success"
 msgid "Rename Remote Site Success"
 msgstr "Changer de certificat"
 msgstr "Changer de certificat"
 
 
-#: src/components/Notification/notifications.ts:119
+#: src/components/Notification/notifications.ts:137
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Stream Error"
 msgid "Rename Remote Stream Error"
 msgstr "Changer de certificat"
 msgstr "Changer de certificat"
 
 
-#: src/components/Notification/notifications.ts:123
+#: src/components/Notification/notifications.ts:141
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Stream Success"
 msgid "Rename Remote Stream Success"
 msgstr "Changer de certificat"
 msgstr "Changer de certificat"
 
 
-#: src/components/Notification/notifications.ts:78
+#: src/components/Notification/notifications.ts:96
 #, fuzzy
 #, fuzzy
 msgid "Rename site %{name} to %{new_name} on %{node} failed"
 msgid "Rename site %{name} to %{new_name} on %{node} failed"
 msgstr "Dupliqué avec succès"
 msgstr "Dupliqué avec succès"
 
 
-#: src/components/Notification/notifications.ts:82
+#: src/components/Notification/notifications.ts:100
 #, fuzzy
 #, fuzzy
 msgid "Rename site %{name} to %{new_name} on %{node} successfully"
 msgid "Rename site %{name} to %{new_name} on %{node} successfully"
 msgstr "Dupliqué avec succès"
 msgstr "Dupliqué avec succès"
 
 
-#: src/components/Notification/notifications.ts:120
+#: src/components/Notification/notifications.ts:138
 #, fuzzy
 #, fuzzy
 msgid "Rename stream %{name} to %{new_name} on %{node} failed"
 msgid "Rename stream %{name} to %{new_name} on %{node} failed"
 msgstr "Dupliqué avec succès"
 msgstr "Dupliqué avec succès"
 
 
-#: src/components/Notification/notifications.ts:124
+#: src/components/Notification/notifications.ts:142
 #, fuzzy
 #, fuzzy
 msgid "Rename stream %{name} to %{new_name} on %{node} successfully"
 msgid "Rename stream %{name} to %{new_name} on %{node} successfully"
 msgstr "Dupliqué avec succès"
 msgstr "Dupliqué avec succès"
@@ -3072,22 +3119,22 @@ msgstr "Redémarrer"
 msgid "Restart Nginx"
 msgid "Restart Nginx"
 msgstr "Redémarrage"
 msgstr "Redémarrage"
 
 
-#: src/components/Notification/notifications.ts:152
+#: src/components/Notification/notifications.ts:18
 #, fuzzy
 #, fuzzy
 msgid "Restart Nginx on %{node} failed, response: %{resp}"
 msgid "Restart Nginx on %{node} failed, response: %{resp}"
 msgstr "Dupliqué avec succès"
 msgstr "Dupliqué avec succès"
 
 
-#: src/components/Notification/notifications.ts:156
+#: src/components/Notification/notifications.ts:22
 #, fuzzy
 #, fuzzy
 msgid "Restart Nginx on %{node} successfully"
 msgid "Restart Nginx on %{node} successfully"
 msgstr "Mise à niveau réussie"
 msgstr "Mise à niveau réussie"
 
 
-#: src/components/Notification/notifications.ts:151
+#: src/components/Notification/notifications.ts:17
 #, fuzzy
 #, fuzzy
 msgid "Restart Remote Nginx Error"
 msgid "Restart Remote Nginx Error"
 msgstr "Changer de certificat"
 msgstr "Changer de certificat"
 
 
-#: src/components/Notification/notifications.ts:155
+#: src/components/Notification/notifications.ts:21
 #, fuzzy
 #, fuzzy
 msgid "Restart Remote Nginx Success"
 msgid "Restart Remote Nginx Success"
 msgstr "Changer de certificat"
 msgstr "Changer de certificat"
@@ -3154,7 +3201,7 @@ msgstr "En cours d'éxécution"
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/ConfigEditor.vue:271
 #: src/views/config/ConfigEditor.vue:271
 #: src/views/preference/components/Passkey.vue:130
 #: src/views/preference/components/Passkey.vue:130
-#: src/views/preference/Preference.vue:221
+#: src/views/preference/Preference.vue:228
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:127
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:127
 #: src/views/site/site_edit/components/ConfigName.vue:52
 #: src/views/site/site_edit/components/ConfigName.vue:52
 #: src/views/site/site_edit/SiteEdit.vue:292
 #: src/views/site/site_edit/SiteEdit.vue:292
@@ -3172,42 +3219,44 @@ msgstr "Enregistrer la directive"
 msgid "Save error %{msg}"
 msgid "Save error %{msg}"
 msgstr "Enregistrer l'erreur %{msg}"
 msgstr "Enregistrer l'erreur %{msg}"
 
 
-#: src/components/Notification/notifications.ts:85 src/language/constants.ts:48
+#: src/components/Notification/notifications.ts:103
+#: src/language/constants.ts:48
 #, fuzzy
 #, fuzzy
 msgid "Save Remote Site Error"
 msgid "Save Remote Site Error"
 msgstr "Changer de certificat"
 msgstr "Changer de certificat"
 
 
-#: src/components/Notification/notifications.ts:89 src/language/constants.ts:47
+#: src/components/Notification/notifications.ts:107
+#: src/language/constants.ts:47
 #, fuzzy
 #, fuzzy
 msgid "Save Remote Site Success"
 msgid "Save Remote Site Success"
 msgstr "Changer de certificat"
 msgstr "Changer de certificat"
 
 
-#: src/components/Notification/notifications.ts:127
+#: src/components/Notification/notifications.ts:145
 #, fuzzy
 #, fuzzy
 msgid "Save Remote Stream Error"
 msgid "Save Remote Stream Error"
 msgstr "Changer de certificat"
 msgstr "Changer de certificat"
 
 
-#: src/components/Notification/notifications.ts:131
+#: src/components/Notification/notifications.ts:149
 #, fuzzy
 #, fuzzy
 msgid "Save Remote Stream Success"
 msgid "Save Remote Stream Success"
 msgstr "Changer de certificat"
 msgstr "Changer de certificat"
 
 
-#: src/components/Notification/notifications.ts:86
+#: src/components/Notification/notifications.ts:104
 #, fuzzy
 #, fuzzy
 msgid "Save site %{name} to %{node} failed"
 msgid "Save site %{name} to %{node} failed"
 msgstr "Dupliqué avec succès"
 msgstr "Dupliqué avec succès"
 
 
-#: src/components/Notification/notifications.ts:90
+#: src/components/Notification/notifications.ts:108
 #, fuzzy
 #, fuzzy
 msgid "Save site %{name} to %{node} successfully"
 msgid "Save site %{name} to %{node} successfully"
 msgstr "Dupliqué avec succès"
 msgstr "Dupliqué avec succès"
 
 
-#: src/components/Notification/notifications.ts:128
+#: src/components/Notification/notifications.ts:146
 #, fuzzy
 #, fuzzy
 msgid "Save stream %{name} to %{node} failed"
 msgid "Save stream %{name} to %{node} failed"
 msgstr "Dupliqué avec succès"
 msgstr "Dupliqué avec succès"
 
 
-#: src/components/Notification/notifications.ts:132
+#: src/components/Notification/notifications.ts:150
 #, fuzzy
 #, fuzzy
 msgid "Save stream %{name} to %{node} successfully"
 msgid "Save stream %{name} to %{node} successfully"
 msgstr "Dupliqué avec succès"
 msgstr "Dupliqué avec succès"
@@ -3215,7 +3264,7 @@ msgstr "Dupliqué avec succès"
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:47
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:47
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:97
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:97
 #: src/views/certificate/CertificateEditor.vue:49
 #: src/views/certificate/CertificateEditor.vue:49
-#: src/views/preference/Preference.vue:123
+#: src/views/preference/Preference.vue:124
 msgid "Save successfully"
 msgid "Save successfully"
 msgstr "Sauvegarde réussie"
 msgstr "Sauvegarde réussie"
 
 
@@ -3235,6 +3284,10 @@ msgstr ""
 msgid "SDK"
 msgid "SDK"
 msgstr ""
 msgstr ""
 
 
+#: src/views/preference/components/ExternalNotify/dingtalk.ts:13
+msgid "Secret (Optional)"
+msgstr ""
+
 #: src/views/preference/components/TOTP.vue:109
 #: src/views/preference/components/TOTP.vue:109
 msgid "Secret has been copied"
 msgid "Secret has been copied"
 msgstr ""
 msgstr ""
@@ -3266,7 +3319,7 @@ msgstr ""
 msgid "Send"
 msgid "Send"
 msgstr "Envoyer"
 msgstr "Envoyer"
 
 
-#: src/views/preference/Preference.vue:156
+#: src/views/preference/Preference.vue:157
 #, fuzzy
 #, fuzzy
 msgid "Server"
 msgid "Server"
 msgstr "Informations sur le serveur"
 msgstr "Informations sur le serveur"
@@ -3275,6 +3328,11 @@ msgstr "Informations sur le serveur"
 msgid "Server Info"
 msgid "Server Info"
 msgstr "Informations sur le serveur"
 msgstr "Informations sur le serveur"
 
 
+#: src/views/preference/components/ExternalNotify/bark.ts:13
+#, fuzzy
+msgid "Server URL"
+msgstr "Informations sur le serveur"
+
 #: src/views/site/cert/components/ObtainCert.vue:107
 #: src/views/site/cert/components/ObtainCert.vue:107
 msgid "server_name not found in directives"
 msgid "server_name not found in directives"
 msgstr "server_name introuvable dans les directives"
 msgstr "server_name introuvable dans les directives"
@@ -3455,7 +3513,7 @@ msgstr ""
 #: src/views/certificate/ACMEUser.vue:65
 #: src/views/certificate/ACMEUser.vue:65
 #: src/views/certificate/CertificateList/certColumns.tsx:65
 #: src/views/certificate/CertificateList/certColumns.tsx:65
 #: src/views/environments/list/envColumns.tsx:44
 #: src/views/environments/list/envColumns.tsx:44
-#: src/views/site/site_edit/RightSettings.vue:56
+#: src/views/site/site_edit/RightSettings.vue:55
 #: src/views/site/site_list/columns.tsx:80 src/views/stream/StreamList.vue:47
 #: src/views/site/site_list/columns.tsx:80 src/views/stream/StreamList.vue:47
 msgid "Status"
 msgid "Status"
 msgstr "Statut"
 msgstr "Statut"
@@ -3534,42 +3592,42 @@ msgstr ""
 msgid "Sync Certificate"
 msgid "Sync Certificate"
 msgstr "Changer de certificat"
 msgstr "Changer de certificat"
 
 
-#: src/components/Notification/notifications.ts:10
+#: src/components/Notification/notifications.ts:28
 #, fuzzy
 #, fuzzy
 msgid "Sync Certificate %{cert_name} to %{env_name} failed"
 msgid "Sync Certificate %{cert_name} to %{env_name} failed"
 msgstr "Dupliqué avec succès"
 msgstr "Dupliqué avec succès"
 
 
-#: src/components/Notification/notifications.ts:14
+#: src/components/Notification/notifications.ts:32
 #, fuzzy
 #, fuzzy
 msgid "Sync Certificate %{cert_name} to %{env_name} successfully"
 msgid "Sync Certificate %{cert_name} to %{env_name} successfully"
 msgstr "Dupliqué avec succès"
 msgstr "Dupliqué avec succès"
 
 
-#: src/components/Notification/notifications.ts:9 src/language/constants.ts:39
+#: src/components/Notification/notifications.ts:27 src/language/constants.ts:39
 #, fuzzy
 #, fuzzy
 msgid "Sync Certificate Error"
 msgid "Sync Certificate Error"
 msgstr "Changer de certificat"
 msgstr "Changer de certificat"
 
 
-#: src/components/Notification/notifications.ts:13 src/language/constants.ts:38
+#: src/components/Notification/notifications.ts:31 src/language/constants.ts:38
 #, fuzzy
 #, fuzzy
 msgid "Sync Certificate Success"
 msgid "Sync Certificate Success"
 msgstr "Changer de certificat"
 msgstr "Changer de certificat"
 
 
-#: src/components/Notification/notifications.ts:20
+#: src/components/Notification/notifications.ts:38
 #, fuzzy
 #, fuzzy
 msgid "Sync config %{config_name} to %{env_name} failed"
 msgid "Sync config %{config_name} to %{env_name} failed"
 msgstr "Dupliqué avec succès"
 msgstr "Dupliqué avec succès"
 
 
-#: src/components/Notification/notifications.ts:24
+#: src/components/Notification/notifications.ts:42
 #, fuzzy
 #, fuzzy
 msgid "Sync config %{config_name} to %{env_name} successfully"
 msgid "Sync config %{config_name} to %{env_name} successfully"
 msgstr "Dupliqué avec succès"
 msgstr "Dupliqué avec succès"
 
 
-#: src/components/Notification/notifications.ts:19 src/language/constants.ts:45
+#: src/components/Notification/notifications.ts:37 src/language/constants.ts:45
 #, fuzzy
 #, fuzzy
 msgid "Sync Config Error"
 msgid "Sync Config Error"
 msgstr "Changer de certificat"
 msgstr "Changer de certificat"
 
 
-#: src/components/Notification/notifications.ts:23 src/language/constants.ts:44
+#: src/components/Notification/notifications.ts:41 src/language/constants.ts:44
 #, fuzzy
 #, fuzzy
 msgid "Sync Config Success"
 msgid "Sync Config Success"
 msgstr "Changer de certificat"
 msgstr "Changer de certificat"
@@ -3579,8 +3637,8 @@ msgstr "Changer de certificat"
 msgid "Sync Nodes"
 msgid "Sync Nodes"
 msgstr ""
 msgstr ""
 
 
-#: src/views/site/site_edit/RightSettings.vue:102
-#: src/views/site/site_edit/RightSettings.vue:89
+#: src/views/site/site_edit/RightSettings.vue:101
+#: src/views/site/site_edit/RightSettings.vue:88
 #: src/views/stream/components/RightSettings.vue:111
 #: src/views/stream/components/RightSettings.vue:111
 #: src/views/stream/components/RightSettings.vue:124
 #: src/views/stream/components/RightSettings.vue:124
 #, fuzzy
 #, fuzzy
@@ -3592,7 +3650,7 @@ msgstr "Changer de certificat"
 msgid "Sync to"
 msgid "Sync to"
 msgstr "Changer de certificat"
 msgstr "Changer de certificat"
 
 
-#: src/views/site/site_edit/RightSettings.vue:86
+#: src/views/site/site_edit/RightSettings.vue:85
 #: src/views/stream/components/RightSettings.vue:108
 #: src/views/stream/components/RightSettings.vue:108
 msgid "Synchronization"
 msgid "Synchronization"
 msgstr ""
 msgstr ""
@@ -3625,7 +3683,11 @@ msgstr "Nginx a redémarré avec succès"
 msgid "Task not found"
 msgid "Task not found"
 msgstr "Fichier introuvable"
 msgstr "Fichier introuvable"
 
 
-#: src/routes/modules/terminal.ts:10 src/views/preference/Preference.vue:180
+#: src/views/preference/components/ExternalNotify/telegram.ts:5
+msgid "Telegram"
+msgstr ""
+
+#: src/routes/modules/terminal.ts:10 src/views/preference/Preference.vue:187
 #: src/views/terminal/Terminal.vue:129
 #: src/views/terminal/Terminal.vue:129
 msgid "Terminal"
 msgid "Terminal"
 msgstr "Terminal"
 msgstr "Terminal"
@@ -3882,6 +3944,7 @@ msgstr ""
 #: src/views/certificate/CertificateList/certColumns.tsx:25
 #: src/views/certificate/CertificateList/certColumns.tsx:25
 #: src/views/nginx_log/NginxLogList.vue:21
 #: src/views/nginx_log/NginxLogList.vue:21
 #: src/views/notification/notificationColumns.tsx:9
 #: src/views/notification/notificationColumns.tsx:9
+#: src/views/preference/components/ExternalNotify/columns.ts:17
 msgid "Type"
 msgid "Type"
 msgstr "Type"
 msgstr "Type"
 
 
@@ -3899,7 +3962,7 @@ msgstr "Mis à jour avec succés"
 #: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:325
 #: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:325
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/environments/list/envColumns.tsx:90
-#: src/views/site/site_edit/RightSettings.vue:76
+#: src/views/site/site_edit/RightSettings.vue:75
 #: src/views/site/site_list/columns.tsx:110
 #: src/views/site/site_list/columns.tsx:110
 #: src/views/stream/components/RightSettings.vue:99
 #: src/views/stream/components/RightSettings.vue:99
 #: src/views/stream/StreamList.vue:67 src/views/user/userColumns.tsx:54
 #: src/views/stream/StreamList.vue:67 src/views/user/userColumns.tsx:54
@@ -4063,7 +4126,7 @@ msgid ""
 "Pebble as CA."
 "Pebble as CA."
 msgstr ""
 msgstr ""
 
 
-#: src/views/site/site_edit/RightSettings.vue:92
+#: src/views/site/site_edit/RightSettings.vue:91
 msgid ""
 msgid ""
 "When you enable/disable, delete, or save this site, the nodes set in the "
 "When you enable/disable, delete, or save this site, the nodes set in the "
 "Node Group and the nodes selected below will be synchronized."
 "Node Group and the nodes selected below will be synchronized."
@@ -4343,10 +4406,6 @@ msgstr ""
 #~ msgid "Theme"
 #~ msgid "Theme"
 #~ msgstr "Thème"
 #~ msgstr "Thème"
 
 
-#, fuzzy
-#~ msgid "Token"
-#~ msgstr "Jeton d'API"
-
 #~ msgid "Git"
 #~ msgid "Git"
 #~ msgstr "Git"
 #~ msgstr "Git"
 
 

+ 165 - 102
app/src/language/ko_KR/app.po

@@ -35,6 +35,11 @@ msgstr "접근 로그"
 msgid "Access Logs"
 msgid "Access Logs"
 msgstr "접근 로그"
 msgstr "접근 로그"
 
 
+#: src/views/preference/components/ExternalNotify/dingtalk.ts:9
+#, fuzzy
+msgid "Access Token"
+msgstr "접근 로그"
+
 #: src/routes/modules/certificates.ts:20 src/views/certificate/ACMEUser.vue:113
 #: src/routes/modules/certificates.ts:20 src/views/certificate/ACMEUser.vue:113
 #: src/views/certificate/ACMEUserSelector.vue:85
 #: src/views/certificate/ACMEUserSelector.vue:85
 msgid "ACME User"
 msgid "ACME User"
@@ -49,6 +54,7 @@ msgstr "ACME 사용자"
 #: src/views/nginx_log/NginxLogList.vue:53
 #: src/views/nginx_log/NginxLogList.vue:53
 #: src/views/notification/notificationColumns.tsx:66
 #: src/views/notification/notificationColumns.tsx:66
 #: src/views/preference/AuthSettings.vue:30
 #: src/views/preference/AuthSettings.vue:30
+#: src/views/preference/components/ExternalNotify/columns.ts:46
 #: src/views/site/site_list/columns.tsx:117 src/views/stream/StreamList.vue:74
 #: src/views/site/site_list/columns.tsx:117 src/views/stream/StreamList.vue:74
 #: src/views/user/userColumns.tsx:60
 #: src/views/user/userColumns.tsx:60
 msgid "Action"
 msgid "Action"
@@ -113,7 +119,7 @@ msgstr ""
 msgid "All"
 msgid "All"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:137
+#: src/components/Notification/notifications.ts:155
 #: src/language/constants.ts:58
 #: src/language/constants.ts:58
 msgid "All Recovery Codes Have Been Used"
 msgid "All Recovery Codes Have Been Used"
 msgstr ""
 msgstr ""
@@ -139,7 +145,7 @@ msgstr "API 토큰"
 msgid "API Type"
 msgid "API Type"
 msgstr "API 토큰"
 msgstr "API 토큰"
 
 
-#: src/views/preference/Preference.vue:162
+#: src/views/preference/Preference.vue:163
 msgid "App"
 msgid "App"
 msgstr "앱"
 msgstr "앱"
 
 
@@ -193,7 +199,7 @@ msgstr "이 항목을 영구적으로 삭제하시겠습니까?"
 msgid "Are you sure you want to delete this item?"
 msgid "Are you sure you want to delete this item?"
 msgstr "이 항목을 삭제하시겠습니까?"
 msgstr "이 항목을 삭제하시겠습니까?"
 
 
-#: src/views/site/site_list/SiteList.vue:163
+#: src/views/site/site_list/SiteList.vue:167
 #: src/views/stream/StreamList.vue:227
 #: src/views/stream/StreamList.vue:227
 msgid "Are you sure you want to delete?"
 msgid "Are you sure you want to delete?"
 msgstr "정말 삭제하시겠습니까?"
 msgstr "정말 삭제하시겠습니까?"
@@ -238,7 +244,7 @@ msgstr "수정 시도"
 msgid "Attempts"
 msgid "Attempts"
 msgstr "시도 횟수"
 msgstr "시도 횟수"
 
 
-#: src/views/preference/Preference.vue:186
+#: src/views/preference/Preference.vue:193
 msgid "Auth"
 msgid "Auth"
 msgstr "인증"
 msgstr "인증"
 
 
@@ -322,12 +328,16 @@ msgstr "차단된 IP"
 msgid "Banned Until"
 msgid "Banned Until"
 msgstr "차단될 시간"
 msgstr "차단될 시간"
 
 
+#: src/views/preference/components/ExternalNotify/bark.ts:5
+msgid "Bark"
+msgstr ""
+
 #: src/views/site/site_add/SiteAdd.vue:95
 #: src/views/site/site_add/SiteAdd.vue:95
 msgid "Base information"
 msgid "Base information"
 msgstr "기본 정보"
 msgstr "기본 정보"
 
 
 #: src/views/config/ConfigEditor.vue:290
 #: src/views/config/ConfigEditor.vue:290
-#: src/views/site/site_edit/RightSettings.vue:53
+#: src/views/site/site_edit/RightSettings.vue:52
 #: src/views/stream/components/RightSettings.vue:79
 #: src/views/stream/components/RightSettings.vue:79
 msgid "Basic"
 msgid "Basic"
 msgstr "기본"
 msgstr "기본"
@@ -359,6 +369,11 @@ msgstr "아래에는 일괄 수정하려는 선택된 항목이 있습니다"
 msgid "Block is nil"
 msgid "Block is nil"
 msgstr "블록 없음"
 msgstr "블록 없음"
 
 
+#: src/views/preference/components/ExternalNotify/telegram.ts:9
+#, fuzzy
+msgid "Bot Token"
+msgstr "API 토큰"
+
 #: src/views/system/About.vue:55
 #: src/views/system/About.vue:55
 msgid "Build with"
 msgid "Build with"
 msgstr "빌드 환경"
 msgstr "빌드 환경"
@@ -399,7 +414,7 @@ msgstr ""
 msgid "Cannot remove initial user"
 msgid "Cannot remove initial user"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/Preference.vue:192
+#: src/views/preference/Preference.vue:199
 #, fuzzy
 #, fuzzy
 msgid "Cert"
 msgid "Cert"
 msgstr "자동 인증"
 msgstr "자동 인증"
@@ -474,6 +489,10 @@ msgstr "인증서 변경"
 msgid "Channel"
 msgid "Channel"
 msgstr "채널"
 msgstr "채널"
 
 
+#: src/views/preference/components/ExternalNotify/telegram.ts:13
+msgid "Chat ID"
+msgstr ""
+
 #: src/views/system/Upgrade.vue:185
 #: src/views/system/Upgrade.vue:185
 msgid "Check again"
 msgid "Check again"
 msgstr "다시 확인"
 msgstr "다시 확인"
@@ -670,6 +689,7 @@ msgstr ""
 
 
 #: src/views/environments/group/columns.ts:31
 #: src/views/environments/group/columns.ts:31
 #: src/views/notification/notificationColumns.tsx:59
 #: src/views/notification/notificationColumns.tsx:59
+#: src/views/preference/components/ExternalNotify/columns.ts:41
 #: src/views/preference/components/Passkey.vue:95
 #: src/views/preference/components/Passkey.vue:95
 #: src/views/user/userColumns.tsx:48
 #: src/views/user/userColumns.tsx:48
 msgid "Created at"
 msgid "Created at"
@@ -742,7 +762,7 @@ msgstr "설명"
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/views/site/ngx_conf/NgxServer.vue:110
 #: src/views/site/ngx_conf/NgxServer.vue:110
 #: src/views/site/ngx_conf/NgxUpstream.vue:128
 #: src/views/site/ngx_conf/NgxUpstream.vue:128
-#: src/views/site/site_list/SiteList.vue:172
+#: src/views/site/site_list/SiteList.vue:176
 #: src/views/stream/StreamList.vue:236
 #: src/views/stream/StreamList.vue:236
 msgid "Delete"
 msgid "Delete"
 msgstr "삭제"
 msgstr "삭제"
@@ -752,46 +772,46 @@ msgstr "삭제"
 msgid "Delete Permanently"
 msgid "Delete Permanently"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:37 src/language/constants.ts:50
+#: src/components/Notification/notifications.ts:55 src/language/constants.ts:50
 #, fuzzy
 #, fuzzy
 msgid "Delete Remote Site Error"
 msgid "Delete Remote Site Error"
 msgstr "인증서 갱신 오류"
 msgstr "인증서 갱신 오류"
 
 
-#: src/components/Notification/notifications.ts:41 src/language/constants.ts:49
+#: src/components/Notification/notifications.ts:59 src/language/constants.ts:49
 #, fuzzy
 #, fuzzy
 msgid "Delete Remote Site Success"
 msgid "Delete Remote Site Success"
 msgstr "인증서 갱신 성공"
 msgstr "인증서 갱신 성공"
 
 
-#: src/components/Notification/notifications.ts:95
+#: src/components/Notification/notifications.ts:113
 #, fuzzy
 #, fuzzy
 msgid "Delete Remote Stream Error"
 msgid "Delete Remote Stream Error"
 msgstr "인증서 갱신 오류"
 msgstr "인증서 갱신 오류"
 
 
-#: src/components/Notification/notifications.ts:99
+#: src/components/Notification/notifications.ts:117
 #, fuzzy
 #, fuzzy
 msgid "Delete Remote Stream Success"
 msgid "Delete Remote Stream Success"
 msgstr "인증서 갱신 성공"
 msgstr "인증서 갱신 성공"
 
 
-#: src/components/Notification/notifications.ts:38
+#: src/components/Notification/notifications.ts:56
 #, fuzzy
 #, fuzzy
 msgid "Delete site %{name} from %{node} failed"
 msgid "Delete site %{name} from %{node} failed"
 msgstr "%{conf_name}을(를) %{node_name}(으)로 배포 실패"
 msgstr "%{conf_name}을(를) %{node_name}(으)로 배포 실패"
 
 
-#: src/components/Notification/notifications.ts:42
+#: src/components/Notification/notifications.ts:60
 #, fuzzy
 #, fuzzy
 msgid "Delete site %{name} from %{node} successfully"
 msgid "Delete site %{name} from %{node} successfully"
 msgstr "%{conf_name}을(를) %{node_name}(으)로 성공적으로 복제함"
 msgstr "%{conf_name}을(를) %{node_name}(으)로 성공적으로 복제함"
 
 
-#: src/views/site/site_list/SiteList.vue:94
+#: src/views/site/site_list/SiteList.vue:98
 msgid "Delete site: %{site_name}"
 msgid "Delete site: %{site_name}"
 msgstr "사이트 삭제: %{site_name}"
 msgstr "사이트 삭제: %{site_name}"
 
 
-#: src/components/Notification/notifications.ts:96
+#: src/components/Notification/notifications.ts:114
 #, fuzzy
 #, fuzzy
 msgid "Delete stream %{name} from %{node} failed"
 msgid "Delete stream %{name} from %{node} failed"
 msgstr "%{conf_name}을(를) %{node_name}(으)로 배포 실패"
 msgstr "%{conf_name}을(를) %{node_name}(으)로 배포 실패"
 
 
-#: src/components/Notification/notifications.ts:100
+#: src/components/Notification/notifications.ts:118
 #, fuzzy
 #, fuzzy
 msgid "Delete stream %{name} from %{node} successfully"
 msgid "Delete stream %{name} from %{node} successfully"
 msgstr "%{conf_name}을(를) %{node_name}(으)로 성공적으로 복제함"
 msgstr "%{conf_name}을(를) %{node_name}(으)로 성공적으로 복제함"
@@ -829,6 +849,14 @@ msgstr "세부 사항"
 msgid "Development Mode"
 msgid "Development Mode"
 msgstr "개발 모드"
 msgstr "개발 모드"
 
 
+#: src/views/preference/components/ExternalNotify/bark.ts:9
+msgid "Device Key"
+msgstr ""
+
+#: src/views/preference/components/ExternalNotify/dingtalk.ts:5
+msgid "DingTalk"
+msgstr ""
+
 #: src/views/site/ngx_conf/directive/DirectiveAdd.vue:89
 #: src/views/site/ngx_conf/directive/DirectiveAdd.vue:89
 msgid "Directive"
 msgid "Directive"
 msgstr "지시문"
 msgstr "지시문"
@@ -862,62 +890,62 @@ msgstr "비활성화"
 msgid "Disable auto-renewal failed for %{name}"
 msgid "Disable auto-renewal failed for %{name}"
 msgstr "%{name}의 자동 갱신 비활성화 실패"
 msgstr "%{name}의 자동 갱신 비활성화 실패"
 
 
-#: src/components/Notification/notifications.ts:45 src/language/constants.ts:52
+#: src/components/Notification/notifications.ts:63 src/language/constants.ts:52
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Site Error"
 msgid "Disable Remote Site Error"
 msgstr "인증서 갱신 오류"
 msgstr "인증서 갱신 오류"
 
 
-#: src/components/Notification/notifications.ts:69
+#: src/components/Notification/notifications.ts:87
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Site Maintenance Error"
 msgid "Disable Remote Site Maintenance Error"
 msgstr "인증서 갱신 오류"
 msgstr "인증서 갱신 오류"
 
 
-#: src/components/Notification/notifications.ts:73
+#: src/components/Notification/notifications.ts:91
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Site Maintenance Success"
 msgid "Disable Remote Site Maintenance Success"
 msgstr "인증서 갱신 성공"
 msgstr "인증서 갱신 성공"
 
 
-#: src/components/Notification/notifications.ts:49 src/language/constants.ts:51
+#: src/components/Notification/notifications.ts:67 src/language/constants.ts:51
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Site Success"
 msgid "Disable Remote Site Success"
 msgstr "인증서 갱신 성공"
 msgstr "인증서 갱신 성공"
 
 
-#: src/components/Notification/notifications.ts:103
+#: src/components/Notification/notifications.ts:121
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Stream Error"
 msgid "Disable Remote Stream Error"
 msgstr "인증서 갱신 오류"
 msgstr "인증서 갱신 오류"
 
 
-#: src/components/Notification/notifications.ts:107
+#: src/components/Notification/notifications.ts:125
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Stream Success"
 msgid "Disable Remote Stream Success"
 msgstr "인증서 갱신 성공"
 msgstr "인증서 갱신 성공"
 
 
-#: src/components/Notification/notifications.ts:46
+#: src/components/Notification/notifications.ts:64
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} from %{node} failed"
 msgid "Disable site %{name} from %{node} failed"
 msgstr "%{node_name}에서 %{conf_name} 성공적으로 활성화됨"
 msgstr "%{node_name}에서 %{conf_name} 성공적으로 활성화됨"
 
 
-#: src/components/Notification/notifications.ts:50
+#: src/components/Notification/notifications.ts:68
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} from %{node} successfully"
 msgid "Disable site %{name} from %{node} successfully"
 msgstr "%{node_name}에서 %{conf_name} 성공적으로 활성화됨"
 msgstr "%{node_name}에서 %{conf_name} 성공적으로 활성화됨"
 
 
-#: src/components/Notification/notifications.ts:70
+#: src/components/Notification/notifications.ts:88
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} maintenance on %{node} failed"
 msgid "Disable site %{name} maintenance on %{node} failed"
 msgstr "%{node_name}에서 %{conf_name} 성공적으로 활성화됨"
 msgstr "%{node_name}에서 %{conf_name} 성공적으로 활성화됨"
 
 
-#: src/components/Notification/notifications.ts:74
+#: src/components/Notification/notifications.ts:92
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} maintenance on %{node} successfully"
 msgid "Disable site %{name} maintenance on %{node} successfully"
 msgstr "%{node_name}에서 %{conf_name} 성공적으로 활성화됨"
 msgstr "%{node_name}에서 %{conf_name} 성공적으로 활성화됨"
 
 
-#: src/components/Notification/notifications.ts:104
+#: src/components/Notification/notifications.ts:122
 #, fuzzy
 #, fuzzy
 msgid "Disable stream %{name} from %{node} failed"
 msgid "Disable stream %{name} from %{node} failed"
 msgstr "%{node_name}에서 %{conf_name} 활성화 실패"
 msgstr "%{node_name}에서 %{conf_name} 활성화 실패"
 
 
-#: src/components/Notification/notifications.ts:108
+#: src/components/Notification/notifications.ts:126
 #, fuzzy
 #, fuzzy
 msgid "Disable stream %{name} from %{node} successfully"
 msgid "Disable stream %{name} from %{node} successfully"
 msgstr "%{node_name}에서 %{conf_name} 성공적으로 활성화됨"
 msgstr "%{node_name}에서 %{conf_name} 성공적으로 활성화됨"
@@ -1028,7 +1056,7 @@ msgid ""
 msgstr ""
 msgstr ""
 
 
 #: src/views/site/site_list/SiteDuplicate.vue:72
 #: src/views/site/site_list/SiteDuplicate.vue:72
-#: src/views/site/site_list/SiteList.vue:158
+#: src/views/site/site_list/SiteList.vue:162
 #: src/views/stream/components/StreamDuplicate.vue:64
 #: src/views/stream/components/StreamDuplicate.vue:64
 #: src/views/stream/StreamList.vue:222
 #: src/views/stream/StreamList.vue:222
 msgid "Duplicate"
 msgid "Duplicate"
@@ -1098,62 +1126,62 @@ msgstr "활성화 실패"
 msgid "Enable HTTPS"
 msgid "Enable HTTPS"
 msgstr "TLS 활성화"
 msgstr "TLS 활성화"
 
 
-#: src/components/Notification/notifications.ts:53 src/language/constants.ts:54
+#: src/components/Notification/notifications.ts:71 src/language/constants.ts:54
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Site Error"
 msgid "Enable Remote Site Error"
 msgstr "인증서 갱신 오류"
 msgstr "인증서 갱신 오류"
 
 
-#: src/components/Notification/notifications.ts:61
+#: src/components/Notification/notifications.ts:79
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Site Maintenance Error"
 msgid "Enable Remote Site Maintenance Error"
 msgstr "인증서 갱신 오류"
 msgstr "인증서 갱신 오류"
 
 
-#: src/components/Notification/notifications.ts:65
+#: src/components/Notification/notifications.ts:83
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Site Maintenance Success"
 msgid "Enable Remote Site Maintenance Success"
 msgstr "인증서 갱신 성공"
 msgstr "인증서 갱신 성공"
 
 
-#: src/components/Notification/notifications.ts:57 src/language/constants.ts:53
+#: src/components/Notification/notifications.ts:75 src/language/constants.ts:53
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Site Success"
 msgid "Enable Remote Site Success"
 msgstr "인증서 갱신 성공"
 msgstr "인증서 갱신 성공"
 
 
-#: src/components/Notification/notifications.ts:111
+#: src/components/Notification/notifications.ts:129
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Stream Error"
 msgid "Enable Remote Stream Error"
 msgstr "인증서 갱신 오류"
 msgstr "인증서 갱신 오류"
 
 
-#: src/components/Notification/notifications.ts:115
+#: src/components/Notification/notifications.ts:133
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Stream Success"
 msgid "Enable Remote Stream Success"
 msgstr "인증서 갱신 성공"
 msgstr "인증서 갱신 성공"
 
 
-#: src/components/Notification/notifications.ts:62
+#: src/components/Notification/notifications.ts:80
 #, fuzzy
 #, fuzzy
 msgid "Enable site %{name} maintenance on %{node} failed"
 msgid "Enable site %{name} maintenance on %{node} failed"
 msgstr "%{node_name}에서 %{conf_name} 활성화 실패"
 msgstr "%{node_name}에서 %{conf_name} 활성화 실패"
 
 
-#: src/components/Notification/notifications.ts:66
+#: src/components/Notification/notifications.ts:84
 #, fuzzy
 #, fuzzy
 msgid "Enable site %{name} maintenance on %{node} successfully"
 msgid "Enable site %{name} maintenance on %{node} successfully"
 msgstr "%{node_name}에서 %{conf_name} 성공적으로 활성화됨"
 msgstr "%{node_name}에서 %{conf_name} 성공적으로 활성화됨"
 
 
-#: src/components/Notification/notifications.ts:54
+#: src/components/Notification/notifications.ts:72
 #, fuzzy
 #, fuzzy
 msgid "Enable site %{name} on %{node} failed"
 msgid "Enable site %{name} on %{node} failed"
 msgstr "%{node_name}에서 %{conf_name} 활성화 실패"
 msgstr "%{node_name}에서 %{conf_name} 활성화 실패"
 
 
-#: src/components/Notification/notifications.ts:58
+#: src/components/Notification/notifications.ts:76
 #, fuzzy
 #, fuzzy
 msgid "Enable site %{name} on %{node} successfully"
 msgid "Enable site %{name} on %{node} successfully"
 msgstr "%{node_name}에서 %{conf_name} 성공적으로 활성화됨"
 msgstr "%{node_name}에서 %{conf_name} 성공적으로 활성화됨"
 
 
-#: src/components/Notification/notifications.ts:112
+#: src/components/Notification/notifications.ts:130
 #, fuzzy
 #, fuzzy
 msgid "Enable stream %{name} on %{node} failed"
 msgid "Enable stream %{name} on %{node} failed"
 msgstr "%{node_name}에서 %{conf_name} 활성화 실패"
 msgstr "%{node_name}에서 %{conf_name} 활성화 실패"
 
 
-#: src/components/Notification/notifications.ts:116
+#: src/components/Notification/notifications.ts:134
 #, fuzzy
 #, fuzzy
 msgid "Enable stream %{name} on %{node} successfully"
 msgid "Enable stream %{name} on %{node} successfully"
 msgstr "%{node_name}에서 %{conf_name} 성공적으로 활성화됨"
 msgstr "%{node_name}에서 %{conf_name} 성공적으로 활성화됨"
@@ -1244,6 +1272,11 @@ msgstr "%{date}에 만료됨"
 msgid "Export"
 msgid "Export"
 msgstr "내보내기"
 msgstr "내보내기"
 
 
+#: src/views/preference/ExternalNotify.vue:10
+#: src/views/preference/Preference.vue:169
+msgid "External Notify"
+msgstr ""
+
 #: src/views/site/cert/components/ObtainCertLive.vue:94
 #: src/views/site/cert/components/ObtainCertLive.vue:94
 #, fuzzy
 #, fuzzy
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
@@ -1646,7 +1679,7 @@ msgstr "홈"
 msgid "Host"
 msgid "Host"
 msgstr "HTTP 호스트"
 msgstr "HTTP 호스트"
 
 
-#: src/views/preference/Preference.vue:174
+#: src/views/preference/Preference.vue:181
 #, fuzzy
 #, fuzzy
 msgid "HTTP"
 msgid "HTTP"
 msgstr "HTTP01"
 msgstr "HTTP01"
@@ -1704,12 +1737,12 @@ msgid "Import Certificate"
 msgstr "인증서 상태"
 msgstr "인증서 상태"
 
 
 #: src/views/nginx_log/NginxLogList.vue:137
 #: src/views/nginx_log/NginxLogList.vue:137
-#: src/views/site/site_list/SiteList.vue:128
+#: src/views/site/site_list/SiteList.vue:132
 msgid "Indexed"
 msgid "Indexed"
 msgstr ""
 msgstr ""
 
 
 #: src/views/nginx_log/NginxLogList.vue:134
 #: src/views/nginx_log/NginxLogList.vue:134
-#: src/views/site/site_list/SiteList.vue:125
+#: src/views/site/site_list/SiteList.vue:129
 msgid "Indexing..."
 msgid "Indexing..."
 msgstr ""
 msgstr ""
 
 
@@ -1794,6 +1827,11 @@ msgstr "Invalid E-mail!"
 msgid "Invalid folder name"
 msgid "Invalid folder name"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/notification.ts:3
+#, fuzzy
+msgid "Invalid notifier config"
+msgstr "유효함"
+
 #: src/constants/errors/user.ts:4
 #: src/constants/errors/user.ts:4
 #, fuzzy
 #, fuzzy
 msgid "Invalid otp code"
 msgid "Invalid otp code"
@@ -1857,6 +1895,10 @@ msgstr ""
 msgid "Key Type"
 msgid "Key Type"
 msgstr "키 유형"
 msgstr "키 유형"
 
 
+#: src/views/preference/components/ExternalNotify/columns.ts:29
+msgid "Language"
+msgstr ""
+
 #: src/views/system/Upgrade.vue:179
 #: src/views/system/Upgrade.vue:179
 msgid "Last checked at"
 msgid "Last checked at"
 msgstr "마지막 확인 시간"
 msgstr "마지막 확인 시간"
@@ -1961,7 +2003,7 @@ msgstr "로그인 성공"
 msgid "Logout successful"
 msgid "Logout successful"
 msgstr "로그아웃 성공"
 msgstr "로그아웃 성공"
 
 
-#: src/views/preference/Preference.vue:210
+#: src/views/preference/Preference.vue:217
 msgid "Logrotate"
 msgid "Logrotate"
 msgstr "로그관리"
 msgstr "로그관리"
 
 
@@ -2009,7 +2051,7 @@ msgstr ""
 msgid "Manage Configs"
 msgid "Manage Configs"
 msgstr "구성 관리"
 msgstr "구성 관리"
 
 
-#: src/routes/modules/sites.ts:10 src/views/site/site_list/SiteList.vue:121
+#: src/routes/modules/sites.ts:10 src/views/site/site_list/SiteList.vue:125
 msgid "Manage Sites"
 msgid "Manage Sites"
 msgstr "사이트 관리"
 msgstr "사이트 관리"
 
 
@@ -2092,7 +2134,7 @@ msgstr "단일 지시문"
 #: src/views/nginx_log/NginxLogList.vue:37
 #: src/views/nginx_log/NginxLogList.vue:37
 #: src/views/preference/components/AddPasskey.vue:75
 #: src/views/preference/components/AddPasskey.vue:75
 #: src/views/site/ngx_conf/NgxUpstream.vue:177
 #: src/views/site/ngx_conf/NgxUpstream.vue:177
-#: src/views/site/site_edit/RightSettings.vue:64
+#: src/views/site/site_edit/RightSettings.vue:63
 #: src/views/site/site_list/columns.tsx:17
 #: src/views/site/site_list/columns.tsx:17
 #: src/views/site/site_list/SiteDuplicate.vue:79
 #: src/views/site/site_list/SiteDuplicate.vue:79
 #: src/views/stream/components/RightSettings.vue:87
 #: src/views/stream/components/RightSettings.vue:87
@@ -2142,7 +2184,7 @@ msgstr "새 버전 출시"
 msgid "Next"
 msgid "Next"
 msgstr "다음"
 msgstr "다음"
 
 
-#: src/views/preference/Preference.vue:198
+#: src/views/preference/Preference.vue:205
 msgid "Nginx"
 msgid "Nginx"
 msgstr "Nginx"
 msgstr "Nginx"
 
 
@@ -2287,7 +2329,7 @@ msgstr "Nginx 구성 오류름"
 #: src/views/preference/CertSettings.vue:73
 #: src/views/preference/CertSettings.vue:73
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:97
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:97
 #: src/views/site/ngx_conf/LocationEditor.vue:88
 #: src/views/site/ngx_conf/LocationEditor.vue:88
-#: src/views/site/site_list/SiteList.vue:161
+#: src/views/site/site_list/SiteList.vue:165
 #: src/views/stream/StreamList.vue:225
 #: src/views/stream/StreamList.vue:225
 msgid "No"
 msgid "No"
 msgstr "아니요"
 msgstr "아니요"
@@ -2302,12 +2344,12 @@ msgstr "작업"
 msgid "No records selected"
 msgid "No records selected"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/Preference.vue:168
+#: src/views/preference/Preference.vue:175
 #, fuzzy
 #, fuzzy
 msgid "Node"
 msgid "Node"
 msgstr "이름 변경"
 msgstr "이름 변경"
 
 
-#: src/views/site/site_edit/RightSettings.vue:67
+#: src/views/site/site_edit/RightSettings.vue:66
 #: src/views/site/site_list/columns.tsx:63
 #: src/views/site/site_list/columns.tsx:63
 #: src/views/stream/components/RightSettings.vue:90
 #: src/views/stream/components/RightSettings.vue:90
 #: src/views/stream/StreamList.vue:30
 #: src/views/stream/StreamList.vue:30
@@ -2352,7 +2394,7 @@ msgstr "유효 시작일: %{date}"
 msgid "Note"
 msgid "Note"
 msgstr "참고"
 msgstr "참고"
 
 
-#: src/views/site/site_edit/RightSettings.vue:96
+#: src/views/site/site_edit/RightSettings.vue:95
 #: src/views/stream/components/RightSettings.vue:118
 #: src/views/stream/components/RightSettings.vue:118
 msgid ""
 msgid ""
 "Note, if the configuration file include other configurations or "
 "Note, if the configuration file include other configurations or "
@@ -2370,6 +2412,11 @@ msgstr "알림"
 msgid "Notifications"
 msgid "Notifications"
 msgstr "알림"
 msgstr "알림"
 
 
+#: src/constants/errors/notification.ts:2
+#, fuzzy
+msgid "Notifier not found"
+msgstr "파일을 찾을 수 없음"
+
 #: src/views/site/cert/components/ObtainCert.vue:182
 #: src/views/site/cert/components/ObtainCert.vue:182
 #, fuzzy
 #, fuzzy
 msgid "Obtain certificate"
 msgid "Obtain certificate"
@@ -2413,7 +2460,7 @@ msgstr ""
 #: src/views/site/ngx_conf/NgxServer.vue:79
 #: src/views/site/ngx_conf/NgxServer.vue:79
 #: src/views/site/ngx_conf/NgxUpstream.vue:33
 #: src/views/site/ngx_conf/NgxUpstream.vue:33
 #: src/views/site/site_edit/components/SiteStatusSegmented.vue:121
 #: src/views/site/site_edit/components/SiteStatusSegmented.vue:121
-#: src/views/site/site_list/SiteList.vue:162
+#: src/views/site/site_list/SiteList.vue:166
 #: src/views/stream/components/RightSettings.vue:54
 #: src/views/stream/components/RightSettings.vue:54
 #: src/views/stream/StreamList.vue:226
 #: src/views/stream/StreamList.vue:226
 #: src/views/system/Backup/BackupCreator.vue:149
 #: src/views/system/Backup/BackupCreator.vue:149
@@ -2436,7 +2483,7 @@ msgstr "온라인"
 msgid "Only zip files are allowed"
 msgid "Only zip files are allowed"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/Preference.vue:204
+#: src/views/preference/Preference.vue:211
 msgid "OpenAI"
 msgid "OpenAI"
 msgstr "오픈AI"
 msgstr "오픈AI"
 
 
@@ -2578,7 +2625,7 @@ msgstr ""
 "먼저 인증서 > DNS 자격 증명에 자격 증명을 추가한 다음,DNS 제공자의 API를 요청"
 "먼저 인증서 > DNS 자격 증명에 자격 증명을 추가한 다음,DNS 제공자의 API를 요청"
 "하려면 아래 자격 증명 중 하나를 선택해주세요."
 "하려면 아래 자격 증명 중 하나를 선택해주세요."
 
 
-#: src/components/Notification/notifications.ts:138
+#: src/components/Notification/notifications.ts:156
 #: src/language/constants.ts:59
 #: src/language/constants.ts:59
 msgid ""
 msgid ""
 "Please generate new recovery codes in the preferences immediately to prevent "
 "Please generate new recovery codes in the preferences immediately to prevent "
@@ -2673,7 +2720,7 @@ msgstr "작업"
 msgid "Pre-release"
 msgid "Pre-release"
 msgstr "사전 출시"
 msgstr "사전 출시"
 
 
-#: src/routes/modules/preference.ts:10 src/views/preference/Preference.vue:151
+#: src/routes/modules/preference.ts:10 src/views/preference/Preference.vue:152
 msgid "Preference"
 msgid "Preference"
 msgstr "환경설정"
 msgstr "환경설정"
 
 
@@ -2816,22 +2863,22 @@ msgstr "리로드"
 msgid "Reload Nginx"
 msgid "Reload Nginx"
 msgstr "Nginx 리로딩 중"
 msgstr "Nginx 리로딩 중"
 
 
-#: src/components/Notification/notifications.ts:144
+#: src/components/Notification/notifications.ts:10
 #, fuzzy
 #, fuzzy
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgstr "사이트 삭제: %{site_name}"
 msgstr "사이트 삭제: %{site_name}"
 
 
-#: src/components/Notification/notifications.ts:148
+#: src/components/Notification/notifications.ts:14
 #, fuzzy
 #, fuzzy
 msgid "Reload Nginx on %{node} successfully"
 msgid "Reload Nginx on %{node} successfully"
 msgstr "성공적으로 저장되었습니다"
 msgstr "성공적으로 저장되었습니다"
 
 
-#: src/components/Notification/notifications.ts:143
+#: src/components/Notification/notifications.ts:9
 #, fuzzy
 #, fuzzy
 msgid "Reload Remote Nginx Error"
 msgid "Reload Remote Nginx Error"
 msgstr "인증서 갱신 오류"
 msgstr "인증서 갱신 오류"
 
 
-#: src/components/Notification/notifications.ts:147
+#: src/components/Notification/notifications.ts:13
 #, fuzzy
 #, fuzzy
 msgid "Reload Remote Nginx Success"
 msgid "Reload Remote Nginx Success"
 msgstr "인증서 갱신 성공"
 msgstr "인증서 갱신 성공"
@@ -2873,62 +2920,62 @@ msgstr "성공적으로 제거됨"
 msgid "Rename"
 msgid "Rename"
 msgstr "이름 변경"
 msgstr "이름 변경"
 
 
-#: src/components/Notification/notifications.ts:28
+#: src/components/Notification/notifications.ts:46
 #, fuzzy
 #, fuzzy
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} failed"
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} failed"
 msgstr "%{conf_name}을(를) %{node_name}(으)로 성공적으로 복제함"
 msgstr "%{conf_name}을(를) %{node_name}(으)로 성공적으로 복제함"
 
 
-#: src/components/Notification/notifications.ts:32
+#: src/components/Notification/notifications.ts:50
 #, fuzzy
 #, fuzzy
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} successfully"
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} successfully"
 msgstr "%{conf_name}을(를) %{node_name}(으)로 성공적으로 복제함"
 msgstr "%{conf_name}을(를) %{node_name}(으)로 성공적으로 복제함"
 
 
-#: src/components/Notification/notifications.ts:27 src/language/constants.ts:42
+#: src/components/Notification/notifications.ts:45 src/language/constants.ts:42
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Config Error"
 msgid "Rename Remote Config Error"
 msgstr "인증서 갱신 오류"
 msgstr "인증서 갱신 오류"
 
 
-#: src/components/Notification/notifications.ts:31 src/language/constants.ts:41
+#: src/components/Notification/notifications.ts:49 src/language/constants.ts:41
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Config Success"
 msgid "Rename Remote Config Success"
 msgstr "인증서 갱신 성공"
 msgstr "인증서 갱신 성공"
 
 
-#: src/components/Notification/notifications.ts:77 src/language/constants.ts:56
+#: src/components/Notification/notifications.ts:95 src/language/constants.ts:56
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Site Error"
 msgid "Rename Remote Site Error"
 msgstr "인증서 갱신 오류"
 msgstr "인증서 갱신 오류"
 
 
-#: src/components/Notification/notifications.ts:81 src/language/constants.ts:55
+#: src/components/Notification/notifications.ts:99 src/language/constants.ts:55
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Site Success"
 msgid "Rename Remote Site Success"
 msgstr "인증서 갱신 성공"
 msgstr "인증서 갱신 성공"
 
 
-#: src/components/Notification/notifications.ts:119
+#: src/components/Notification/notifications.ts:137
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Stream Error"
 msgid "Rename Remote Stream Error"
 msgstr "인증서 갱신 오류"
 msgstr "인증서 갱신 오류"
 
 
-#: src/components/Notification/notifications.ts:123
+#: src/components/Notification/notifications.ts:141
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Stream Success"
 msgid "Rename Remote Stream Success"
 msgstr "인증서 갱신 성공"
 msgstr "인증서 갱신 성공"
 
 
-#: src/components/Notification/notifications.ts:78
+#: src/components/Notification/notifications.ts:96
 #, fuzzy
 #, fuzzy
 msgid "Rename site %{name} to %{new_name} on %{node} failed"
 msgid "Rename site %{name} to %{new_name} on %{node} failed"
 msgstr "%{conf_name}을(를) %{node_name}(으)로 성공적으로 복제함"
 msgstr "%{conf_name}을(를) %{node_name}(으)로 성공적으로 복제함"
 
 
-#: src/components/Notification/notifications.ts:82
+#: src/components/Notification/notifications.ts:100
 #, fuzzy
 #, fuzzy
 msgid "Rename site %{name} to %{new_name} on %{node} successfully"
 msgid "Rename site %{name} to %{new_name} on %{node} successfully"
 msgstr "%{conf_name}을(를) %{node_name}(으)로 성공적으로 복제함"
 msgstr "%{conf_name}을(를) %{node_name}(으)로 성공적으로 복제함"
 
 
-#: src/components/Notification/notifications.ts:120
+#: src/components/Notification/notifications.ts:138
 #, fuzzy
 #, fuzzy
 msgid "Rename stream %{name} to %{new_name} on %{node} failed"
 msgid "Rename stream %{name} to %{new_name} on %{node} failed"
 msgstr "%{conf_name}을(를) %{node_name}(으)로 성공적으로 복제함"
 msgstr "%{conf_name}을(를) %{node_name}(으)로 성공적으로 복제함"
 
 
-#: src/components/Notification/notifications.ts:124
+#: src/components/Notification/notifications.ts:142
 #, fuzzy
 #, fuzzy
 msgid "Rename stream %{name} to %{new_name} on %{node} successfully"
 msgid "Rename stream %{name} to %{new_name} on %{node} successfully"
 msgstr "%{conf_name}을(를) %{node_name}(으)로 성공적으로 복제함"
 msgstr "%{conf_name}을(를) %{node_name}(으)로 성공적으로 복제함"
@@ -2995,22 +3042,22 @@ msgstr "재시작"
 msgid "Restart Nginx"
 msgid "Restart Nginx"
 msgstr "재시작 중"
 msgstr "재시작 중"
 
 
-#: src/components/Notification/notifications.ts:152
+#: src/components/Notification/notifications.ts:18
 #, fuzzy
 #, fuzzy
 msgid "Restart Nginx on %{node} failed, response: %{resp}"
 msgid "Restart Nginx on %{node} failed, response: %{resp}"
 msgstr "%{node_name}에서 %{conf_name} 성공적으로 활성화됨"
 msgstr "%{node_name}에서 %{conf_name} 성공적으로 활성화됨"
 
 
-#: src/components/Notification/notifications.ts:156
+#: src/components/Notification/notifications.ts:22
 #, fuzzy
 #, fuzzy
 msgid "Restart Nginx on %{node} successfully"
 msgid "Restart Nginx on %{node} successfully"
 msgstr "성공적으로 저장되었습니다"
 msgstr "성공적으로 저장되었습니다"
 
 
-#: src/components/Notification/notifications.ts:151
+#: src/components/Notification/notifications.ts:17
 #, fuzzy
 #, fuzzy
 msgid "Restart Remote Nginx Error"
 msgid "Restart Remote Nginx Error"
 msgstr "인증서 갱신 오류"
 msgstr "인증서 갱신 오류"
 
 
-#: src/components/Notification/notifications.ts:155
+#: src/components/Notification/notifications.ts:21
 #, fuzzy
 #, fuzzy
 msgid "Restart Remote Nginx Success"
 msgid "Restart Remote Nginx Success"
 msgstr "인증서 갱신 성공"
 msgstr "인증서 갱신 성공"
@@ -3078,7 +3125,7 @@ msgstr "실행 중"
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/ConfigEditor.vue:271
 #: src/views/config/ConfigEditor.vue:271
 #: src/views/preference/components/Passkey.vue:130
 #: src/views/preference/components/Passkey.vue:130
-#: src/views/preference/Preference.vue:221
+#: src/views/preference/Preference.vue:228
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:127
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:127
 #: src/views/site/site_edit/components/ConfigName.vue:52
 #: src/views/site/site_edit/components/ConfigName.vue:52
 #: src/views/site/site_edit/SiteEdit.vue:292
 #: src/views/site/site_edit/SiteEdit.vue:292
@@ -3096,42 +3143,44 @@ msgstr "지시문 저장"
 msgid "Save error %{msg}"
 msgid "Save error %{msg}"
 msgstr "저장 오류 %{msg}"
 msgstr "저장 오류 %{msg}"
 
 
-#: src/components/Notification/notifications.ts:85 src/language/constants.ts:48
+#: src/components/Notification/notifications.ts:103
+#: src/language/constants.ts:48
 #, fuzzy
 #, fuzzy
 msgid "Save Remote Site Error"
 msgid "Save Remote Site Error"
 msgstr "인증서 갱신 오류"
 msgstr "인증서 갱신 오류"
 
 
-#: src/components/Notification/notifications.ts:89 src/language/constants.ts:47
+#: src/components/Notification/notifications.ts:107
+#: src/language/constants.ts:47
 #, fuzzy
 #, fuzzy
 msgid "Save Remote Site Success"
 msgid "Save Remote Site Success"
 msgstr "인증서 갱신 성공"
 msgstr "인증서 갱신 성공"
 
 
-#: src/components/Notification/notifications.ts:127
+#: src/components/Notification/notifications.ts:145
 #, fuzzy
 #, fuzzy
 msgid "Save Remote Stream Error"
 msgid "Save Remote Stream Error"
 msgstr "인증서 갱신 오류"
 msgstr "인증서 갱신 오류"
 
 
-#: src/components/Notification/notifications.ts:131
+#: src/components/Notification/notifications.ts:149
 #, fuzzy
 #, fuzzy
 msgid "Save Remote Stream Success"
 msgid "Save Remote Stream Success"
 msgstr "인증서 갱신 성공"
 msgstr "인증서 갱신 성공"
 
 
-#: src/components/Notification/notifications.ts:86
+#: src/components/Notification/notifications.ts:104
 #, fuzzy
 #, fuzzy
 msgid "Save site %{name} to %{node} failed"
 msgid "Save site %{name} to %{node} failed"
 msgstr "%{conf_name}을(를) %{node_name}(으)로 성공적으로 복제함"
 msgstr "%{conf_name}을(를) %{node_name}(으)로 성공적으로 복제함"
 
 
-#: src/components/Notification/notifications.ts:90
+#: src/components/Notification/notifications.ts:108
 #, fuzzy
 #, fuzzy
 msgid "Save site %{name} to %{node} successfully"
 msgid "Save site %{name} to %{node} successfully"
 msgstr "%{conf_name}을(를) %{node_name}(으)로 성공적으로 복제함"
 msgstr "%{conf_name}을(를) %{node_name}(으)로 성공적으로 복제함"
 
 
-#: src/components/Notification/notifications.ts:128
+#: src/components/Notification/notifications.ts:146
 #, fuzzy
 #, fuzzy
 msgid "Save stream %{name} to %{node} failed"
 msgid "Save stream %{name} to %{node} failed"
 msgstr "%{conf_name}을(를) %{node_name}(으)로 배포 실패"
 msgstr "%{conf_name}을(를) %{node_name}(으)로 배포 실패"
 
 
-#: src/components/Notification/notifications.ts:132
+#: src/components/Notification/notifications.ts:150
 #, fuzzy
 #, fuzzy
 msgid "Save stream %{name} to %{node} successfully"
 msgid "Save stream %{name} to %{node} successfully"
 msgstr "%{conf_name}을(를) %{node_name}(으)로 성공적으로 복제함"
 msgstr "%{conf_name}을(를) %{node_name}(으)로 성공적으로 복제함"
@@ -3139,7 +3188,7 @@ msgstr "%{conf_name}을(를) %{node_name}(으)로 성공적으로 복제함"
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:47
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:47
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:97
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:97
 #: src/views/certificate/CertificateEditor.vue:49
 #: src/views/certificate/CertificateEditor.vue:49
-#: src/views/preference/Preference.vue:123
+#: src/views/preference/Preference.vue:124
 #, fuzzy
 #, fuzzy
 msgid "Save successfully"
 msgid "Save successfully"
 msgstr "성공적으로 저장됨"
 msgstr "성공적으로 저장됨"
@@ -3160,6 +3209,10 @@ msgstr ""
 msgid "SDK"
 msgid "SDK"
 msgstr ""
 msgstr ""
 
 
+#: src/views/preference/components/ExternalNotify/dingtalk.ts:13
+msgid "Secret (Optional)"
+msgstr ""
+
 #: src/views/preference/components/TOTP.vue:109
 #: src/views/preference/components/TOTP.vue:109
 msgid "Secret has been copied"
 msgid "Secret has been copied"
 msgstr ""
 msgstr ""
@@ -3190,7 +3243,7 @@ msgstr ""
 msgid "Send"
 msgid "Send"
 msgstr "보내기"
 msgstr "보내기"
 
 
-#: src/views/preference/Preference.vue:156
+#: src/views/preference/Preference.vue:157
 #, fuzzy
 #, fuzzy
 msgid "Server"
 msgid "Server"
 msgstr "서버 정보"
 msgstr "서버 정보"
@@ -3199,6 +3252,11 @@ msgstr "서버 정보"
 msgid "Server Info"
 msgid "Server Info"
 msgstr "서버 정보"
 msgstr "서버 정보"
 
 
+#: src/views/preference/components/ExternalNotify/bark.ts:13
+#, fuzzy
+msgid "Server URL"
+msgstr "서버 정보"
+
 #: src/views/site/cert/components/ObtainCert.vue:107
 #: src/views/site/cert/components/ObtainCert.vue:107
 msgid "server_name not found in directives"
 msgid "server_name not found in directives"
 msgstr "directives에서 server_name을 찾을 수 없습니다"
 msgstr "directives에서 server_name을 찾을 수 없습니다"
@@ -3377,7 +3435,7 @@ msgstr ""
 #: src/views/certificate/ACMEUser.vue:65
 #: src/views/certificate/ACMEUser.vue:65
 #: src/views/certificate/CertificateList/certColumns.tsx:65
 #: src/views/certificate/CertificateList/certColumns.tsx:65
 #: src/views/environments/list/envColumns.tsx:44
 #: src/views/environments/list/envColumns.tsx:44
-#: src/views/site/site_edit/RightSettings.vue:56
+#: src/views/site/site_edit/RightSettings.vue:55
 #: src/views/site/site_list/columns.tsx:80 src/views/stream/StreamList.vue:47
 #: src/views/site/site_list/columns.tsx:80 src/views/stream/StreamList.vue:47
 msgid "Status"
 msgid "Status"
 msgstr "상태"
 msgstr "상태"
@@ -3454,42 +3512,42 @@ msgstr ""
 msgid "Sync Certificate"
 msgid "Sync Certificate"
 msgstr "인증서 갱신"
 msgstr "인증서 갱신"
 
 
-#: src/components/Notification/notifications.ts:10
+#: src/components/Notification/notifications.ts:28
 #, fuzzy
 #, fuzzy
 msgid "Sync Certificate %{cert_name} to %{env_name} failed"
 msgid "Sync Certificate %{cert_name} to %{env_name} failed"
 msgstr "%{conf_name}을(를) %{node_name}(으)로 성공적으로 복제함"
 msgstr "%{conf_name}을(를) %{node_name}(으)로 성공적으로 복제함"
 
 
-#: src/components/Notification/notifications.ts:14
+#: src/components/Notification/notifications.ts:32
 #, fuzzy
 #, fuzzy
 msgid "Sync Certificate %{cert_name} to %{env_name} successfully"
 msgid "Sync Certificate %{cert_name} to %{env_name} successfully"
 msgstr "%{conf_name}을(를) %{node_name}(으)로 성공적으로 복제함"
 msgstr "%{conf_name}을(를) %{node_name}(으)로 성공적으로 복제함"
 
 
-#: src/components/Notification/notifications.ts:9 src/language/constants.ts:39
+#: src/components/Notification/notifications.ts:27 src/language/constants.ts:39
 #, fuzzy
 #, fuzzy
 msgid "Sync Certificate Error"
 msgid "Sync Certificate Error"
 msgstr "인증서 갱신 오류"
 msgstr "인증서 갱신 오류"
 
 
-#: src/components/Notification/notifications.ts:13 src/language/constants.ts:38
+#: src/components/Notification/notifications.ts:31 src/language/constants.ts:38
 #, fuzzy
 #, fuzzy
 msgid "Sync Certificate Success"
 msgid "Sync Certificate Success"
 msgstr "인증서 갱신 성공"
 msgstr "인증서 갱신 성공"
 
 
-#: src/components/Notification/notifications.ts:20
+#: src/components/Notification/notifications.ts:38
 #, fuzzy
 #, fuzzy
 msgid "Sync config %{config_name} to %{env_name} failed"
 msgid "Sync config %{config_name} to %{env_name} failed"
 msgstr "%{conf_name}을(를) %{node_name}(으)로 성공적으로 복제함"
 msgstr "%{conf_name}을(를) %{node_name}(으)로 성공적으로 복제함"
 
 
-#: src/components/Notification/notifications.ts:24
+#: src/components/Notification/notifications.ts:42
 #, fuzzy
 #, fuzzy
 msgid "Sync config %{config_name} to %{env_name} successfully"
 msgid "Sync config %{config_name} to %{env_name} successfully"
 msgstr "%{conf_name}을(를) %{node_name}(으)로 성공적으로 복제함"
 msgstr "%{conf_name}을(를) %{node_name}(으)로 성공적으로 복제함"
 
 
-#: src/components/Notification/notifications.ts:19 src/language/constants.ts:45
+#: src/components/Notification/notifications.ts:37 src/language/constants.ts:45
 #, fuzzy
 #, fuzzy
 msgid "Sync Config Error"
 msgid "Sync Config Error"
 msgstr "인증서 갱신 오류"
 msgstr "인증서 갱신 오류"
 
 
-#: src/components/Notification/notifications.ts:23 src/language/constants.ts:44
+#: src/components/Notification/notifications.ts:41 src/language/constants.ts:44
 #, fuzzy
 #, fuzzy
 msgid "Sync Config Success"
 msgid "Sync Config Success"
 msgstr "인증서 갱신 성공"
 msgstr "인증서 갱신 성공"
@@ -3499,8 +3557,8 @@ msgstr "인증서 갱신 성공"
 msgid "Sync Nodes"
 msgid "Sync Nodes"
 msgstr ""
 msgstr ""
 
 
-#: src/views/site/site_edit/RightSettings.vue:102
-#: src/views/site/site_edit/RightSettings.vue:89
+#: src/views/site/site_edit/RightSettings.vue:101
+#: src/views/site/site_edit/RightSettings.vue:88
 #: src/views/stream/components/RightSettings.vue:111
 #: src/views/stream/components/RightSettings.vue:111
 #: src/views/stream/components/RightSettings.vue:124
 #: src/views/stream/components/RightSettings.vue:124
 #, fuzzy
 #, fuzzy
@@ -3511,7 +3569,7 @@ msgstr "인증서 갱신"
 msgid "Sync to"
 msgid "Sync to"
 msgstr ""
 msgstr ""
 
 
-#: src/views/site/site_edit/RightSettings.vue:86
+#: src/views/site/site_edit/RightSettings.vue:85
 #: src/views/stream/components/RightSettings.vue:108
 #: src/views/stream/components/RightSettings.vue:108
 msgid "Synchronization"
 msgid "Synchronization"
 msgstr ""
 msgstr ""
@@ -3544,7 +3602,11 @@ msgstr "Nginx가 성공적으로 재시작됨"
 msgid "Task not found"
 msgid "Task not found"
 msgstr "파일을 찾을 수 없음"
 msgstr "파일을 찾을 수 없음"
 
 
-#: src/routes/modules/terminal.ts:10 src/views/preference/Preference.vue:180
+#: src/views/preference/components/ExternalNotify/telegram.ts:5
+msgid "Telegram"
+msgstr ""
+
+#: src/routes/modules/terminal.ts:10 src/views/preference/Preference.vue:187
 #: src/views/terminal/Terminal.vue:129
 #: src/views/terminal/Terminal.vue:129
 msgid "Terminal"
 msgid "Terminal"
 msgstr "터미널"
 msgstr "터미널"
@@ -3797,6 +3859,7 @@ msgstr ""
 #: src/views/certificate/CertificateList/certColumns.tsx:25
 #: src/views/certificate/CertificateList/certColumns.tsx:25
 #: src/views/nginx_log/NginxLogList.vue:21
 #: src/views/nginx_log/NginxLogList.vue:21
 #: src/views/notification/notificationColumns.tsx:9
 #: src/views/notification/notificationColumns.tsx:9
+#: src/views/preference/components/ExternalNotify/columns.ts:17
 msgid "Type"
 msgid "Type"
 msgstr "유형"
 msgstr "유형"
 
 
@@ -3814,7 +3877,7 @@ msgstr "성공적으로 저장되었습니다"
 #: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:325
 #: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:325
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/environments/list/envColumns.tsx:90
-#: src/views/site/site_edit/RightSettings.vue:76
+#: src/views/site/site_edit/RightSettings.vue:75
 #: src/views/site/site_list/columns.tsx:110
 #: src/views/site/site_list/columns.tsx:110
 #: src/views/stream/components/RightSettings.vue:99
 #: src/views/stream/components/RightSettings.vue:99
 #: src/views/stream/StreamList.vue:67 src/views/user/userColumns.tsx:54
 #: src/views/stream/StreamList.vue:67 src/views/user/userColumns.tsx:54
@@ -3983,7 +4046,7 @@ msgid ""
 "Pebble as CA."
 "Pebble as CA."
 msgstr ""
 msgstr ""
 
 
-#: src/views/site/site_edit/RightSettings.vue:92
+#: src/views/site/site_edit/RightSettings.vue:91
 msgid ""
 msgid ""
 "When you enable/disable, delete, or save this site, the nodes set in the "
 "When you enable/disable, delete, or save this site, the nodes set in the "
 "Node Group and the nodes selected below will be synchronized."
 "Node Group and the nodes selected below will be synchronized."

+ 158 - 102
app/src/language/messages.pot

@@ -23,6 +23,10 @@ msgstr ""
 msgid "Access Logs"
 msgid "Access Logs"
 msgstr ""
 msgstr ""
 
 
+#: src/views/preference/components/ExternalNotify/dingtalk.ts:9
+msgid "Access Token"
+msgstr ""
+
 #: src/routes/modules/certificates.ts:20
 #: src/routes/modules/certificates.ts:20
 #: src/views/certificate/ACMEUser.vue:113
 #: src/views/certificate/ACMEUser.vue:113
 #: src/views/certificate/ACMEUserSelector.vue:85
 #: src/views/certificate/ACMEUserSelector.vue:85
@@ -38,6 +42,7 @@ msgstr ""
 #: src/views/nginx_log/NginxLogList.vue:53
 #: src/views/nginx_log/NginxLogList.vue:53
 #: src/views/notification/notificationColumns.tsx:66
 #: src/views/notification/notificationColumns.tsx:66
 #: src/views/preference/AuthSettings.vue:30
 #: src/views/preference/AuthSettings.vue:30
+#: src/views/preference/components/ExternalNotify/columns.ts:46
 #: src/views/site/site_list/columns.tsx:117
 #: src/views/site/site_list/columns.tsx:117
 #: src/views/stream/StreamList.vue:74
 #: src/views/stream/StreamList.vue:74
 #: src/views/user/userColumns.tsx:60
 #: src/views/user/userColumns.tsx:60
@@ -105,7 +110,7 @@ msgstr ""
 msgid "All"
 msgid "All"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:137
+#: src/components/Notification/notifications.ts:155
 #: src/language/constants.ts:58
 #: src/language/constants.ts:58
 msgid "All Recovery Codes Have Been Used"
 msgid "All Recovery Codes Have Been Used"
 msgstr ""
 msgstr ""
@@ -130,7 +135,7 @@ msgstr ""
 msgid "API Type"
 msgid "API Type"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/Preference.vue:162
+#: src/views/preference/Preference.vue:163
 msgid "App"
 msgid "App"
 msgstr ""
 msgstr ""
 
 
@@ -183,7 +188,7 @@ msgstr ""
 msgid "Are you sure you want to delete this item?"
 msgid "Are you sure you want to delete this item?"
 msgstr ""
 msgstr ""
 
 
-#: src/views/site/site_list/SiteList.vue:163
+#: src/views/site/site_list/SiteList.vue:167
 #: src/views/stream/StreamList.vue:227
 #: src/views/stream/StreamList.vue:227
 msgid "Are you sure you want to delete?"
 msgid "Are you sure you want to delete?"
 msgstr ""
 msgstr ""
@@ -228,7 +233,7 @@ msgstr ""
 msgid "Attempts"
 msgid "Attempts"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/Preference.vue:186
+#: src/views/preference/Preference.vue:193
 msgid "Auth"
 msgid "Auth"
 msgstr ""
 msgstr ""
 
 
@@ -311,12 +316,16 @@ msgstr ""
 msgid "Banned Until"
 msgid "Banned Until"
 msgstr ""
 msgstr ""
 
 
+#: src/views/preference/components/ExternalNotify/bark.ts:5
+msgid "Bark"
+msgstr ""
+
 #: src/views/site/site_add/SiteAdd.vue:95
 #: src/views/site/site_add/SiteAdd.vue:95
 msgid "Base information"
 msgid "Base information"
 msgstr ""
 msgstr ""
 
 
 #: src/views/config/ConfigEditor.vue:290
 #: src/views/config/ConfigEditor.vue:290
-#: src/views/site/site_edit/RightSettings.vue:53
+#: src/views/site/site_edit/RightSettings.vue:52
 #: src/views/stream/components/RightSettings.vue:79
 #: src/views/stream/components/RightSettings.vue:79
 msgid "Basic"
 msgid "Basic"
 msgstr ""
 msgstr ""
@@ -347,6 +356,10 @@ msgstr ""
 msgid "Block is nil"
 msgid "Block is nil"
 msgstr ""
 msgstr ""
 
 
+#: src/views/preference/components/ExternalNotify/telegram.ts:9
+msgid "Bot Token"
+msgstr ""
+
 #: src/views/system/About.vue:55
 #: src/views/system/About.vue:55
 msgid "Build with"
 msgid "Build with"
 msgstr ""
 msgstr ""
@@ -386,7 +399,7 @@ msgstr ""
 msgid "Cannot remove initial user"
 msgid "Cannot remove initial user"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/Preference.vue:192
+#: src/views/preference/Preference.vue:199
 msgid "Cert"
 msgid "Cert"
 msgstr ""
 msgstr ""
 
 
@@ -454,6 +467,10 @@ msgstr ""
 msgid "Channel"
 msgid "Channel"
 msgstr ""
 msgstr ""
 
 
+#: src/views/preference/components/ExternalNotify/telegram.ts:13
+msgid "Chat ID"
+msgstr ""
+
 #: src/views/system/Upgrade.vue:185
 #: src/views/system/Upgrade.vue:185
 msgid "Check again"
 msgid "Check again"
 msgstr ""
 msgstr ""
@@ -637,6 +654,7 @@ msgstr ""
 
 
 #: src/views/environments/group/columns.ts:31
 #: src/views/environments/group/columns.ts:31
 #: src/views/notification/notificationColumns.tsx:59
 #: src/views/notification/notificationColumns.tsx:59
+#: src/views/preference/components/ExternalNotify/columns.ts:41
 #: src/views/preference/components/Passkey.vue:95
 #: src/views/preference/components/Passkey.vue:95
 #: src/views/user/userColumns.tsx:48
 #: src/views/user/userColumns.tsx:48
 msgid "Created at"
 msgid "Created at"
@@ -706,7 +724,7 @@ msgstr ""
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/views/site/ngx_conf/NgxServer.vue:110
 #: src/views/site/ngx_conf/NgxServer.vue:110
 #: src/views/site/ngx_conf/NgxUpstream.vue:128
 #: src/views/site/ngx_conf/NgxUpstream.vue:128
-#: src/views/site/site_list/SiteList.vue:172
+#: src/views/site/site_list/SiteList.vue:176
 #: src/views/stream/StreamList.vue:236
 #: src/views/stream/StreamList.vue:236
 msgid "Delete"
 msgid "Delete"
 msgstr ""
 msgstr ""
@@ -716,41 +734,41 @@ msgstr ""
 msgid "Delete Permanently"
 msgid "Delete Permanently"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:37
+#: src/components/Notification/notifications.ts:55
 #: src/language/constants.ts:50
 #: src/language/constants.ts:50
 msgid "Delete Remote Site Error"
 msgid "Delete Remote Site Error"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:41
+#: src/components/Notification/notifications.ts:59
 #: src/language/constants.ts:49
 #: src/language/constants.ts:49
 msgid "Delete Remote Site Success"
 msgid "Delete Remote Site Success"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:95
+#: src/components/Notification/notifications.ts:113
 msgid "Delete Remote Stream Error"
 msgid "Delete Remote Stream Error"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:99
+#: src/components/Notification/notifications.ts:117
 msgid "Delete Remote Stream Success"
 msgid "Delete Remote Stream Success"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:38
+#: src/components/Notification/notifications.ts:56
 msgid "Delete site %{name} from %{node} failed"
 msgid "Delete site %{name} from %{node} failed"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:42
+#: src/components/Notification/notifications.ts:60
 msgid "Delete site %{name} from %{node} successfully"
 msgid "Delete site %{name} from %{node} successfully"
 msgstr ""
 msgstr ""
 
 
-#: src/views/site/site_list/SiteList.vue:94
+#: src/views/site/site_list/SiteList.vue:98
 msgid "Delete site: %{site_name}"
 msgid "Delete site: %{site_name}"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:96
+#: src/components/Notification/notifications.ts:114
 msgid "Delete stream %{name} from %{node} failed"
 msgid "Delete stream %{name} from %{node} failed"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:100
+#: src/components/Notification/notifications.ts:118
 msgid "Delete stream %{name} from %{node} successfully"
 msgid "Delete stream %{name} from %{node} successfully"
 msgstr ""
 msgstr ""
 
 
@@ -788,6 +806,14 @@ msgstr ""
 msgid "Development Mode"
 msgid "Development Mode"
 msgstr ""
 msgstr ""
 
 
+#: src/views/preference/components/ExternalNotify/bark.ts:9
+msgid "Device Key"
+msgstr ""
+
+#: src/views/preference/components/ExternalNotify/dingtalk.ts:5
+msgid "DingTalk"
+msgstr ""
+
 #: src/views/site/ngx_conf/directive/DirectiveAdd.vue:89
 #: src/views/site/ngx_conf/directive/DirectiveAdd.vue:89
 msgid "Directive"
 msgid "Directive"
 msgstr ""
 msgstr ""
@@ -820,53 +846,53 @@ msgstr ""
 msgid "Disable auto-renewal failed for %{name}"
 msgid "Disable auto-renewal failed for %{name}"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:45
+#: src/components/Notification/notifications.ts:63
 #: src/language/constants.ts:52
 #: src/language/constants.ts:52
 msgid "Disable Remote Site Error"
 msgid "Disable Remote Site Error"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:69
+#: src/components/Notification/notifications.ts:87
 msgid "Disable Remote Site Maintenance Error"
 msgid "Disable Remote Site Maintenance Error"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:73
+#: src/components/Notification/notifications.ts:91
 msgid "Disable Remote Site Maintenance Success"
 msgid "Disable Remote Site Maintenance Success"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:49
+#: src/components/Notification/notifications.ts:67
 #: src/language/constants.ts:51
 #: src/language/constants.ts:51
 msgid "Disable Remote Site Success"
 msgid "Disable Remote Site Success"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:103
+#: src/components/Notification/notifications.ts:121
 msgid "Disable Remote Stream Error"
 msgid "Disable Remote Stream Error"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:107
+#: src/components/Notification/notifications.ts:125
 msgid "Disable Remote Stream Success"
 msgid "Disable Remote Stream Success"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:46
+#: src/components/Notification/notifications.ts:64
 msgid "Disable site %{name} from %{node} failed"
 msgid "Disable site %{name} from %{node} failed"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:50
+#: src/components/Notification/notifications.ts:68
 msgid "Disable site %{name} from %{node} successfully"
 msgid "Disable site %{name} from %{node} successfully"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:70
+#: src/components/Notification/notifications.ts:88
 msgid "Disable site %{name} maintenance on %{node} failed"
 msgid "Disable site %{name} maintenance on %{node} failed"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:74
+#: src/components/Notification/notifications.ts:92
 msgid "Disable site %{name} maintenance on %{node} successfully"
 msgid "Disable site %{name} maintenance on %{node} successfully"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:104
+#: src/components/Notification/notifications.ts:122
 msgid "Disable stream %{name} from %{node} failed"
 msgid "Disable stream %{name} from %{node} failed"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:108
+#: src/components/Notification/notifications.ts:126
 msgid "Disable stream %{name} from %{node} successfully"
 msgid "Disable stream %{name} from %{node} successfully"
 msgstr ""
 msgstr ""
 
 
@@ -973,7 +999,7 @@ msgid "Due to the security policies of some browsers, you cannot use passkeys on
 msgstr ""
 msgstr ""
 
 
 #: src/views/site/site_list/SiteDuplicate.vue:72
 #: src/views/site/site_list/SiteDuplicate.vue:72
-#: src/views/site/site_list/SiteList.vue:158
+#: src/views/site/site_list/SiteList.vue:162
 #: src/views/stream/components/StreamDuplicate.vue:64
 #: src/views/stream/components/StreamDuplicate.vue:64
 #: src/views/stream/StreamList.vue:222
 #: src/views/stream/StreamList.vue:222
 msgid "Duplicate"
 msgid "Duplicate"
@@ -1039,53 +1065,53 @@ msgstr ""
 msgid "Enable HTTPS"
 msgid "Enable HTTPS"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:53
+#: src/components/Notification/notifications.ts:71
 #: src/language/constants.ts:54
 #: src/language/constants.ts:54
 msgid "Enable Remote Site Error"
 msgid "Enable Remote Site Error"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:61
+#: src/components/Notification/notifications.ts:79
 msgid "Enable Remote Site Maintenance Error"
 msgid "Enable Remote Site Maintenance Error"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:65
+#: src/components/Notification/notifications.ts:83
 msgid "Enable Remote Site Maintenance Success"
 msgid "Enable Remote Site Maintenance Success"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:57
+#: src/components/Notification/notifications.ts:75
 #: src/language/constants.ts:53
 #: src/language/constants.ts:53
 msgid "Enable Remote Site Success"
 msgid "Enable Remote Site Success"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:111
+#: src/components/Notification/notifications.ts:129
 msgid "Enable Remote Stream Error"
 msgid "Enable Remote Stream Error"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:115
+#: src/components/Notification/notifications.ts:133
 msgid "Enable Remote Stream Success"
 msgid "Enable Remote Stream Success"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:62
+#: src/components/Notification/notifications.ts:80
 msgid "Enable site %{name} maintenance on %{node} failed"
 msgid "Enable site %{name} maintenance on %{node} failed"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:66
+#: src/components/Notification/notifications.ts:84
 msgid "Enable site %{name} maintenance on %{node} successfully"
 msgid "Enable site %{name} maintenance on %{node} successfully"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:54
+#: src/components/Notification/notifications.ts:72
 msgid "Enable site %{name} on %{node} failed"
 msgid "Enable site %{name} on %{node} failed"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:58
+#: src/components/Notification/notifications.ts:76
 msgid "Enable site %{name} on %{node} successfully"
 msgid "Enable site %{name} on %{node} successfully"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:112
+#: src/components/Notification/notifications.ts:130
 msgid "Enable stream %{name} on %{node} failed"
 msgid "Enable stream %{name} on %{node} failed"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:116
+#: src/components/Notification/notifications.ts:134
 msgid "Enable stream %{name} on %{node} successfully"
 msgid "Enable stream %{name} on %{node} successfully"
 msgstr ""
 msgstr ""
 
 
@@ -1174,6 +1200,11 @@ msgstr ""
 msgid "Export"
 msgid "Export"
 msgstr ""
 msgstr ""
 
 
+#: src/views/preference/ExternalNotify.vue:10
+#: src/views/preference/Preference.vue:169
+msgid "External Notify"
+msgstr ""
+
 #: src/views/site/cert/components/ObtainCertLive.vue:94
 #: src/views/site/cert/components/ObtainCertLive.vue:94
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
 msgstr ""
 msgstr ""
@@ -1533,7 +1564,7 @@ msgstr ""
 msgid "Host"
 msgid "Host"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/Preference.vue:174
+#: src/views/preference/Preference.vue:181
 msgid "HTTP"
 msgid "HTTP"
 msgstr ""
 msgstr ""
 
 
@@ -1583,12 +1614,12 @@ msgid "Import Certificate"
 msgstr ""
 msgstr ""
 
 
 #: src/views/nginx_log/NginxLogList.vue:137
 #: src/views/nginx_log/NginxLogList.vue:137
-#: src/views/site/site_list/SiteList.vue:128
+#: src/views/site/site_list/SiteList.vue:132
 msgid "Indexed"
 msgid "Indexed"
 msgstr ""
 msgstr ""
 
 
 #: src/views/nginx_log/NginxLogList.vue:134
 #: src/views/nginx_log/NginxLogList.vue:134
-#: src/views/site/site_list/SiteList.vue:125
+#: src/views/site/site_list/SiteList.vue:129
 msgid "Indexing..."
 msgid "Indexing..."
 msgstr ""
 msgstr ""
 
 
@@ -1668,6 +1699,10 @@ msgstr ""
 msgid "Invalid folder name"
 msgid "Invalid folder name"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/notification.ts:3
+msgid "Invalid notifier config"
+msgstr ""
+
 #: src/constants/errors/user.ts:4
 #: src/constants/errors/user.ts:4
 msgid "Invalid otp code"
 msgid "Invalid otp code"
 msgstr ""
 msgstr ""
@@ -1725,6 +1760,10 @@ msgstr ""
 msgid "Key Type"
 msgid "Key Type"
 msgstr ""
 msgstr ""
 
 
+#: src/views/preference/components/ExternalNotify/columns.ts:29
+msgid "Language"
+msgstr ""
+
 #: src/views/system/Upgrade.vue:179
 #: src/views/system/Upgrade.vue:179
 msgid "Last checked at"
 msgid "Last checked at"
 msgstr ""
 msgstr ""
@@ -1823,7 +1862,7 @@ msgstr ""
 msgid "Logout successful"
 msgid "Logout successful"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/Preference.vue:210
+#: src/views/preference/Preference.vue:217
 msgid "Logrotate"
 msgid "Logrotate"
 msgstr ""
 msgstr ""
 
 
@@ -1856,7 +1895,7 @@ msgid "Manage Configs"
 msgstr ""
 msgstr ""
 
 
 #: src/routes/modules/sites.ts:10
 #: src/routes/modules/sites.ts:10
-#: src/views/site/site_list/SiteList.vue:121
+#: src/views/site/site_list/SiteList.vue:125
 msgid "Manage Sites"
 msgid "Manage Sites"
 msgstr ""
 msgstr ""
 
 
@@ -1935,7 +1974,7 @@ msgstr ""
 #: src/views/nginx_log/NginxLogList.vue:37
 #: src/views/nginx_log/NginxLogList.vue:37
 #: src/views/preference/components/AddPasskey.vue:75
 #: src/views/preference/components/AddPasskey.vue:75
 #: src/views/site/ngx_conf/NgxUpstream.vue:177
 #: src/views/site/ngx_conf/NgxUpstream.vue:177
-#: src/views/site/site_edit/RightSettings.vue:64
+#: src/views/site/site_edit/RightSettings.vue:63
 #: src/views/site/site_list/columns.tsx:17
 #: src/views/site/site_list/columns.tsx:17
 #: src/views/site/site_list/SiteDuplicate.vue:79
 #: src/views/site/site_list/SiteDuplicate.vue:79
 #: src/views/stream/components/RightSettings.vue:87
 #: src/views/stream/components/RightSettings.vue:87
@@ -1983,7 +2022,7 @@ msgstr ""
 msgid "Next"
 msgid "Next"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/Preference.vue:198
+#: src/views/preference/Preference.vue:205
 msgid "Nginx"
 msgid "Nginx"
 msgstr ""
 msgstr ""
 
 
@@ -2115,7 +2154,7 @@ msgstr ""
 #: src/views/preference/CertSettings.vue:73
 #: src/views/preference/CertSettings.vue:73
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:97
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:97
 #: src/views/site/ngx_conf/LocationEditor.vue:88
 #: src/views/site/ngx_conf/LocationEditor.vue:88
-#: src/views/site/site_list/SiteList.vue:161
+#: src/views/site/site_list/SiteList.vue:165
 #: src/views/stream/StreamList.vue:225
 #: src/views/stream/StreamList.vue:225
 msgid "No"
 msgid "No"
 msgstr ""
 msgstr ""
@@ -2129,11 +2168,11 @@ msgstr ""
 msgid "No records selected"
 msgid "No records selected"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/Preference.vue:168
+#: src/views/preference/Preference.vue:175
 msgid "Node"
 msgid "Node"
 msgstr ""
 msgstr ""
 
 
-#: src/views/site/site_edit/RightSettings.vue:67
+#: src/views/site/site_edit/RightSettings.vue:66
 #: src/views/site/site_list/columns.tsx:63
 #: src/views/site/site_list/columns.tsx:63
 #: src/views/stream/components/RightSettings.vue:90
 #: src/views/stream/components/RightSettings.vue:90
 #: src/views/stream/StreamList.vue:30
 #: src/views/stream/StreamList.vue:30
@@ -2174,7 +2213,7 @@ msgstr ""
 msgid "Note"
 msgid "Note"
 msgstr ""
 msgstr ""
 
 
-#: src/views/site/site_edit/RightSettings.vue:96
+#: src/views/site/site_edit/RightSettings.vue:95
 #: src/views/stream/components/RightSettings.vue:118
 #: src/views/stream/components/RightSettings.vue:118
 msgid "Note, if the configuration file include other configurations or certificates, please synchronize them to the remote nodes in advance."
 msgid "Note, if the configuration file include other configurations or certificates, please synchronize them to the remote nodes in advance."
 msgstr ""
 msgstr ""
@@ -2188,6 +2227,10 @@ msgstr ""
 msgid "Notifications"
 msgid "Notifications"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/notification.ts:2
+msgid "Notifier not found"
+msgstr ""
+
 #: src/views/site/cert/components/ObtainCert.vue:182
 #: src/views/site/cert/components/ObtainCert.vue:182
 msgid "Obtain certificate"
 msgid "Obtain certificate"
 msgstr ""
 msgstr ""
@@ -2228,7 +2271,7 @@ msgstr ""
 #: src/views/site/ngx_conf/NgxServer.vue:79
 #: src/views/site/ngx_conf/NgxServer.vue:79
 #: src/views/site/ngx_conf/NgxUpstream.vue:33
 #: src/views/site/ngx_conf/NgxUpstream.vue:33
 #: src/views/site/site_edit/components/SiteStatusSegmented.vue:121
 #: src/views/site/site_edit/components/SiteStatusSegmented.vue:121
-#: src/views/site/site_list/SiteList.vue:162
+#: src/views/site/site_list/SiteList.vue:166
 #: src/views/stream/components/RightSettings.vue:54
 #: src/views/stream/components/RightSettings.vue:54
 #: src/views/stream/StreamList.vue:226
 #: src/views/stream/StreamList.vue:226
 #: src/views/system/Backup/BackupCreator.vue:149
 #: src/views/system/Backup/BackupCreator.vue:149
@@ -2251,7 +2294,7 @@ msgstr ""
 msgid "Only zip files are allowed"
 msgid "Only zip files are allowed"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/Preference.vue:204
+#: src/views/preference/Preference.vue:211
 msgid "OpenAI"
 msgid "OpenAI"
 msgstr ""
 msgstr ""
 
 
@@ -2382,7 +2425,7 @@ msgstr ""
 msgid "Please first add credentials in Certification > DNS Credentials, and then select one of the credentialsbelow to request the API of the DNS provider."
 msgid "Please first add credentials in Certification > DNS Credentials, and then select one of the credentialsbelow to request the API of the DNS provider."
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:138
+#: src/components/Notification/notifications.ts:156
 #: src/language/constants.ts:59
 #: src/language/constants.ts:59
 msgid "Please generate new recovery codes in the preferences immediately to prevent lockout."
 msgid "Please generate new recovery codes in the preferences immediately to prevent lockout."
 msgstr ""
 msgstr ""
@@ -2466,7 +2509,7 @@ msgid "Pre-release"
 msgstr ""
 msgstr ""
 
 
 #: src/routes/modules/preference.ts:10
 #: src/routes/modules/preference.ts:10
-#: src/views/preference/Preference.vue:151
+#: src/views/preference/Preference.vue:152
 msgid "Preference"
 msgid "Preference"
 msgstr ""
 msgstr ""
 
 
@@ -2594,19 +2637,19 @@ msgstr ""
 msgid "Reload Nginx"
 msgid "Reload Nginx"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:144
+#: src/components/Notification/notifications.ts:10
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:148
+#: src/components/Notification/notifications.ts:14
 msgid "Reload Nginx on %{node} successfully"
 msgid "Reload Nginx on %{node} successfully"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:143
+#: src/components/Notification/notifications.ts:9
 msgid "Reload Remote Nginx Error"
 msgid "Reload Remote Nginx Error"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:147
+#: src/components/Notification/notifications.ts:13
 msgid "Reload Remote Nginx Success"
 msgid "Reload Remote Nginx Success"
 msgstr ""
 msgstr ""
 
 
@@ -2644,55 +2687,55 @@ msgstr ""
 msgid "Rename"
 msgid "Rename"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:28
+#: src/components/Notification/notifications.ts:46
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} failed"
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} failed"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:32
+#: src/components/Notification/notifications.ts:50
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} successfully"
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} successfully"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:27
+#: src/components/Notification/notifications.ts:45
 #: src/language/constants.ts:42
 #: src/language/constants.ts:42
 msgid "Rename Remote Config Error"
 msgid "Rename Remote Config Error"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:31
+#: src/components/Notification/notifications.ts:49
 #: src/language/constants.ts:41
 #: src/language/constants.ts:41
 msgid "Rename Remote Config Success"
 msgid "Rename Remote Config Success"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:77
+#: src/components/Notification/notifications.ts:95
 #: src/language/constants.ts:56
 #: src/language/constants.ts:56
 msgid "Rename Remote Site Error"
 msgid "Rename Remote Site Error"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:81
+#: src/components/Notification/notifications.ts:99
 #: src/language/constants.ts:55
 #: src/language/constants.ts:55
 msgid "Rename Remote Site Success"
 msgid "Rename Remote Site Success"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:119
+#: src/components/Notification/notifications.ts:137
 msgid "Rename Remote Stream Error"
 msgid "Rename Remote Stream Error"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:123
+#: src/components/Notification/notifications.ts:141
 msgid "Rename Remote Stream Success"
 msgid "Rename Remote Stream Success"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:78
+#: src/components/Notification/notifications.ts:96
 msgid "Rename site %{name} to %{new_name} on %{node} failed"
 msgid "Rename site %{name} to %{new_name} on %{node} failed"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:82
+#: src/components/Notification/notifications.ts:100
 msgid "Rename site %{name} to %{new_name} on %{node} successfully"
 msgid "Rename site %{name} to %{new_name} on %{node} successfully"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:120
+#: src/components/Notification/notifications.ts:138
 msgid "Rename stream %{name} to %{new_name} on %{node} failed"
 msgid "Rename stream %{name} to %{new_name} on %{node} failed"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:124
+#: src/components/Notification/notifications.ts:142
 msgid "Rename stream %{name} to %{new_name} on %{node} successfully"
 msgid "Rename stream %{name} to %{new_name} on %{node} successfully"
 msgstr ""
 msgstr ""
 
 
@@ -2750,19 +2793,19 @@ msgstr ""
 msgid "Restart Nginx"
 msgid "Restart Nginx"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:152
+#: src/components/Notification/notifications.ts:18
 msgid "Restart Nginx on %{node} failed, response: %{resp}"
 msgid "Restart Nginx on %{node} failed, response: %{resp}"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:156
+#: src/components/Notification/notifications.ts:22
 msgid "Restart Nginx on %{node} successfully"
 msgid "Restart Nginx on %{node} successfully"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:151
+#: src/components/Notification/notifications.ts:17
 msgid "Restart Remote Nginx Error"
 msgid "Restart Remote Nginx Error"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:155
+#: src/components/Notification/notifications.ts:21
 msgid "Restart Remote Nginx Success"
 msgid "Restart Remote Nginx Success"
 msgstr ""
 msgstr ""
 
 
@@ -2824,7 +2867,7 @@ msgstr ""
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/ConfigEditor.vue:271
 #: src/views/config/ConfigEditor.vue:271
 #: src/views/preference/components/Passkey.vue:130
 #: src/views/preference/components/Passkey.vue:130
-#: src/views/preference/Preference.vue:221
+#: src/views/preference/Preference.vue:228
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:127
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:127
 #: src/views/site/site_edit/components/ConfigName.vue:52
 #: src/views/site/site_edit/components/ConfigName.vue:52
 #: src/views/site/site_edit/SiteEdit.vue:292
 #: src/views/site/site_edit/SiteEdit.vue:292
@@ -2842,44 +2885,44 @@ msgstr ""
 msgid "Save error %{msg}"
 msgid "Save error %{msg}"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:85
+#: src/components/Notification/notifications.ts:103
 #: src/language/constants.ts:48
 #: src/language/constants.ts:48
 msgid "Save Remote Site Error"
 msgid "Save Remote Site Error"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:89
+#: src/components/Notification/notifications.ts:107
 #: src/language/constants.ts:47
 #: src/language/constants.ts:47
 msgid "Save Remote Site Success"
 msgid "Save Remote Site Success"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:127
+#: src/components/Notification/notifications.ts:145
 msgid "Save Remote Stream Error"
 msgid "Save Remote Stream Error"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:131
+#: src/components/Notification/notifications.ts:149
 msgid "Save Remote Stream Success"
 msgid "Save Remote Stream Success"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:86
+#: src/components/Notification/notifications.ts:104
 msgid "Save site %{name} to %{node} failed"
 msgid "Save site %{name} to %{node} failed"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:90
+#: src/components/Notification/notifications.ts:108
 msgid "Save site %{name} to %{node} successfully"
 msgid "Save site %{name} to %{node} successfully"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:128
+#: src/components/Notification/notifications.ts:146
 msgid "Save stream %{name} to %{node} failed"
 msgid "Save stream %{name} to %{node} failed"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:132
+#: src/components/Notification/notifications.ts:150
 msgid "Save stream %{name} to %{node} successfully"
 msgid "Save stream %{name} to %{node} successfully"
 msgstr ""
 msgstr ""
 
 
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:47
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:47
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:97
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:97
 #: src/views/certificate/CertificateEditor.vue:49
 #: src/views/certificate/CertificateEditor.vue:49
-#: src/views/preference/Preference.vue:123
+#: src/views/preference/Preference.vue:124
 msgid "Save successfully"
 msgid "Save successfully"
 msgstr ""
 msgstr ""
 
 
@@ -2899,6 +2942,10 @@ msgstr ""
 msgid "SDK"
 msgid "SDK"
 msgstr ""
 msgstr ""
 
 
+#: src/views/preference/components/ExternalNotify/dingtalk.ts:13
+msgid "Secret (Optional)"
+msgstr ""
+
 #: src/views/preference/components/TOTP.vue:109
 #: src/views/preference/components/TOTP.vue:109
 msgid "Secret has been copied"
 msgid "Secret has been copied"
 msgstr ""
 msgstr ""
@@ -2930,7 +2977,7 @@ msgstr ""
 msgid "Send"
 msgid "Send"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/Preference.vue:156
+#: src/views/preference/Preference.vue:157
 msgid "Server"
 msgid "Server"
 msgstr ""
 msgstr ""
 
 
@@ -2938,6 +2985,10 @@ msgstr ""
 msgid "Server Info"
 msgid "Server Info"
 msgstr ""
 msgstr ""
 
 
+#: src/views/preference/components/ExternalNotify/bark.ts:13
+msgid "Server URL"
+msgstr ""
+
 #: src/views/site/cert/components/ObtainCert.vue:107
 #: src/views/site/cert/components/ObtainCert.vue:107
 msgid "server_name not found in directives"
 msgid "server_name not found in directives"
 msgstr ""
 msgstr ""
@@ -3094,7 +3145,7 @@ msgstr ""
 #: src/views/certificate/ACMEUser.vue:65
 #: src/views/certificate/ACMEUser.vue:65
 #: src/views/certificate/CertificateList/certColumns.tsx:65
 #: src/views/certificate/CertificateList/certColumns.tsx:65
 #: src/views/environments/list/envColumns.tsx:44
 #: src/views/environments/list/envColumns.tsx:44
-#: src/views/site/site_edit/RightSettings.vue:56
+#: src/views/site/site_edit/RightSettings.vue:55
 #: src/views/site/site_list/columns.tsx:80
 #: src/views/site/site_list/columns.tsx:80
 #: src/views/stream/StreamList.vue:47
 #: src/views/stream/StreamList.vue:47
 msgid "Status"
 msgid "Status"
@@ -3164,38 +3215,38 @@ msgstr ""
 msgid "Sync Certificate"
 msgid "Sync Certificate"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:10
+#: src/components/Notification/notifications.ts:28
 msgid "Sync Certificate %{cert_name} to %{env_name} failed"
 msgid "Sync Certificate %{cert_name} to %{env_name} failed"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:14
+#: src/components/Notification/notifications.ts:32
 msgid "Sync Certificate %{cert_name} to %{env_name} successfully"
 msgid "Sync Certificate %{cert_name} to %{env_name} successfully"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:9
+#: src/components/Notification/notifications.ts:27
 #: src/language/constants.ts:39
 #: src/language/constants.ts:39
 msgid "Sync Certificate Error"
 msgid "Sync Certificate Error"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:13
+#: src/components/Notification/notifications.ts:31
 #: src/language/constants.ts:38
 #: src/language/constants.ts:38
 msgid "Sync Certificate Success"
 msgid "Sync Certificate Success"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:20
+#: src/components/Notification/notifications.ts:38
 msgid "Sync config %{config_name} to %{env_name} failed"
 msgid "Sync config %{config_name} to %{env_name} failed"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:24
+#: src/components/Notification/notifications.ts:42
 msgid "Sync config %{config_name} to %{env_name} successfully"
 msgid "Sync config %{config_name} to %{env_name} successfully"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:19
+#: src/components/Notification/notifications.ts:37
 #: src/language/constants.ts:45
 #: src/language/constants.ts:45
 msgid "Sync Config Error"
 msgid "Sync Config Error"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:23
+#: src/components/Notification/notifications.ts:41
 #: src/language/constants.ts:44
 #: src/language/constants.ts:44
 msgid "Sync Config Success"
 msgid "Sync Config Success"
 msgstr ""
 msgstr ""
@@ -3205,8 +3256,8 @@ msgstr ""
 msgid "Sync Nodes"
 msgid "Sync Nodes"
 msgstr ""
 msgstr ""
 
 
-#: src/views/site/site_edit/RightSettings.vue:102
-#: src/views/site/site_edit/RightSettings.vue:89
+#: src/views/site/site_edit/RightSettings.vue:101
+#: src/views/site/site_edit/RightSettings.vue:88
 #: src/views/stream/components/RightSettings.vue:111
 #: src/views/stream/components/RightSettings.vue:111
 #: src/views/stream/components/RightSettings.vue:124
 #: src/views/stream/components/RightSettings.vue:124
 msgid "Sync strategy"
 msgid "Sync strategy"
@@ -3216,7 +3267,7 @@ msgstr ""
 msgid "Sync to"
 msgid "Sync to"
 msgstr ""
 msgstr ""
 
 
-#: src/views/site/site_edit/RightSettings.vue:86
+#: src/views/site/site_edit/RightSettings.vue:85
 #: src/views/stream/components/RightSettings.vue:108
 #: src/views/stream/components/RightSettings.vue:108
 msgid "Synchronization"
 msgid "Synchronization"
 msgstr ""
 msgstr ""
@@ -3246,8 +3297,12 @@ msgstr ""
 msgid "Task not found"
 msgid "Task not found"
 msgstr ""
 msgstr ""
 
 
+#: src/views/preference/components/ExternalNotify/telegram.ts:5
+msgid "Telegram"
+msgstr ""
+
 #: src/routes/modules/terminal.ts:10
 #: src/routes/modules/terminal.ts:10
-#: src/views/preference/Preference.vue:180
+#: src/views/preference/Preference.vue:187
 #: src/views/terminal/Terminal.vue:129
 #: src/views/terminal/Terminal.vue:129
 msgid "Terminal"
 msgid "Terminal"
 msgstr ""
 msgstr ""
@@ -3442,6 +3497,7 @@ msgstr ""
 #: src/views/certificate/CertificateList/certColumns.tsx:25
 #: src/views/certificate/CertificateList/certColumns.tsx:25
 #: src/views/nginx_log/NginxLogList.vue:21
 #: src/views/nginx_log/NginxLogList.vue:21
 #: src/views/notification/notificationColumns.tsx:9
 #: src/views/notification/notificationColumns.tsx:9
+#: src/views/preference/components/ExternalNotify/columns.ts:17
 msgid "Type"
 msgid "Type"
 msgstr ""
 msgstr ""
 
 
@@ -3459,7 +3515,7 @@ msgstr ""
 #: src/views/config/ConfigEditor.vue:325
 #: src/views/config/ConfigEditor.vue:325
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/environments/list/envColumns.tsx:90
-#: src/views/site/site_edit/RightSettings.vue:76
+#: src/views/site/site_edit/RightSettings.vue:75
 #: src/views/site/site_list/columns.tsx:110
 #: src/views/site/site_list/columns.tsx:110
 #: src/views/stream/components/RightSettings.vue:99
 #: src/views/stream/components/RightSettings.vue:99
 #: src/views/stream/StreamList.vue:67
 #: src/views/stream/StreamList.vue:67
@@ -3608,7 +3664,7 @@ msgstr ""
 msgid "When Enabled, Nginx UI will automatically re-register users upon startup. Generally, do not enable this unless you are in a dev environment and using Pebble as CA."
 msgid "When Enabled, Nginx UI will automatically re-register users upon startup. Generally, do not enable this unless you are in a dev environment and using Pebble as CA."
 msgstr ""
 msgstr ""
 
 
-#: src/views/site/site_edit/RightSettings.vue:92
+#: src/views/site/site_edit/RightSettings.vue:91
 msgid "When you enable/disable, delete, or save this site, the nodes set in the Node Group and the nodes selected below will be synchronized."
 msgid "When you enable/disable, delete, or save this site, the nodes set in the Node Group and the nodes selected below will be synchronized."
 msgstr ""
 msgstr ""
 
 

+ 165 - 102
app/src/language/ru_RU/app.po

@@ -37,6 +37,11 @@ msgstr "Журналы доступа"
 msgid "Access Logs"
 msgid "Access Logs"
 msgstr "Журналы доступа"
 msgstr "Журналы доступа"
 
 
+#: src/views/preference/components/ExternalNotify/dingtalk.ts:9
+#, fuzzy
+msgid "Access Token"
+msgstr "Журналы доступа"
+
 #: src/routes/modules/certificates.ts:20 src/views/certificate/ACMEUser.vue:113
 #: src/routes/modules/certificates.ts:20 src/views/certificate/ACMEUser.vue:113
 #: src/views/certificate/ACMEUserSelector.vue:85
 #: src/views/certificate/ACMEUserSelector.vue:85
 msgid "ACME User"
 msgid "ACME User"
@@ -51,6 +56,7 @@ msgstr "Пользователь ACME"
 #: src/views/nginx_log/NginxLogList.vue:53
 #: src/views/nginx_log/NginxLogList.vue:53
 #: src/views/notification/notificationColumns.tsx:66
 #: src/views/notification/notificationColumns.tsx:66
 #: src/views/preference/AuthSettings.vue:30
 #: src/views/preference/AuthSettings.vue:30
+#: src/views/preference/components/ExternalNotify/columns.ts:46
 #: src/views/site/site_list/columns.tsx:117 src/views/stream/StreamList.vue:74
 #: src/views/site/site_list/columns.tsx:117 src/views/stream/StreamList.vue:74
 #: src/views/user/userColumns.tsx:60
 #: src/views/user/userColumns.tsx:60
 msgid "Action"
 msgid "Action"
@@ -115,7 +121,7 @@ msgstr "Затем, обновите эту страницу и снова на
 msgid "All"
 msgid "All"
 msgstr "Все"
 msgstr "Все"
 
 
-#: src/components/Notification/notifications.ts:137
+#: src/components/Notification/notifications.ts:155
 #: src/language/constants.ts:58
 #: src/language/constants.ts:58
 msgid "All Recovery Codes Have Been Used"
 msgid "All Recovery Codes Have Been Used"
 msgstr "Все коды восстановления были использованы"
 msgstr "Все коды восстановления были использованы"
@@ -140,7 +146,7 @@ msgstr "API токен"
 msgid "API Type"
 msgid "API Type"
 msgstr "Тип API"
 msgstr "Тип API"
 
 
-#: src/views/preference/Preference.vue:162
+#: src/views/preference/Preference.vue:163
 #, fuzzy
 #, fuzzy
 msgid "App"
 msgid "App"
 msgstr "Применить"
 msgstr "Применить"
@@ -195,7 +201,7 @@ msgstr "Вы уверены, что хотите удалить этот эле
 msgid "Are you sure you want to delete this item?"
 msgid "Are you sure you want to delete this item?"
 msgstr "Вы уверены, что хотите удалить этот элемент?"
 msgstr "Вы уверены, что хотите удалить этот элемент?"
 
 
-#: src/views/site/site_list/SiteList.vue:163
+#: src/views/site/site_list/SiteList.vue:167
 #: src/views/stream/StreamList.vue:227
 #: src/views/stream/StreamList.vue:227
 msgid "Are you sure you want to delete?"
 msgid "Are you sure you want to delete?"
 msgstr "Вы уверены, что хотите удалить?"
 msgstr "Вы уверены, что хотите удалить?"
@@ -242,7 +248,7 @@ msgstr "Попытка исправить"
 msgid "Attempts"
 msgid "Attempts"
 msgstr "Попытки"
 msgstr "Попытки"
 
 
-#: src/views/preference/Preference.vue:186
+#: src/views/preference/Preference.vue:193
 msgid "Auth"
 msgid "Auth"
 msgstr "Авторизация"
 msgstr "Авторизация"
 
 
@@ -326,12 +332,16 @@ msgstr "Заблокированные IP-адреса"
 msgid "Banned Until"
 msgid "Banned Until"
 msgstr "Заблокирован до"
 msgstr "Заблокирован до"
 
 
+#: src/views/preference/components/ExternalNotify/bark.ts:5
+msgid "Bark"
+msgstr ""
+
 #: src/views/site/site_add/SiteAdd.vue:95
 #: src/views/site/site_add/SiteAdd.vue:95
 msgid "Base information"
 msgid "Base information"
 msgstr "Основная информация"
 msgstr "Основная информация"
 
 
 #: src/views/config/ConfigEditor.vue:290
 #: src/views/config/ConfigEditor.vue:290
-#: src/views/site/site_edit/RightSettings.vue:53
+#: src/views/site/site_edit/RightSettings.vue:52
 #: src/views/stream/components/RightSettings.vue:79
 #: src/views/stream/components/RightSettings.vue:79
 msgid "Basic"
 msgid "Basic"
 msgstr "Основные"
 msgstr "Основные"
@@ -363,6 +373,11 @@ msgstr "Ниже приведены выбранные элементы, кот
 msgid "Block is nil"
 msgid "Block is nil"
 msgstr ""
 msgstr ""
 
 
+#: src/views/preference/components/ExternalNotify/telegram.ts:9
+#, fuzzy
+msgid "Bot Token"
+msgstr "API токен"
+
 #: src/views/system/About.vue:55
 #: src/views/system/About.vue:55
 msgid "Build with"
 msgid "Build with"
 msgstr "Собрать с"
 msgstr "Собрать с"
@@ -402,7 +417,7 @@ msgstr ""
 msgid "Cannot remove initial user"
 msgid "Cannot remove initial user"
 msgstr "Невозможно удалить начального пользователя"
 msgstr "Невозможно удалить начального пользователя"
 
 
-#: src/views/preference/Preference.vue:192
+#: src/views/preference/Preference.vue:199
 #, fuzzy
 #, fuzzy
 msgid "Cert"
 msgid "Cert"
 msgstr "Авто Сертификат"
 msgstr "Авто Сертификат"
@@ -472,6 +487,10 @@ msgstr "Путь изменён"
 msgid "Channel"
 msgid "Channel"
 msgstr "Канал"
 msgstr "Канал"
 
 
+#: src/views/preference/components/ExternalNotify/telegram.ts:13
+msgid "Chat ID"
+msgstr ""
+
 #: src/views/system/Upgrade.vue:185
 #: src/views/system/Upgrade.vue:185
 msgid "Check again"
 msgid "Check again"
 msgstr "Проверить повторно"
 msgstr "Проверить повторно"
@@ -667,6 +686,7 @@ msgstr ""
 
 
 #: src/views/environments/group/columns.ts:31
 #: src/views/environments/group/columns.ts:31
 #: src/views/notification/notificationColumns.tsx:59
 #: src/views/notification/notificationColumns.tsx:59
+#: src/views/preference/components/ExternalNotify/columns.ts:41
 #: src/views/preference/components/Passkey.vue:95
 #: src/views/preference/components/Passkey.vue:95
 #: src/views/user/userColumns.tsx:48
 #: src/views/user/userColumns.tsx:48
 msgid "Created at"
 msgid "Created at"
@@ -738,7 +758,7 @@ msgstr "Ошибка расшифровки"
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/views/site/ngx_conf/NgxServer.vue:110
 #: src/views/site/ngx_conf/NgxServer.vue:110
 #: src/views/site/ngx_conf/NgxUpstream.vue:128
 #: src/views/site/ngx_conf/NgxUpstream.vue:128
-#: src/views/site/site_list/SiteList.vue:172
+#: src/views/site/site_list/SiteList.vue:176
 #: src/views/stream/StreamList.vue:236
 #: src/views/stream/StreamList.vue:236
 msgid "Delete"
 msgid "Delete"
 msgstr "Удалить"
 msgstr "Удалить"
@@ -748,45 +768,45 @@ msgstr "Удалить"
 msgid "Delete Permanently"
 msgid "Delete Permanently"
 msgstr "Удалить навсегда"
 msgstr "Удалить навсегда"
 
 
-#: src/components/Notification/notifications.ts:37 src/language/constants.ts:50
+#: src/components/Notification/notifications.ts:55 src/language/constants.ts:50
 #, fuzzy
 #, fuzzy
 msgid "Delete Remote Site Error"
 msgid "Delete Remote Site Error"
 msgstr "Ошибка переименования удаленной конфигурации"
 msgstr "Ошибка переименования удаленной конфигурации"
 
 
-#: src/components/Notification/notifications.ts:41 src/language/constants.ts:49
+#: src/components/Notification/notifications.ts:59 src/language/constants.ts:49
 #, fuzzy
 #, fuzzy
 msgid "Delete Remote Site Success"
 msgid "Delete Remote Site Success"
 msgstr "Переименование удаленной конфигурации прошло успешно"
 msgstr "Переименование удаленной конфигурации прошло успешно"
 
 
-#: src/components/Notification/notifications.ts:95
+#: src/components/Notification/notifications.ts:113
 #, fuzzy
 #, fuzzy
 msgid "Delete Remote Stream Error"
 msgid "Delete Remote Stream Error"
 msgstr "Ошибка переименования удаленной конфигурации"
 msgstr "Ошибка переименования удаленной конфигурации"
 
 
-#: src/components/Notification/notifications.ts:99
+#: src/components/Notification/notifications.ts:117
 #, fuzzy
 #, fuzzy
 msgid "Delete Remote Stream Success"
 msgid "Delete Remote Stream Success"
 msgstr "Переименование удаленной конфигурации прошло успешно"
 msgstr "Переименование удаленной конфигурации прошло успешно"
 
 
-#: src/components/Notification/notifications.ts:38
+#: src/components/Notification/notifications.ts:56
 #, fuzzy
 #, fuzzy
 msgid "Delete site %{name} from %{node} failed"
 msgid "Delete site %{name} from %{node} failed"
 msgstr "Не удалось развернуть %{conf_name} на %{node_name}"
 msgstr "Не удалось развернуть %{conf_name} на %{node_name}"
 
 
-#: src/components/Notification/notifications.ts:42
+#: src/components/Notification/notifications.ts:60
 msgid "Delete site %{name} from %{node} successfully"
 msgid "Delete site %{name} from %{node} successfully"
 msgstr "Сайт %{name} успешно удалён с %{node}"
 msgstr "Сайт %{name} успешно удалён с %{node}"
 
 
-#: src/views/site/site_list/SiteList.vue:94
+#: src/views/site/site_list/SiteList.vue:98
 msgid "Delete site: %{site_name}"
 msgid "Delete site: %{site_name}"
 msgstr "Удалить сайт: %{site_name}"
 msgstr "Удалить сайт: %{site_name}"
 
 
-#: src/components/Notification/notifications.ts:96
+#: src/components/Notification/notifications.ts:114
 #, fuzzy
 #, fuzzy
 msgid "Delete stream %{name} from %{node} failed"
 msgid "Delete stream %{name} from %{node} failed"
 msgstr "Не удалось развернуть %{conf_name} на %{node_name}"
 msgstr "Не удалось развернуть %{conf_name} на %{node_name}"
 
 
-#: src/components/Notification/notifications.ts:100
+#: src/components/Notification/notifications.ts:118
 msgid "Delete stream %{name} from %{node} successfully"
 msgid "Delete stream %{name} from %{node} successfully"
 msgstr "Поток %{name} успешно удалён с %{node}"
 msgstr "Поток %{name} успешно удалён с %{node}"
 
 
@@ -823,6 +843,14 @@ msgstr "Детали"
 msgid "Development Mode"
 msgid "Development Mode"
 msgstr "Режим разработки"
 msgstr "Режим разработки"
 
 
+#: src/views/preference/components/ExternalNotify/bark.ts:9
+msgid "Device Key"
+msgstr ""
+
+#: src/views/preference/components/ExternalNotify/dingtalk.ts:5
+msgid "DingTalk"
+msgstr ""
+
 #: src/views/site/ngx_conf/directive/DirectiveAdd.vue:89
 #: src/views/site/ngx_conf/directive/DirectiveAdd.vue:89
 msgid "Directive"
 msgid "Directive"
 msgstr "Директива"
 msgstr "Директива"
@@ -856,62 +884,62 @@ msgstr "Отключить"
 msgid "Disable auto-renewal failed for %{name}"
 msgid "Disable auto-renewal failed for %{name}"
 msgstr "Не удалось отключить автоматическое продление для %{name}"
 msgstr "Не удалось отключить автоматическое продление для %{name}"
 
 
-#: src/components/Notification/notifications.ts:45 src/language/constants.ts:52
+#: src/components/Notification/notifications.ts:63 src/language/constants.ts:52
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Site Error"
 msgid "Disable Remote Site Error"
 msgstr "Ошибка переименования удаленной конфигурации"
 msgstr "Ошибка переименования удаленной конфигурации"
 
 
-#: src/components/Notification/notifications.ts:69
+#: src/components/Notification/notifications.ts:87
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Site Maintenance Error"
 msgid "Disable Remote Site Maintenance Error"
 msgstr "Ошибка переименования удаленной конфигурации"
 msgstr "Ошибка переименования удаленной конфигурации"
 
 
-#: src/components/Notification/notifications.ts:73
+#: src/components/Notification/notifications.ts:91
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Site Maintenance Success"
 msgid "Disable Remote Site Maintenance Success"
 msgstr "Переименование удаленной конфигурации прошло успешно"
 msgstr "Переименование удаленной конфигурации прошло успешно"
 
 
-#: src/components/Notification/notifications.ts:49 src/language/constants.ts:51
+#: src/components/Notification/notifications.ts:67 src/language/constants.ts:51
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Site Success"
 msgid "Disable Remote Site Success"
 msgstr "Переименование удаленной конфигурации прошло успешно"
 msgstr "Переименование удаленной конфигурации прошло успешно"
 
 
-#: src/components/Notification/notifications.ts:103
+#: src/components/Notification/notifications.ts:121
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Stream Error"
 msgid "Disable Remote Stream Error"
 msgstr "Ошибка переименования удаленной конфигурации"
 msgstr "Ошибка переименования удаленной конфигурации"
 
 
-#: src/components/Notification/notifications.ts:107
+#: src/components/Notification/notifications.ts:125
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Stream Success"
 msgid "Disable Remote Stream Success"
 msgstr "Переименование удаленной конфигурации прошло успешно"
 msgstr "Переименование удаленной конфигурации прошло успешно"
 
 
-#: src/components/Notification/notifications.ts:46
+#: src/components/Notification/notifications.ts:64
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} from %{node} failed"
 msgid "Disable site %{name} from %{node} failed"
 msgstr "Включение %{conf_name} in %{node_name} успешно"
 msgstr "Включение %{conf_name} in %{node_name} успешно"
 
 
-#: src/components/Notification/notifications.ts:50
+#: src/components/Notification/notifications.ts:68
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} from %{node} successfully"
 msgid "Disable site %{name} from %{node} successfully"
 msgstr "Включение %{conf_name} in %{node_name} успешно"
 msgstr "Включение %{conf_name} in %{node_name} успешно"
 
 
-#: src/components/Notification/notifications.ts:70
+#: src/components/Notification/notifications.ts:88
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} maintenance on %{node} failed"
 msgid "Disable site %{name} maintenance on %{node} failed"
 msgstr "Включение %{conf_name} in %{node_name} успешно"
 msgstr "Включение %{conf_name} in %{node_name} успешно"
 
 
-#: src/components/Notification/notifications.ts:74
+#: src/components/Notification/notifications.ts:92
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} maintenance on %{node} successfully"
 msgid "Disable site %{name} maintenance on %{node} successfully"
 msgstr "Включение %{conf_name} in %{node_name} успешно"
 msgstr "Включение %{conf_name} in %{node_name} успешно"
 
 
-#: src/components/Notification/notifications.ts:104
+#: src/components/Notification/notifications.ts:122
 #, fuzzy
 #, fuzzy
 msgid "Disable stream %{name} from %{node} failed"
 msgid "Disable stream %{name} from %{node} failed"
 msgstr "Включение %{conf_name} in %{node_name} нипалучилася"
 msgstr "Включение %{conf_name} in %{node_name} нипалучилася"
 
 
-#: src/components/Notification/notifications.ts:108
+#: src/components/Notification/notifications.ts:126
 #, fuzzy
 #, fuzzy
 msgid "Disable stream %{name} from %{node} successfully"
 msgid "Disable stream %{name} from %{node} successfully"
 msgstr "Включение %{conf_name} in %{node_name} успешно"
 msgstr "Включение %{conf_name} in %{node_name} успешно"
@@ -1026,7 +1054,7 @@ msgstr ""
 "запускаются на localhost."
 "запускаются на localhost."
 
 
 #: src/views/site/site_list/SiteDuplicate.vue:72
 #: src/views/site/site_list/SiteDuplicate.vue:72
-#: src/views/site/site_list/SiteList.vue:158
+#: src/views/site/site_list/SiteList.vue:162
 #: src/views/stream/components/StreamDuplicate.vue:64
 #: src/views/stream/components/StreamDuplicate.vue:64
 #: src/views/stream/StreamList.vue:222
 #: src/views/stream/StreamList.vue:222
 msgid "Duplicate"
 msgid "Duplicate"
@@ -1094,61 +1122,61 @@ msgstr "Не удалось включить"
 msgid "Enable HTTPS"
 msgid "Enable HTTPS"
 msgstr "Включить TOTP"
 msgstr "Включить TOTP"
 
 
-#: src/components/Notification/notifications.ts:53 src/language/constants.ts:54
+#: src/components/Notification/notifications.ts:71 src/language/constants.ts:54
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Site Error"
 msgid "Enable Remote Site Error"
 msgstr "Ошибка переименования удаленной конфигурации"
 msgstr "Ошибка переименования удаленной конфигурации"
 
 
-#: src/components/Notification/notifications.ts:61
+#: src/components/Notification/notifications.ts:79
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Site Maintenance Error"
 msgid "Enable Remote Site Maintenance Error"
 msgstr "Ошибка переименования удаленной конфигурации"
 msgstr "Ошибка переименования удаленной конфигурации"
 
 
-#: src/components/Notification/notifications.ts:65
+#: src/components/Notification/notifications.ts:83
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Site Maintenance Success"
 msgid "Enable Remote Site Maintenance Success"
 msgstr "Переименование удаленной конфигурации прошло успешно"
 msgstr "Переименование удаленной конфигурации прошло успешно"
 
 
-#: src/components/Notification/notifications.ts:57 src/language/constants.ts:53
+#: src/components/Notification/notifications.ts:75 src/language/constants.ts:53
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Site Success"
 msgid "Enable Remote Site Success"
 msgstr "Переименование удаленной конфигурации прошло успешно"
 msgstr "Переименование удаленной конфигурации прошло успешно"
 
 
-#: src/components/Notification/notifications.ts:111
+#: src/components/Notification/notifications.ts:129
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Stream Error"
 msgid "Enable Remote Stream Error"
 msgstr "Ошибка переименования удаленной конфигурации"
 msgstr "Ошибка переименования удаленной конфигурации"
 
 
-#: src/components/Notification/notifications.ts:115
+#: src/components/Notification/notifications.ts:133
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Stream Success"
 msgid "Enable Remote Stream Success"
 msgstr "Переименование удаленной конфигурации прошло успешно"
 msgstr "Переименование удаленной конфигурации прошло успешно"
 
 
-#: src/components/Notification/notifications.ts:62
+#: src/components/Notification/notifications.ts:80
 #, fuzzy
 #, fuzzy
 msgid "Enable site %{name} maintenance on %{node} failed"
 msgid "Enable site %{name} maintenance on %{node} failed"
 msgstr "Включение %{conf_name} in %{node_name} нипалучилася"
 msgstr "Включение %{conf_name} in %{node_name} нипалучилася"
 
 
-#: src/components/Notification/notifications.ts:66
+#: src/components/Notification/notifications.ts:84
 #, fuzzy
 #, fuzzy
 msgid "Enable site %{name} maintenance on %{node} successfully"
 msgid "Enable site %{name} maintenance on %{node} successfully"
 msgstr "Сайт %{name} успешно включён на %{node}"
 msgstr "Сайт %{name} успешно включён на %{node}"
 
 
-#: src/components/Notification/notifications.ts:54
+#: src/components/Notification/notifications.ts:72
 #, fuzzy
 #, fuzzy
 msgid "Enable site %{name} on %{node} failed"
 msgid "Enable site %{name} on %{node} failed"
 msgstr "Включение %{conf_name} in %{node_name} нипалучилася"
 msgstr "Включение %{conf_name} in %{node_name} нипалучилася"
 
 
-#: src/components/Notification/notifications.ts:58
+#: src/components/Notification/notifications.ts:76
 msgid "Enable site %{name} on %{node} successfully"
 msgid "Enable site %{name} on %{node} successfully"
 msgstr "Сайт %{name} успешно включён на %{node}"
 msgstr "Сайт %{name} успешно включён на %{node}"
 
 
-#: src/components/Notification/notifications.ts:112
+#: src/components/Notification/notifications.ts:130
 #, fuzzy
 #, fuzzy
 msgid "Enable stream %{name} on %{node} failed"
 msgid "Enable stream %{name} on %{node} failed"
 msgstr "Включение %{conf_name} in %{node_name} нипалучилася"
 msgstr "Включение %{conf_name} in %{node_name} нипалучилася"
 
 
-#: src/components/Notification/notifications.ts:116
+#: src/components/Notification/notifications.ts:134
 msgid "Enable stream %{name} on %{node} successfully"
 msgid "Enable stream %{name} on %{node} successfully"
 msgstr "Поток %{name} успешно включён на %{node}"
 msgstr "Поток %{name} успешно включён на %{node}"
 
 
@@ -1235,6 +1263,11 @@ msgstr "Истекает: %{date}"
 msgid "Export"
 msgid "Export"
 msgstr "Экспорт"
 msgstr "Экспорт"
 
 
+#: src/views/preference/ExternalNotify.vue:10
+#: src/views/preference/Preference.vue:169
+msgid "External Notify"
+msgstr ""
+
 #: src/views/site/cert/components/ObtainCertLive.vue:94
 #: src/views/site/cert/components/ObtainCertLive.vue:94
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
 msgstr "Не удалось получить сертификат"
 msgstr "Не удалось получить сертификат"
@@ -1636,7 +1669,7 @@ msgstr "Главная"
 msgid "Host"
 msgid "Host"
 msgstr "Хостинг HTTP"
 msgstr "Хостинг HTTP"
 
 
-#: src/views/preference/Preference.vue:174
+#: src/views/preference/Preference.vue:181
 #, fuzzy
 #, fuzzy
 msgid "HTTP"
 msgid "HTTP"
 msgstr "HTTP01"
 msgstr "HTTP01"
@@ -1699,12 +1732,12 @@ msgid "Import Certificate"
 msgstr "Импортировать сертификат"
 msgstr "Импортировать сертификат"
 
 
 #: src/views/nginx_log/NginxLogList.vue:137
 #: src/views/nginx_log/NginxLogList.vue:137
-#: src/views/site/site_list/SiteList.vue:128
+#: src/views/site/site_list/SiteList.vue:132
 msgid "Indexed"
 msgid "Indexed"
 msgstr ""
 msgstr ""
 
 
 #: src/views/nginx_log/NginxLogList.vue:134
 #: src/views/nginx_log/NginxLogList.vue:134
-#: src/views/site/site_list/SiteList.vue:125
+#: src/views/site/site_list/SiteList.vue:129
 msgid "Indexing..."
 msgid "Indexing..."
 msgstr ""
 msgstr ""
 
 
@@ -1786,6 +1819,11 @@ msgstr "Неверное имя файла"
 msgid "Invalid folder name"
 msgid "Invalid folder name"
 msgstr "Недопустимое имя папки"
 msgstr "Недопустимое имя папки"
 
 
+#: src/constants/errors/notification.ts:3
+#, fuzzy
+msgid "Invalid notifier config"
+msgstr "Неверный код OTP"
+
 #: src/constants/errors/user.ts:4
 #: src/constants/errors/user.ts:4
 msgid "Invalid otp code"
 msgid "Invalid otp code"
 msgstr "Неверный код OTP"
 msgstr "Неверный код OTP"
@@ -1846,6 +1884,10 @@ msgstr ""
 msgid "Key Type"
 msgid "Key Type"
 msgstr "Тип ключа"
 msgstr "Тип ключа"
 
 
+#: src/views/preference/components/ExternalNotify/columns.ts:29
+msgid "Language"
+msgstr ""
+
 #: src/views/system/Upgrade.vue:179
 #: src/views/system/Upgrade.vue:179
 msgid "Last checked at"
 msgid "Last checked at"
 msgstr "Последняя проверка в"
 msgstr "Последняя проверка в"
@@ -1944,7 +1986,7 @@ msgstr "Авторизация успешна"
 msgid "Logout successful"
 msgid "Logout successful"
 msgstr "Выход выполнен успешно"
 msgstr "Выход выполнен успешно"
 
 
-#: src/views/preference/Preference.vue:210
+#: src/views/preference/Preference.vue:217
 msgid "Logrotate"
 msgid "Logrotate"
 msgstr "Прокрутка"
 msgstr "Прокрутка"
 
 
@@ -1992,7 +2034,7 @@ msgstr ""
 msgid "Manage Configs"
 msgid "Manage Configs"
 msgstr "Конфигурации"
 msgstr "Конфигурации"
 
 
-#: src/routes/modules/sites.ts:10 src/views/site/site_list/SiteList.vue:121
+#: src/routes/modules/sites.ts:10 src/views/site/site_list/SiteList.vue:125
 msgid "Manage Sites"
 msgid "Manage Sites"
 msgstr "Сайты"
 msgstr "Сайты"
 
 
@@ -2068,7 +2110,7 @@ msgstr "Многострочная директива"
 #: src/views/nginx_log/NginxLogList.vue:37
 #: src/views/nginx_log/NginxLogList.vue:37
 #: src/views/preference/components/AddPasskey.vue:75
 #: src/views/preference/components/AddPasskey.vue:75
 #: src/views/site/ngx_conf/NgxUpstream.vue:177
 #: src/views/site/ngx_conf/NgxUpstream.vue:177
-#: src/views/site/site_edit/RightSettings.vue:64
+#: src/views/site/site_edit/RightSettings.vue:63
 #: src/views/site/site_list/columns.tsx:17
 #: src/views/site/site_list/columns.tsx:17
 #: src/views/site/site_list/SiteDuplicate.vue:79
 #: src/views/site/site_list/SiteDuplicate.vue:79
 #: src/views/stream/components/RightSettings.vue:87
 #: src/views/stream/components/RightSettings.vue:87
@@ -2116,7 +2158,7 @@ msgstr "Вышла новая версия"
 msgid "Next"
 msgid "Next"
 msgstr "Дальше"
 msgstr "Дальше"
 
 
-#: src/views/preference/Preference.vue:198
+#: src/views/preference/Preference.vue:205
 msgid "Nginx"
 msgid "Nginx"
 msgstr "Nginx"
 msgstr "Nginx"
 
 
@@ -2258,7 +2300,7 @@ msgstr "Ошибка разбора конфигурации Nginx"
 #: src/views/preference/CertSettings.vue:73
 #: src/views/preference/CertSettings.vue:73
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:97
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:97
 #: src/views/site/ngx_conf/LocationEditor.vue:88
 #: src/views/site/ngx_conf/LocationEditor.vue:88
-#: src/views/site/site_list/SiteList.vue:161
+#: src/views/site/site_list/SiteList.vue:165
 #: src/views/stream/StreamList.vue:225
 #: src/views/stream/StreamList.vue:225
 msgid "No"
 msgid "No"
 msgstr "Нет"
 msgstr "Нет"
@@ -2273,12 +2315,12 @@ msgstr "Действие"
 msgid "No records selected"
 msgid "No records selected"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/Preference.vue:168
+#: src/views/preference/Preference.vue:175
 #, fuzzy
 #, fuzzy
 msgid "Node"
 msgid "Node"
 msgstr "Имя узла"
 msgstr "Имя узла"
 
 
-#: src/views/site/site_edit/RightSettings.vue:67
+#: src/views/site/site_edit/RightSettings.vue:66
 #: src/views/site/site_list/columns.tsx:63
 #: src/views/site/site_list/columns.tsx:63
 #: src/views/stream/components/RightSettings.vue:90
 #: src/views/stream/components/RightSettings.vue:90
 #: src/views/stream/StreamList.vue:30
 #: src/views/stream/StreamList.vue:30
@@ -2322,7 +2364,7 @@ msgstr "Недействительно до: %{date}"
 msgid "Note"
 msgid "Note"
 msgstr "Заметка"
 msgstr "Заметка"
 
 
-#: src/views/site/site_edit/RightSettings.vue:96
+#: src/views/site/site_edit/RightSettings.vue:95
 #: src/views/stream/components/RightSettings.vue:118
 #: src/views/stream/components/RightSettings.vue:118
 msgid ""
 msgid ""
 "Note, if the configuration file include other configurations or "
 "Note, if the configuration file include other configurations or "
@@ -2340,6 +2382,11 @@ msgstr "Уведомление"
 msgid "Notifications"
 msgid "Notifications"
 msgstr "Уведомления"
 msgstr "Уведомления"
 
 
+#: src/constants/errors/notification.ts:2
+#, fuzzy
+msgid "Notifier not found"
+msgstr "Файл не найден"
+
 #: src/views/site/cert/components/ObtainCert.vue:182
 #: src/views/site/cert/components/ObtainCert.vue:182
 msgid "Obtain certificate"
 msgid "Obtain certificate"
 msgstr "Получить сертификат"
 msgstr "Получить сертификат"
@@ -2384,7 +2431,7 @@ msgstr "Ок"
 #: src/views/site/ngx_conf/NgxServer.vue:79
 #: src/views/site/ngx_conf/NgxServer.vue:79
 #: src/views/site/ngx_conf/NgxUpstream.vue:33
 #: src/views/site/ngx_conf/NgxUpstream.vue:33
 #: src/views/site/site_edit/components/SiteStatusSegmented.vue:121
 #: src/views/site/site_edit/components/SiteStatusSegmented.vue:121
-#: src/views/site/site_list/SiteList.vue:162
+#: src/views/site/site_list/SiteList.vue:166
 #: src/views/stream/components/RightSettings.vue:54
 #: src/views/stream/components/RightSettings.vue:54
 #: src/views/stream/StreamList.vue:226
 #: src/views/stream/StreamList.vue:226
 #: src/views/system/Backup/BackupCreator.vue:149
 #: src/views/system/Backup/BackupCreator.vue:149
@@ -2407,7 +2454,7 @@ msgstr "Онлайн"
 msgid "Only zip files are allowed"
 msgid "Only zip files are allowed"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/Preference.vue:204
+#: src/views/preference/Preference.vue:211
 msgid "OpenAI"
 msgid "OpenAI"
 msgstr "OpenAI"
 msgstr "OpenAI"
 
 
@@ -2553,7 +2600,7 @@ msgstr ""
 "Credentials, а затем выберите одну из учетных данных ниже, чтобы запросить "
 "Credentials, а затем выберите одну из учетных данных ниже, чтобы запросить "
 "API провайдера DNS."
 "API провайдера DNS."
 
 
-#: src/components/Notification/notifications.ts:138
+#: src/components/Notification/notifications.ts:156
 #: src/language/constants.ts:59
 #: src/language/constants.ts:59
 msgid ""
 msgid ""
 "Please generate new recovery codes in the preferences immediately to prevent "
 "Please generate new recovery codes in the preferences immediately to prevent "
@@ -2650,7 +2697,7 @@ msgstr "Действие"
 msgid "Pre-release"
 msgid "Pre-release"
 msgstr "Предварительный выпуск"
 msgstr "Предварительный выпуск"
 
 
-#: src/routes/modules/preference.ts:10 src/views/preference/Preference.vue:151
+#: src/routes/modules/preference.ts:10 src/views/preference/Preference.vue:152
 msgid "Preference"
 msgid "Preference"
 msgstr "Настройки"
 msgstr "Настройки"
 
 
@@ -2788,22 +2835,22 @@ msgstr "Перегрузить"
 msgid "Reload Nginx"
 msgid "Reload Nginx"
 msgstr "Перезагружается nginx"
 msgstr "Перезагружается nginx"
 
 
-#: src/components/Notification/notifications.ts:144
+#: src/components/Notification/notifications.ts:10
 #, fuzzy
 #, fuzzy
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgstr "Удалить сайт: %{site_name}"
 msgstr "Удалить сайт: %{site_name}"
 
 
-#: src/components/Notification/notifications.ts:148
+#: src/components/Notification/notifications.ts:14
 #, fuzzy
 #, fuzzy
 msgid "Reload Nginx on %{node} successfully"
 msgid "Reload Nginx on %{node} successfully"
 msgstr "Интерфейс Nginx на %{node} успешно обновлен 🎉"
 msgstr "Интерфейс Nginx на %{node} успешно обновлен 🎉"
 
 
-#: src/components/Notification/notifications.ts:143
+#: src/components/Notification/notifications.ts:9
 #, fuzzy
 #, fuzzy
 msgid "Reload Remote Nginx Error"
 msgid "Reload Remote Nginx Error"
 msgstr "Ошибка переименования удаленной конфигурации"
 msgstr "Ошибка переименования удаленной конфигурации"
 
 
-#: src/components/Notification/notifications.ts:147
+#: src/components/Notification/notifications.ts:13
 #, fuzzy
 #, fuzzy
 msgid "Reload Remote Nginx Success"
 msgid "Reload Remote Nginx Success"
 msgstr "Переименование удаленной конфигурации прошло успешно"
 msgstr "Переименование удаленной конфигурации прошло успешно"
@@ -2842,58 +2889,58 @@ msgstr "Успешно удалено"
 msgid "Rename"
 msgid "Rename"
 msgstr "Переименовать"
 msgstr "Переименовать"
 
 
-#: src/components/Notification/notifications.ts:28
+#: src/components/Notification/notifications.ts:46
 #, fuzzy
 #, fuzzy
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} failed"
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} failed"
 msgstr "Переименование %{orig_path} в %{new_path} на %{env_name} успешно"
 msgstr "Переименование %{orig_path} в %{new_path} на %{env_name} успешно"
 
 
-#: src/components/Notification/notifications.ts:32
+#: src/components/Notification/notifications.ts:50
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} successfully"
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} successfully"
 msgstr "%{orig_path} успешно переименован в %{new_path} на %{env_name}"
 msgstr "%{orig_path} успешно переименован в %{new_path} на %{env_name}"
 
 
-#: src/components/Notification/notifications.ts:27 src/language/constants.ts:42
+#: src/components/Notification/notifications.ts:45 src/language/constants.ts:42
 msgid "Rename Remote Config Error"
 msgid "Rename Remote Config Error"
 msgstr "Ошибка переименования удаленной конфигурации"
 msgstr "Ошибка переименования удаленной конфигурации"
 
 
-#: src/components/Notification/notifications.ts:31 src/language/constants.ts:41
+#: src/components/Notification/notifications.ts:49 src/language/constants.ts:41
 msgid "Rename Remote Config Success"
 msgid "Rename Remote Config Success"
 msgstr "Переименование удаленной конфигурации прошло успешно"
 msgstr "Переименование удаленной конфигурации прошло успешно"
 
 
-#: src/components/Notification/notifications.ts:77 src/language/constants.ts:56
+#: src/components/Notification/notifications.ts:95 src/language/constants.ts:56
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Site Error"
 msgid "Rename Remote Site Error"
 msgstr "Ошибка переименования удаленной конфигурации"
 msgstr "Ошибка переименования удаленной конфигурации"
 
 
-#: src/components/Notification/notifications.ts:81 src/language/constants.ts:55
+#: src/components/Notification/notifications.ts:99 src/language/constants.ts:55
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Site Success"
 msgid "Rename Remote Site Success"
 msgstr "Переименование удаленной конфигурации прошло успешно"
 msgstr "Переименование удаленной конфигурации прошло успешно"
 
 
-#: src/components/Notification/notifications.ts:119
+#: src/components/Notification/notifications.ts:137
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Stream Error"
 msgid "Rename Remote Stream Error"
 msgstr "Ошибка переименования удаленной конфигурации"
 msgstr "Ошибка переименования удаленной конфигурации"
 
 
-#: src/components/Notification/notifications.ts:123
+#: src/components/Notification/notifications.ts:141
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Stream Success"
 msgid "Rename Remote Stream Success"
 msgstr "Переименование удаленной конфигурации прошло успешно"
 msgstr "Переименование удаленной конфигурации прошло успешно"
 
 
-#: src/components/Notification/notifications.ts:78
+#: src/components/Notification/notifications.ts:96
 #, fuzzy
 #, fuzzy
 msgid "Rename site %{name} to %{new_name} on %{node} failed"
 msgid "Rename site %{name} to %{new_name} on %{node} failed"
 msgstr "Переименование %{orig_path} в %{new_path} на %{env_name} успешно"
 msgstr "Переименование %{orig_path} в %{new_path} на %{env_name} успешно"
 
 
-#: src/components/Notification/notifications.ts:82
+#: src/components/Notification/notifications.ts:100
 msgid "Rename site %{name} to %{new_name} on %{node} successfully"
 msgid "Rename site %{name} to %{new_name} on %{node} successfully"
 msgstr "Сайт %{name} успешно переименован в %{new_name} на %{node}"
 msgstr "Сайт %{name} успешно переименован в %{new_name} на %{node}"
 
 
-#: src/components/Notification/notifications.ts:120
+#: src/components/Notification/notifications.ts:138
 #, fuzzy
 #, fuzzy
 msgid "Rename stream %{name} to %{new_name} on %{node} failed"
 msgid "Rename stream %{name} to %{new_name} on %{node} failed"
 msgstr "Переименование %{orig_path} в %{new_path} на %{env_name} успешно"
 msgstr "Переименование %{orig_path} в %{new_path} на %{env_name} успешно"
 
 
-#: src/components/Notification/notifications.ts:124
+#: src/components/Notification/notifications.ts:142
 msgid "Rename stream %{name} to %{new_name} on %{node} successfully"
 msgid "Rename stream %{name} to %{new_name} on %{node} successfully"
 msgstr "Поток %{name} успешно переименован в %{new_name} на %{node}"
 msgstr "Поток %{name} успешно переименован в %{new_name} на %{node}"
 
 
@@ -2953,22 +3000,22 @@ msgstr "Перезапуск"
 msgid "Restart Nginx"
 msgid "Restart Nginx"
 msgstr "Перезапускается"
 msgstr "Перезапускается"
 
 
-#: src/components/Notification/notifications.ts:152
+#: src/components/Notification/notifications.ts:18
 #, fuzzy
 #, fuzzy
 msgid "Restart Nginx on %{node} failed, response: %{resp}"
 msgid "Restart Nginx on %{node} failed, response: %{resp}"
 msgstr "Включение %{conf_name} in %{node_name} успешно"
 msgstr "Включение %{conf_name} in %{node_name} успешно"
 
 
-#: src/components/Notification/notifications.ts:156
+#: src/components/Notification/notifications.ts:22
 #, fuzzy
 #, fuzzy
 msgid "Restart Nginx on %{node} successfully"
 msgid "Restart Nginx on %{node} successfully"
 msgstr "Интерфейс Nginx на %{node} успешно обновлен 🎉"
 msgstr "Интерфейс Nginx на %{node} успешно обновлен 🎉"
 
 
-#: src/components/Notification/notifications.ts:151
+#: src/components/Notification/notifications.ts:17
 #, fuzzy
 #, fuzzy
 msgid "Restart Remote Nginx Error"
 msgid "Restart Remote Nginx Error"
 msgstr "Ошибка переименования удаленной конфигурации"
 msgstr "Ошибка переименования удаленной конфигурации"
 
 
-#: src/components/Notification/notifications.ts:155
+#: src/components/Notification/notifications.ts:21
 #, fuzzy
 #, fuzzy
 msgid "Restart Remote Nginx Success"
 msgid "Restart Remote Nginx Success"
 msgstr "Переименование удаленной конфигурации прошло успешно"
 msgstr "Переименование удаленной конфигурации прошло успешно"
@@ -3035,7 +3082,7 @@ msgstr "Выполняется"
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/ConfigEditor.vue:271
 #: src/views/config/ConfigEditor.vue:271
 #: src/views/preference/components/Passkey.vue:130
 #: src/views/preference/components/Passkey.vue:130
-#: src/views/preference/Preference.vue:221
+#: src/views/preference/Preference.vue:228
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:127
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:127
 #: src/views/site/site_edit/components/ConfigName.vue:52
 #: src/views/site/site_edit/components/ConfigName.vue:52
 #: src/views/site/site_edit/SiteEdit.vue:292
 #: src/views/site/site_edit/SiteEdit.vue:292
@@ -3053,48 +3100,50 @@ msgstr "Сохранить директиву"
 msgid "Save error %{msg}"
 msgid "Save error %{msg}"
 msgstr "Ошибка сохранения %{msg}"
 msgstr "Ошибка сохранения %{msg}"
 
 
-#: src/components/Notification/notifications.ts:85 src/language/constants.ts:48
+#: src/components/Notification/notifications.ts:103
+#: src/language/constants.ts:48
 #, fuzzy
 #, fuzzy
 msgid "Save Remote Site Error"
 msgid "Save Remote Site Error"
 msgstr "Ошибка переименования удаленной конфигурации"
 msgstr "Ошибка переименования удаленной конфигурации"
 
 
-#: src/components/Notification/notifications.ts:89 src/language/constants.ts:47
+#: src/components/Notification/notifications.ts:107
+#: src/language/constants.ts:47
 #, fuzzy
 #, fuzzy
 msgid "Save Remote Site Success"
 msgid "Save Remote Site Success"
 msgstr "Переименование удаленной конфигурации прошло успешно"
 msgstr "Переименование удаленной конфигурации прошло успешно"
 
 
-#: src/components/Notification/notifications.ts:127
+#: src/components/Notification/notifications.ts:145
 #, fuzzy
 #, fuzzy
 msgid "Save Remote Stream Error"
 msgid "Save Remote Stream Error"
 msgstr "Ошибка переименования удаленной конфигурации"
 msgstr "Ошибка переименования удаленной конфигурации"
 
 
-#: src/components/Notification/notifications.ts:131
+#: src/components/Notification/notifications.ts:149
 #, fuzzy
 #, fuzzy
 msgid "Save Remote Stream Success"
 msgid "Save Remote Stream Success"
 msgstr "Переименование удаленной конфигурации прошло успешно"
 msgstr "Переименование удаленной конфигурации прошло успешно"
 
 
-#: src/components/Notification/notifications.ts:86
+#: src/components/Notification/notifications.ts:104
 #, fuzzy
 #, fuzzy
 msgid "Save site %{name} to %{node} failed"
 msgid "Save site %{name} to %{node} failed"
 msgstr "Продублированно %{conf_name} в %{node_name}"
 msgstr "Продублированно %{conf_name} в %{node_name}"
 
 
-#: src/components/Notification/notifications.ts:90
+#: src/components/Notification/notifications.ts:108
 msgid "Save site %{name} to %{node} successfully"
 msgid "Save site %{name} to %{node} successfully"
 msgstr "Сайт %{name} успешно сохранён на %{node}"
 msgstr "Сайт %{name} успешно сохранён на %{node}"
 
 
-#: src/components/Notification/notifications.ts:128
+#: src/components/Notification/notifications.ts:146
 #, fuzzy
 #, fuzzy
 msgid "Save stream %{name} to %{node} failed"
 msgid "Save stream %{name} to %{node} failed"
 msgstr "Не удалось развернуть %{conf_name} на %{node_name}"
 msgstr "Не удалось развернуть %{conf_name} на %{node_name}"
 
 
-#: src/components/Notification/notifications.ts:132
+#: src/components/Notification/notifications.ts:150
 msgid "Save stream %{name} to %{node} successfully"
 msgid "Save stream %{name} to %{node} successfully"
 msgstr "Поток %{name} успешно сохранён на %{node}"
 msgstr "Поток %{name} успешно сохранён на %{node}"
 
 
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:47
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:47
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:97
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:97
 #: src/views/certificate/CertificateEditor.vue:49
 #: src/views/certificate/CertificateEditor.vue:49
-#: src/views/preference/Preference.vue:123
+#: src/views/preference/Preference.vue:124
 msgid "Save successfully"
 msgid "Save successfully"
 msgstr "Сохранено успешно"
 msgstr "Сохранено успешно"
 
 
@@ -3116,6 +3165,10 @@ msgstr ""
 msgid "SDK"
 msgid "SDK"
 msgstr "SDK"
 msgstr "SDK"
 
 
+#: src/views/preference/components/ExternalNotify/dingtalk.ts:13
+msgid "Secret (Optional)"
+msgstr ""
+
 #: src/views/preference/components/TOTP.vue:109
 #: src/views/preference/components/TOTP.vue:109
 msgid "Secret has been copied"
 msgid "Secret has been copied"
 msgstr ""
 msgstr ""
@@ -3147,7 +3200,7 @@ msgstr ""
 msgid "Send"
 msgid "Send"
 msgstr "Отправлено"
 msgstr "Отправлено"
 
 
-#: src/views/preference/Preference.vue:156
+#: src/views/preference/Preference.vue:157
 #, fuzzy
 #, fuzzy
 msgid "Server"
 msgid "Server"
 msgstr "Информация о сервере"
 msgstr "Информация о сервере"
@@ -3156,6 +3209,11 @@ msgstr "Информация о сервере"
 msgid "Server Info"
 msgid "Server Info"
 msgstr "Информация о сервере"
 msgstr "Информация о сервере"
 
 
+#: src/views/preference/components/ExternalNotify/bark.ts:13
+#, fuzzy
+msgid "Server URL"
+msgstr "Информация о сервере"
+
 #: src/views/site/cert/components/ObtainCert.vue:107
 #: src/views/site/cert/components/ObtainCert.vue:107
 msgid "server_name not found in directives"
 msgid "server_name not found in directives"
 msgstr "server_name не нашел в директивах"
 msgstr "server_name не нашел в директивах"
@@ -3329,7 +3387,7 @@ msgstr ""
 #: src/views/certificate/ACMEUser.vue:65
 #: src/views/certificate/ACMEUser.vue:65
 #: src/views/certificate/CertificateList/certColumns.tsx:65
 #: src/views/certificate/CertificateList/certColumns.tsx:65
 #: src/views/environments/list/envColumns.tsx:44
 #: src/views/environments/list/envColumns.tsx:44
-#: src/views/site/site_edit/RightSettings.vue:56
+#: src/views/site/site_edit/RightSettings.vue:55
 #: src/views/site/site_list/columns.tsx:80 src/views/stream/StreamList.vue:47
 #: src/views/site/site_list/columns.tsx:80 src/views/stream/StreamList.vue:47
 msgid "Status"
 msgid "Status"
 msgstr "Статус"
 msgstr "Статус"
@@ -3405,38 +3463,38 @@ msgstr "Синхронизация"
 msgid "Sync Certificate"
 msgid "Sync Certificate"
 msgstr "Синхронизировать сертификат"
 msgstr "Синхронизировать сертификат"
 
 
-#: src/components/Notification/notifications.ts:10
+#: src/components/Notification/notifications.ts:28
 #, fuzzy
 #, fuzzy
 msgid "Sync Certificate %{cert_name} to %{env_name} failed"
 msgid "Sync Certificate %{cert_name} to %{env_name} failed"
 msgstr "Сертификат %{cert_name} успешно синхронизирован с %{env_name}"
 msgstr "Сертификат %{cert_name} успешно синхронизирован с %{env_name}"
 
 
-#: src/components/Notification/notifications.ts:14
+#: src/components/Notification/notifications.ts:32
 msgid "Sync Certificate %{cert_name} to %{env_name} successfully"
 msgid "Sync Certificate %{cert_name} to %{env_name} successfully"
 msgstr "Сертификат %{cert_name} успешно синхронизирован с %{env_name}"
 msgstr "Сертификат %{cert_name} успешно синхронизирован с %{env_name}"
 
 
-#: src/components/Notification/notifications.ts:9 src/language/constants.ts:39
+#: src/components/Notification/notifications.ts:27 src/language/constants.ts:39
 msgid "Sync Certificate Error"
 msgid "Sync Certificate Error"
 msgstr "Ошибка синхронизации сертификата"
 msgstr "Ошибка синхронизации сертификата"
 
 
-#: src/components/Notification/notifications.ts:13 src/language/constants.ts:38
+#: src/components/Notification/notifications.ts:31 src/language/constants.ts:38
 msgid "Sync Certificate Success"
 msgid "Sync Certificate Success"
 msgstr "Сертификат успешно синхронизирован"
 msgstr "Сертификат успешно синхронизирован"
 
 
-#: src/components/Notification/notifications.ts:20
+#: src/components/Notification/notifications.ts:38
 #, fuzzy
 #, fuzzy
 msgid "Sync config %{config_name} to %{env_name} failed"
 msgid "Sync config %{config_name} to %{env_name} failed"
 msgstr "Конфигурация синхронизирована %{config_name} с %{env_name} успешно"
 msgstr "Конфигурация синхронизирована %{config_name} с %{env_name} успешно"
 
 
-#: src/components/Notification/notifications.ts:24
+#: src/components/Notification/notifications.ts:42
 #, fuzzy
 #, fuzzy
 msgid "Sync config %{config_name} to %{env_name} successfully"
 msgid "Sync config %{config_name} to %{env_name} successfully"
 msgstr "Конфигурация синхронизирована %{config_name} с %{env_name} успешно"
 msgstr "Конфигурация синхронизирована %{config_name} с %{env_name} успешно"
 
 
-#: src/components/Notification/notifications.ts:19 src/language/constants.ts:45
+#: src/components/Notification/notifications.ts:37 src/language/constants.ts:45
 msgid "Sync Config Error"
 msgid "Sync Config Error"
 msgstr "Ошибка синхронизации конфигурации"
 msgstr "Ошибка синхронизации конфигурации"
 
 
-#: src/components/Notification/notifications.ts:23 src/language/constants.ts:44
+#: src/components/Notification/notifications.ts:41 src/language/constants.ts:44
 msgid "Sync Config Success"
 msgid "Sync Config Success"
 msgstr "Синхронизация конфигурации успешна"
 msgstr "Синхронизация конфигурации успешна"
 
 
@@ -3446,8 +3504,8 @@ msgstr "Синхронизация конфигурации успешна"
 msgid "Sync Nodes"
 msgid "Sync Nodes"
 msgstr "Синхронизировать с"
 msgstr "Синхронизировать с"
 
 
-#: src/views/site/site_edit/RightSettings.vue:102
-#: src/views/site/site_edit/RightSettings.vue:89
+#: src/views/site/site_edit/RightSettings.vue:101
+#: src/views/site/site_edit/RightSettings.vue:88
 #: src/views/stream/components/RightSettings.vue:111
 #: src/views/stream/components/RightSettings.vue:111
 #: src/views/stream/components/RightSettings.vue:124
 #: src/views/stream/components/RightSettings.vue:124
 #, fuzzy
 #, fuzzy
@@ -3458,7 +3516,7 @@ msgstr "Синхронизировать сертификат"
 msgid "Sync to"
 msgid "Sync to"
 msgstr "Синхронизировать с"
 msgstr "Синхронизировать с"
 
 
-#: src/views/site/site_edit/RightSettings.vue:86
+#: src/views/site/site_edit/RightSettings.vue:85
 #: src/views/stream/components/RightSettings.vue:108
 #: src/views/stream/components/RightSettings.vue:108
 msgid "Synchronization"
 msgid "Synchronization"
 msgstr ""
 msgstr ""
@@ -3491,7 +3549,11 @@ msgstr "Nginx успешно перезапущен"
 msgid "Task not found"
 msgid "Task not found"
 msgstr "Файл не найден"
 msgstr "Файл не найден"
 
 
-#: src/routes/modules/terminal.ts:10 src/views/preference/Preference.vue:180
+#: src/views/preference/components/ExternalNotify/telegram.ts:5
+msgid "Telegram"
+msgstr ""
+
+#: src/routes/modules/terminal.ts:10 src/views/preference/Preference.vue:187
 #: src/views/terminal/Terminal.vue:129
 #: src/views/terminal/Terminal.vue:129
 msgid "Terminal"
 msgid "Terminal"
 msgstr "Терминал"
 msgstr "Терминал"
@@ -3764,6 +3826,7 @@ msgstr "Требуется двухфакторная аутентификаци
 #: src/views/certificate/CertificateList/certColumns.tsx:25
 #: src/views/certificate/CertificateList/certColumns.tsx:25
 #: src/views/nginx_log/NginxLogList.vue:21
 #: src/views/nginx_log/NginxLogList.vue:21
 #: src/views/notification/notificationColumns.tsx:9
 #: src/views/notification/notificationColumns.tsx:9
+#: src/views/preference/components/ExternalNotify/columns.ts:17
 msgid "Type"
 msgid "Type"
 msgstr "Тип"
 msgstr "Тип"
 
 
@@ -3781,7 +3844,7 @@ msgstr "Успешно обновлено"
 #: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:325
 #: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:325
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/environments/list/envColumns.tsx:90
-#: src/views/site/site_edit/RightSettings.vue:76
+#: src/views/site/site_edit/RightSettings.vue:75
 #: src/views/site/site_list/columns.tsx:110
 #: src/views/site/site_list/columns.tsx:110
 #: src/views/stream/components/RightSettings.vue:99
 #: src/views/stream/components/RightSettings.vue:99
 #: src/views/stream/StreamList.vue:67 src/views/user/userColumns.tsx:54
 #: src/views/stream/StreamList.vue:67 src/views/user/userColumns.tsx:54
@@ -3944,7 +4007,7 @@ msgid ""
 "Pebble as CA."
 "Pebble as CA."
 msgstr ""
 msgstr ""
 
 
-#: src/views/site/site_edit/RightSettings.vue:92
+#: src/views/site/site_edit/RightSettings.vue:91
 msgid ""
 msgid ""
 "When you enable/disable, delete, or save this site, the nodes set in the "
 "When you enable/disable, delete, or save this site, the nodes set in the "
 "Node Group and the nodes selected below will be synchronized."
 "Node Group and the nodes selected below will be synchronized."

+ 165 - 102
app/src/language/tr_TR/app.po

@@ -33,6 +33,11 @@ msgstr "Erişim Günlükleri"
 msgid "Access Logs"
 msgid "Access Logs"
 msgstr "Erişim Günlükleri"
 msgstr "Erişim Günlükleri"
 
 
+#: src/views/preference/components/ExternalNotify/dingtalk.ts:9
+#, fuzzy
+msgid "Access Token"
+msgstr "Erişim Günlükleri"
+
 #: src/routes/modules/certificates.ts:20 src/views/certificate/ACMEUser.vue:113
 #: src/routes/modules/certificates.ts:20 src/views/certificate/ACMEUser.vue:113
 #: src/views/certificate/ACMEUserSelector.vue:85
 #: src/views/certificate/ACMEUserSelector.vue:85
 msgid "ACME User"
 msgid "ACME User"
@@ -47,6 +52,7 @@ msgstr "ACME Kullanıcısı"
 #: src/views/nginx_log/NginxLogList.vue:53
 #: src/views/nginx_log/NginxLogList.vue:53
 #: src/views/notification/notificationColumns.tsx:66
 #: src/views/notification/notificationColumns.tsx:66
 #: src/views/preference/AuthSettings.vue:30
 #: src/views/preference/AuthSettings.vue:30
+#: src/views/preference/components/ExternalNotify/columns.ts:46
 #: src/views/site/site_list/columns.tsx:117 src/views/stream/StreamList.vue:74
 #: src/views/site/site_list/columns.tsx:117 src/views/stream/StreamList.vue:74
 #: src/views/user/userColumns.tsx:60
 #: src/views/user/userColumns.tsx:60
 msgid "Action"
 msgid "Action"
@@ -112,7 +118,7 @@ msgstr ""
 msgid "All"
 msgid "All"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:137
+#: src/components/Notification/notifications.ts:155
 #: src/language/constants.ts:58
 #: src/language/constants.ts:58
 msgid "All Recovery Codes Have Been Used"
 msgid "All Recovery Codes Have Been Used"
 msgstr ""
 msgstr ""
@@ -138,7 +144,7 @@ msgstr "API Token"
 msgid "API Type"
 msgid "API Type"
 msgstr "API Token"
 msgstr "API Token"
 
 
-#: src/views/preference/Preference.vue:162
+#: src/views/preference/Preference.vue:163
 msgid "App"
 msgid "App"
 msgstr ""
 msgstr ""
 
 
@@ -195,7 +201,7 @@ msgstr "Bu öğeyi kalıcı olarak silmek istediğinizden emin misiniz?"
 msgid "Are you sure you want to delete this item?"
 msgid "Are you sure you want to delete this item?"
 msgstr "Bu öğeyi silmek istediğinizden emin misiniz?"
 msgstr "Bu öğeyi silmek istediğinizden emin misiniz?"
 
 
-#: src/views/site/site_list/SiteList.vue:163
+#: src/views/site/site_list/SiteList.vue:167
 #: src/views/stream/StreamList.vue:227
 #: src/views/stream/StreamList.vue:227
 msgid "Are you sure you want to delete?"
 msgid "Are you sure you want to delete?"
 msgstr "Silmek istediğine emin misin?"
 msgstr "Silmek istediğine emin misin?"
@@ -243,7 +249,7 @@ msgstr "Girişimler"
 msgid "Attempts"
 msgid "Attempts"
 msgstr "Girişimler"
 msgstr "Girişimler"
 
 
-#: src/views/preference/Preference.vue:186
+#: src/views/preference/Preference.vue:193
 msgid "Auth"
 msgid "Auth"
 msgstr "Kimlik Doğrulama"
 msgstr "Kimlik Doğrulama"
 
 
@@ -327,12 +333,16 @@ msgstr "Yasaklı IP'ler"
 msgid "Banned Until"
 msgid "Banned Until"
 msgstr "Şu Zamana Kadar Yasaklı"
 msgstr "Şu Zamana Kadar Yasaklı"
 
 
+#: src/views/preference/components/ExternalNotify/bark.ts:5
+msgid "Bark"
+msgstr ""
+
 #: src/views/site/site_add/SiteAdd.vue:95
 #: src/views/site/site_add/SiteAdd.vue:95
 msgid "Base information"
 msgid "Base information"
 msgstr "Temel bilgiler"
 msgstr "Temel bilgiler"
 
 
 #: src/views/config/ConfigEditor.vue:290
 #: src/views/config/ConfigEditor.vue:290
-#: src/views/site/site_edit/RightSettings.vue:53
+#: src/views/site/site_edit/RightSettings.vue:52
 #: src/views/stream/components/RightSettings.vue:79
 #: src/views/stream/components/RightSettings.vue:79
 msgid "Basic"
 msgid "Basic"
 msgstr "Temel"
 msgstr "Temel"
@@ -364,6 +374,11 @@ msgstr ""
 msgid "Block is nil"
 msgid "Block is nil"
 msgstr ""
 msgstr ""
 
 
+#: src/views/preference/components/ExternalNotify/telegram.ts:9
+#, fuzzy
+msgid "Bot Token"
+msgstr "API Token"
+
 #: src/views/system/About.vue:55
 #: src/views/system/About.vue:55
 msgid "Build with"
 msgid "Build with"
 msgstr "İle Oluşturuldu"
 msgstr "İle Oluşturuldu"
@@ -405,7 +420,7 @@ msgstr ""
 msgid "Cannot remove initial user"
 msgid "Cannot remove initial user"
 msgstr "Sistem İlk Kullanıcısı"
 msgstr "Sistem İlk Kullanıcısı"
 
 
-#: src/views/preference/Preference.vue:192
+#: src/views/preference/Preference.vue:199
 msgid "Cert"
 msgid "Cert"
 msgstr ""
 msgstr ""
 
 
@@ -477,6 +492,10 @@ msgstr "Değişen Dosya Yolu"
 msgid "Channel"
 msgid "Channel"
 msgstr "Kanal"
 msgstr "Kanal"
 
 
+#: src/views/preference/components/ExternalNotify/telegram.ts:13
+msgid "Chat ID"
+msgstr ""
+
 #: src/views/system/Upgrade.vue:185
 #: src/views/system/Upgrade.vue:185
 msgid "Check again"
 msgid "Check again"
 msgstr "Tekrar kontrol et"
 msgstr "Tekrar kontrol et"
@@ -673,6 +692,7 @@ msgstr ""
 
 
 #: src/views/environments/group/columns.ts:31
 #: src/views/environments/group/columns.ts:31
 #: src/views/notification/notificationColumns.tsx:59
 #: src/views/notification/notificationColumns.tsx:59
+#: src/views/preference/components/ExternalNotify/columns.ts:41
 #: src/views/preference/components/Passkey.vue:95
 #: src/views/preference/components/Passkey.vue:95
 #: src/views/user/userColumns.tsx:48
 #: src/views/user/userColumns.tsx:48
 msgid "Created at"
 msgid "Created at"
@@ -745,7 +765,7 @@ msgstr "Açıklama"
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/views/site/ngx_conf/NgxServer.vue:110
 #: src/views/site/ngx_conf/NgxServer.vue:110
 #: src/views/site/ngx_conf/NgxUpstream.vue:128
 #: src/views/site/ngx_conf/NgxUpstream.vue:128
-#: src/views/site/site_list/SiteList.vue:172
+#: src/views/site/site_list/SiteList.vue:176
 #: src/views/stream/StreamList.vue:236
 #: src/views/stream/StreamList.vue:236
 msgid "Delete"
 msgid "Delete"
 msgstr "Sil"
 msgstr "Sil"
@@ -755,48 +775,48 @@ msgstr "Sil"
 msgid "Delete Permanently"
 msgid "Delete Permanently"
 msgstr "Kalıcı Olarak Sil"
 msgstr "Kalıcı Olarak Sil"
 
 
-#: src/components/Notification/notifications.ts:37 src/language/constants.ts:50
+#: src/components/Notification/notifications.ts:55 src/language/constants.ts:50
 #, fuzzy
 #, fuzzy
 msgid "Delete Remote Site Error"
 msgid "Delete Remote Site Error"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandır Hatası"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandır Hatası"
 
 
-#: src/components/Notification/notifications.ts:41 src/language/constants.ts:49
+#: src/components/Notification/notifications.ts:59 src/language/constants.ts:49
 #, fuzzy
 #, fuzzy
 msgid "Delete Remote Site Success"
 msgid "Delete Remote Site Success"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandırma Başarılı"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandırma Başarılı"
 
 
-#: src/components/Notification/notifications.ts:95
+#: src/components/Notification/notifications.ts:113
 #, fuzzy
 #, fuzzy
 msgid "Delete Remote Stream Error"
 msgid "Delete Remote Stream Error"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandır Hatası"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandır Hatası"
 
 
-#: src/components/Notification/notifications.ts:99
+#: src/components/Notification/notifications.ts:117
 #, fuzzy
 #, fuzzy
 msgid "Delete Remote Stream Success"
 msgid "Delete Remote Stream Success"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandırma Başarılı"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandırma Başarılı"
 
 
-#: src/components/Notification/notifications.ts:38
+#: src/components/Notification/notifications.ts:56
 #, fuzzy
 #, fuzzy
 msgid "Delete site %{name} from %{node} failed"
 msgid "Delete site %{name} from %{node} failed"
 msgstr ""
 msgstr ""
 "%{conf_name} yapılandırmasını %{node_name} düğümüne dağıtma başarısız oldu"
 "%{conf_name} yapılandırmasını %{node_name} düğümüne dağıtma başarısız oldu"
 
 
-#: src/components/Notification/notifications.ts:42
+#: src/components/Notification/notifications.ts:60
 #, fuzzy
 #, fuzzy
 msgid "Delete site %{name} from %{node} successfully"
 msgid "Delete site %{name} from %{node} successfully"
 msgstr "%{conf_name} başarıyla %{node_name} düğümüne kopyalandı"
 msgstr "%{conf_name} başarıyla %{node_name} düğümüne kopyalandı"
 
 
-#: src/views/site/site_list/SiteList.vue:94
+#: src/views/site/site_list/SiteList.vue:98
 msgid "Delete site: %{site_name}"
 msgid "Delete site: %{site_name}"
 msgstr "Siteyi sil: %{site_name}"
 msgstr "Siteyi sil: %{site_name}"
 
 
-#: src/components/Notification/notifications.ts:96
+#: src/components/Notification/notifications.ts:114
 #, fuzzy
 #, fuzzy
 msgid "Delete stream %{name} from %{node} failed"
 msgid "Delete stream %{name} from %{node} failed"
 msgstr ""
 msgstr ""
 "%{conf_name} yapılandırmasını %{node_name} düğümüne dağıtma başarısız oldu"
 "%{conf_name} yapılandırmasını %{node_name} düğümüne dağıtma başarısız oldu"
 
 
-#: src/components/Notification/notifications.ts:100
+#: src/components/Notification/notifications.ts:118
 #, fuzzy
 #, fuzzy
 msgid "Delete stream %{name} from %{node} successfully"
 msgid "Delete stream %{name} from %{node} successfully"
 msgstr "%{conf_name} başarıyla %{node_name} düğümüne kopyalandı"
 msgstr "%{conf_name} başarıyla %{node_name} düğümüne kopyalandı"
@@ -834,6 +854,14 @@ msgstr "Detaylar"
 msgid "Development Mode"
 msgid "Development Mode"
 msgstr "Geliştirme modu"
 msgstr "Geliştirme modu"
 
 
+#: src/views/preference/components/ExternalNotify/bark.ts:9
+msgid "Device Key"
+msgstr ""
+
+#: src/views/preference/components/ExternalNotify/dingtalk.ts:5
+msgid "DingTalk"
+msgstr ""
+
 #: src/views/site/ngx_conf/directive/DirectiveAdd.vue:89
 #: src/views/site/ngx_conf/directive/DirectiveAdd.vue:89
 msgid "Directive"
 msgid "Directive"
 msgstr "Talimat"
 msgstr "Talimat"
@@ -867,72 +895,72 @@ msgstr "Devre Dışı"
 msgid "Disable auto-renewal failed for %{name}"
 msgid "Disable auto-renewal failed for %{name}"
 msgstr "%{name} için otomatik yenilemeyi devre dışı bırakma başarısız oldu"
 msgstr "%{name} için otomatik yenilemeyi devre dışı bırakma başarısız oldu"
 
 
-#: src/components/Notification/notifications.ts:45 src/language/constants.ts:52
+#: src/components/Notification/notifications.ts:63 src/language/constants.ts:52
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Site Error"
 msgid "Disable Remote Site Error"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandır Hatası"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandır Hatası"
 
 
-#: src/components/Notification/notifications.ts:69
+#: src/components/Notification/notifications.ts:87
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Site Maintenance Error"
 msgid "Disable Remote Site Maintenance Error"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandır Hatası"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandır Hatası"
 
 
-#: src/components/Notification/notifications.ts:73
+#: src/components/Notification/notifications.ts:91
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Site Maintenance Success"
 msgid "Disable Remote Site Maintenance Success"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandırma Başarılı"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandırma Başarılı"
 
 
-#: src/components/Notification/notifications.ts:49 src/language/constants.ts:51
+#: src/components/Notification/notifications.ts:67 src/language/constants.ts:51
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Site Success"
 msgid "Disable Remote Site Success"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandırma Başarılı"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandırma Başarılı"
 
 
-#: src/components/Notification/notifications.ts:103
+#: src/components/Notification/notifications.ts:121
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Stream Error"
 msgid "Disable Remote Stream Error"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandır Hatası"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandır Hatası"
 
 
-#: src/components/Notification/notifications.ts:107
+#: src/components/Notification/notifications.ts:125
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Stream Success"
 msgid "Disable Remote Stream Success"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandırma Başarılı"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandırma Başarılı"
 
 
-#: src/components/Notification/notifications.ts:46
+#: src/components/Notification/notifications.ts:64
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} from %{node} failed"
 msgid "Disable site %{name} from %{node} failed"
 msgstr ""
 msgstr ""
 "%{conf_name} yapılandırmasını %{node_name} düğümünde etkinleştirme başarılı "
 "%{conf_name} yapılandırmasını %{node_name} düğümünde etkinleştirme başarılı "
 "oldu"
 "oldu"
 
 
-#: src/components/Notification/notifications.ts:50
+#: src/components/Notification/notifications.ts:68
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} from %{node} successfully"
 msgid "Disable site %{name} from %{node} successfully"
 msgstr ""
 msgstr ""
 "%{conf_name} yapılandırmasını %{node_name} düğümünde etkinleştirme başarılı "
 "%{conf_name} yapılandırmasını %{node_name} düğümünde etkinleştirme başarılı "
 "oldu"
 "oldu"
 
 
-#: src/components/Notification/notifications.ts:70
+#: src/components/Notification/notifications.ts:88
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} maintenance on %{node} failed"
 msgid "Disable site %{name} maintenance on %{node} failed"
 msgstr ""
 msgstr ""
 "%{conf_name} yapılandırmasını %{node_name} düğümünde etkinleştirme başarılı "
 "%{conf_name} yapılandırmasını %{node_name} düğümünde etkinleştirme başarılı "
 "oldu"
 "oldu"
 
 
-#: src/components/Notification/notifications.ts:74
+#: src/components/Notification/notifications.ts:92
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} maintenance on %{node} successfully"
 msgid "Disable site %{name} maintenance on %{node} successfully"
 msgstr ""
 msgstr ""
 "%{conf_name} yapılandırmasını %{node_name} düğümünde etkinleştirme başarılı "
 "%{conf_name} yapılandırmasını %{node_name} düğümünde etkinleştirme başarılı "
 "oldu"
 "oldu"
 
 
-#: src/components/Notification/notifications.ts:104
+#: src/components/Notification/notifications.ts:122
 #, fuzzy
 #, fuzzy
 msgid "Disable stream %{name} from %{node} failed"
 msgid "Disable stream %{name} from %{node} failed"
 msgstr ""
 msgstr ""
 "%{conf_name} yapılandırmasını %{node_name} düğümünde etkinleştirme başarısız "
 "%{conf_name} yapılandırmasını %{node_name} düğümünde etkinleştirme başarısız "
 "oldu"
 "oldu"
 
 
-#: src/components/Notification/notifications.ts:108
+#: src/components/Notification/notifications.ts:126
 #, fuzzy
 #, fuzzy
 msgid "Disable stream %{name} from %{node} successfully"
 msgid "Disable stream %{name} from %{node} successfully"
 msgstr ""
 msgstr ""
@@ -1049,7 +1077,7 @@ msgstr ""
 "kullanamazsınız."
 "kullanamazsınız."
 
 
 #: src/views/site/site_list/SiteDuplicate.vue:72
 #: src/views/site/site_list/SiteDuplicate.vue:72
-#: src/views/site/site_list/SiteList.vue:158
+#: src/views/site/site_list/SiteList.vue:162
 #: src/views/stream/components/StreamDuplicate.vue:64
 #: src/views/stream/components/StreamDuplicate.vue:64
 #: src/views/stream/StreamList.vue:222
 #: src/views/stream/StreamList.vue:222
 msgid "Duplicate"
 msgid "Duplicate"
@@ -1117,72 +1145,72 @@ msgstr "Etkinleştirme başarısız"
 msgid "Enable HTTPS"
 msgid "Enable HTTPS"
 msgstr "TOTP'yi Etkinleştir"
 msgstr "TOTP'yi Etkinleştir"
 
 
-#: src/components/Notification/notifications.ts:53 src/language/constants.ts:54
+#: src/components/Notification/notifications.ts:71 src/language/constants.ts:54
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Site Error"
 msgid "Enable Remote Site Error"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandır Hatası"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandır Hatası"
 
 
-#: src/components/Notification/notifications.ts:61
+#: src/components/Notification/notifications.ts:79
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Site Maintenance Error"
 msgid "Enable Remote Site Maintenance Error"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandır Hatası"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandır Hatası"
 
 
-#: src/components/Notification/notifications.ts:65
+#: src/components/Notification/notifications.ts:83
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Site Maintenance Success"
 msgid "Enable Remote Site Maintenance Success"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandırma Başarılı"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandırma Başarılı"
 
 
-#: src/components/Notification/notifications.ts:57 src/language/constants.ts:53
+#: src/components/Notification/notifications.ts:75 src/language/constants.ts:53
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Site Success"
 msgid "Enable Remote Site Success"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandırma Başarılı"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandırma Başarılı"
 
 
-#: src/components/Notification/notifications.ts:111
+#: src/components/Notification/notifications.ts:129
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Stream Error"
 msgid "Enable Remote Stream Error"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandır Hatası"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandır Hatası"
 
 
-#: src/components/Notification/notifications.ts:115
+#: src/components/Notification/notifications.ts:133
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Stream Success"
 msgid "Enable Remote Stream Success"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandırma Başarılı"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandırma Başarılı"
 
 
-#: src/components/Notification/notifications.ts:62
+#: src/components/Notification/notifications.ts:80
 #, fuzzy
 #, fuzzy
 msgid "Enable site %{name} maintenance on %{node} failed"
 msgid "Enable site %{name} maintenance on %{node} failed"
 msgstr ""
 msgstr ""
 "%{conf_name} yapılandırmasını %{node_name} düğümünde etkinleştirme başarısız "
 "%{conf_name} yapılandırmasını %{node_name} düğümünde etkinleştirme başarısız "
 "oldu"
 "oldu"
 
 
-#: src/components/Notification/notifications.ts:66
+#: src/components/Notification/notifications.ts:84
 #, fuzzy
 #, fuzzy
 msgid "Enable site %{name} maintenance on %{node} successfully"
 msgid "Enable site %{name} maintenance on %{node} successfully"
 msgstr ""
 msgstr ""
 "%{conf_name} yapılandırmasını %{node_name} düğümünde etkinleştirme başarılı "
 "%{conf_name} yapılandırmasını %{node_name} düğümünde etkinleştirme başarılı "
 "oldu"
 "oldu"
 
 
-#: src/components/Notification/notifications.ts:54
+#: src/components/Notification/notifications.ts:72
 #, fuzzy
 #, fuzzy
 msgid "Enable site %{name} on %{node} failed"
 msgid "Enable site %{name} on %{node} failed"
 msgstr ""
 msgstr ""
 "%{conf_name} yapılandırmasını %{node_name} düğümünde etkinleştirme başarısız "
 "%{conf_name} yapılandırmasını %{node_name} düğümünde etkinleştirme başarısız "
 "oldu"
 "oldu"
 
 
-#: src/components/Notification/notifications.ts:58
+#: src/components/Notification/notifications.ts:76
 #, fuzzy
 #, fuzzy
 msgid "Enable site %{name} on %{node} successfully"
 msgid "Enable site %{name} on %{node} successfully"
 msgstr ""
 msgstr ""
 "%{conf_name} yapılandırmasını %{node_name} düğümünde etkinleştirme başarılı "
 "%{conf_name} yapılandırmasını %{node_name} düğümünde etkinleştirme başarılı "
 "oldu"
 "oldu"
 
 
-#: src/components/Notification/notifications.ts:112
+#: src/components/Notification/notifications.ts:130
 #, fuzzy
 #, fuzzy
 msgid "Enable stream %{name} on %{node} failed"
 msgid "Enable stream %{name} on %{node} failed"
 msgstr ""
 msgstr ""
 "%{conf_name} yapılandırmasını %{node_name} düğümünde etkinleştirme başarısız "
 "%{conf_name} yapılandırmasını %{node_name} düğümünde etkinleştirme başarısız "
 "oldu"
 "oldu"
 
 
-#: src/components/Notification/notifications.ts:116
+#: src/components/Notification/notifications.ts:134
 #, fuzzy
 #, fuzzy
 msgid "Enable stream %{name} on %{node} successfully"
 msgid "Enable stream %{name} on %{node} successfully"
 msgstr ""
 msgstr ""
@@ -1272,6 +1300,11 @@ msgstr "Son kullanma tarihi: %{date}"
 msgid "Export"
 msgid "Export"
 msgstr "Dışa Aktar"
 msgstr "Dışa Aktar"
 
 
+#: src/views/preference/ExternalNotify.vue:10
+#: src/views/preference/Preference.vue:169
+msgid "External Notify"
+msgstr ""
+
 #: src/views/site/cert/components/ObtainCertLive.vue:94
 #: src/views/site/cert/components/ObtainCertLive.vue:94
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
 msgstr "Sertifika alınamadı"
 msgstr "Sertifika alınamadı"
@@ -1673,7 +1706,7 @@ msgstr "Anasayfa"
 msgid "Host"
 msgid "Host"
 msgstr "HTTP Sunucusu"
 msgstr "HTTP Sunucusu"
 
 
-#: src/views/preference/Preference.vue:174
+#: src/views/preference/Preference.vue:181
 #, fuzzy
 #, fuzzy
 msgid "HTTP"
 msgid "HTTP"
 msgstr "HTTP01"
 msgstr "HTTP01"
@@ -1737,12 +1770,12 @@ msgid "Import Certificate"
 msgstr "Sertifika İçe Aktar"
 msgstr "Sertifika İçe Aktar"
 
 
 #: src/views/nginx_log/NginxLogList.vue:137
 #: src/views/nginx_log/NginxLogList.vue:137
-#: src/views/site/site_list/SiteList.vue:128
+#: src/views/site/site_list/SiteList.vue:132
 msgid "Indexed"
 msgid "Indexed"
 msgstr ""
 msgstr ""
 
 
 #: src/views/nginx_log/NginxLogList.vue:134
 #: src/views/nginx_log/NginxLogList.vue:134
-#: src/views/site/site_list/SiteList.vue:125
+#: src/views/site/site_list/SiteList.vue:129
 msgid "Indexing..."
 msgid "Indexing..."
 msgstr ""
 msgstr ""
 
 
@@ -1824,6 +1857,11 @@ msgstr "Geçersiz dosya adı"
 msgid "Invalid folder name"
 msgid "Invalid folder name"
 msgstr "Geçersiz klasör adı"
 msgstr "Geçersiz klasör adı"
 
 
+#: src/constants/errors/notification.ts:3
+#, fuzzy
+msgid "Invalid notifier config"
+msgstr "Geçersiz 2FA veya kurtarma kodu"
+
 #: src/constants/errors/user.ts:4
 #: src/constants/errors/user.ts:4
 #, fuzzy
 #, fuzzy
 msgid "Invalid otp code"
 msgid "Invalid otp code"
@@ -1886,6 +1924,10 @@ msgstr ""
 msgid "Key Type"
 msgid "Key Type"
 msgstr "Anahtar Türü"
 msgstr "Anahtar Türü"
 
 
+#: src/views/preference/components/ExternalNotify/columns.ts:29
+msgid "Language"
+msgstr ""
+
 #: src/views/system/Upgrade.vue:179
 #: src/views/system/Upgrade.vue:179
 msgid "Last checked at"
 msgid "Last checked at"
 msgstr "En son şu tarihte kontrol edildi"
 msgstr "En son şu tarihte kontrol edildi"
@@ -1983,7 +2025,7 @@ msgstr "Giriş Başarılı"
 msgid "Logout successful"
 msgid "Logout successful"
 msgstr "Çıkış başarılı"
 msgstr "Çıkış başarılı"
 
 
-#: src/views/preference/Preference.vue:210
+#: src/views/preference/Preference.vue:217
 msgid "Logrotate"
 msgid "Logrotate"
 msgstr "Logrotate"
 msgstr "Logrotate"
 
 
@@ -2033,7 +2075,7 @@ msgstr ""
 msgid "Manage Configs"
 msgid "Manage Configs"
 msgstr "Yapılandırmaları Yönet"
 msgstr "Yapılandırmaları Yönet"
 
 
-#: src/routes/modules/sites.ts:10 src/views/site/site_list/SiteList.vue:121
+#: src/routes/modules/sites.ts:10 src/views/site/site_list/SiteList.vue:125
 #, fuzzy
 #, fuzzy
 msgid "Manage Sites"
 msgid "Manage Sites"
 msgstr "Siteleri Yönet"
 msgstr "Siteleri Yönet"
@@ -2123,7 +2165,7 @@ msgstr "Çok Hatlı Direktif"
 #: src/views/nginx_log/NginxLogList.vue:37
 #: src/views/nginx_log/NginxLogList.vue:37
 #: src/views/preference/components/AddPasskey.vue:75
 #: src/views/preference/components/AddPasskey.vue:75
 #: src/views/site/ngx_conf/NgxUpstream.vue:177
 #: src/views/site/ngx_conf/NgxUpstream.vue:177
-#: src/views/site/site_edit/RightSettings.vue:64
+#: src/views/site/site_edit/RightSettings.vue:63
 #: src/views/site/site_list/columns.tsx:17
 #: src/views/site/site_list/columns.tsx:17
 #: src/views/site/site_list/SiteDuplicate.vue:79
 #: src/views/site/site_list/SiteDuplicate.vue:79
 #: src/views/stream/components/RightSettings.vue:87
 #: src/views/stream/components/RightSettings.vue:87
@@ -2180,7 +2222,7 @@ msgstr "Yeni sürüm yayınlandı"
 msgid "Next"
 msgid "Next"
 msgstr "Sonraki"
 msgstr "Sonraki"
 
 
-#: src/views/preference/Preference.vue:198
+#: src/views/preference/Preference.vue:205
 #, fuzzy
 #, fuzzy
 msgid "Nginx"
 msgid "Nginx"
 msgstr "Nginx"
 msgstr "Nginx"
@@ -2331,7 +2373,7 @@ msgstr "Nginx Yapılandırma Ayrıştırma Hatası"
 #: src/views/preference/CertSettings.vue:73
 #: src/views/preference/CertSettings.vue:73
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:97
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:97
 #: src/views/site/ngx_conf/LocationEditor.vue:88
 #: src/views/site/ngx_conf/LocationEditor.vue:88
-#: src/views/site/site_list/SiteList.vue:161
+#: src/views/site/site_list/SiteList.vue:165
 #: src/views/stream/StreamList.vue:225
 #: src/views/stream/StreamList.vue:225
 #, fuzzy
 #, fuzzy
 msgid "No"
 msgid "No"
@@ -2347,12 +2389,12 @@ msgstr "Eylem"
 msgid "No records selected"
 msgid "No records selected"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/Preference.vue:168
+#: src/views/preference/Preference.vue:175
 #, fuzzy
 #, fuzzy
 msgid "Node"
 msgid "Node"
 msgstr "Yeni Ad"
 msgstr "Yeni Ad"
 
 
-#: src/views/site/site_edit/RightSettings.vue:67
+#: src/views/site/site_edit/RightSettings.vue:66
 #: src/views/site/site_list/columns.tsx:63
 #: src/views/site/site_list/columns.tsx:63
 #: src/views/stream/components/RightSettings.vue:90
 #: src/views/stream/components/RightSettings.vue:90
 #: src/views/stream/StreamList.vue:30
 #: src/views/stream/StreamList.vue:30
@@ -2402,7 +2444,7 @@ msgstr "Önce Geçerli Değil: %{date}"
 msgid "Note"
 msgid "Note"
 msgstr "Not"
 msgstr "Not"
 
 
-#: src/views/site/site_edit/RightSettings.vue:96
+#: src/views/site/site_edit/RightSettings.vue:95
 #: src/views/stream/components/RightSettings.vue:118
 #: src/views/stream/components/RightSettings.vue:118
 msgid ""
 msgid ""
 "Note, if the configuration file include other configurations or "
 "Note, if the configuration file include other configurations or "
@@ -2420,6 +2462,11 @@ msgstr "Bildirim"
 msgid "Notifications"
 msgid "Notifications"
 msgstr "Bildirimler"
 msgstr "Bildirimler"
 
 
+#: src/constants/errors/notification.ts:2
+#, fuzzy
+msgid "Notifier not found"
+msgstr "Dosya bulunamadı"
+
 #: src/views/site/cert/components/ObtainCert.vue:182
 #: src/views/site/cert/components/ObtainCert.vue:182
 #, fuzzy
 #, fuzzy
 msgid "Obtain certificate"
 msgid "Obtain certificate"
@@ -2470,7 +2517,7 @@ msgstr "Tamam"
 #: src/views/site/ngx_conf/NgxServer.vue:79
 #: src/views/site/ngx_conf/NgxServer.vue:79
 #: src/views/site/ngx_conf/NgxUpstream.vue:33
 #: src/views/site/ngx_conf/NgxUpstream.vue:33
 #: src/views/site/site_edit/components/SiteStatusSegmented.vue:121
 #: src/views/site/site_edit/components/SiteStatusSegmented.vue:121
-#: src/views/site/site_list/SiteList.vue:162
+#: src/views/site/site_list/SiteList.vue:166
 #: src/views/stream/components/RightSettings.vue:54
 #: src/views/stream/components/RightSettings.vue:54
 #: src/views/stream/StreamList.vue:226
 #: src/views/stream/StreamList.vue:226
 #: src/views/system/Backup/BackupCreator.vue:149
 #: src/views/system/Backup/BackupCreator.vue:149
@@ -2496,7 +2543,7 @@ msgstr "Çevrimiçi"
 msgid "Only zip files are allowed"
 msgid "Only zip files are allowed"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/Preference.vue:204
+#: src/views/preference/Preference.vue:211
 #, fuzzy
 #, fuzzy
 msgid "OpenAI"
 msgid "OpenAI"
 msgstr "OpenAI"
 msgstr "OpenAI"
@@ -2668,7 +2715,7 @@ msgstr ""
 "ekleyin ve ardından DNS sağlayıcısının API'sini istemek için aşağıdaki "
 "ekleyin ve ardından DNS sağlayıcısının API'sini istemek için aşağıdaki "
 "kimlik bilgilerinden birini seçin."
 "kimlik bilgilerinden birini seçin."
 
 
-#: src/components/Notification/notifications.ts:138
+#: src/components/Notification/notifications.ts:156
 #: src/language/constants.ts:59
 #: src/language/constants.ts:59
 msgid ""
 msgid ""
 "Please generate new recovery codes in the preferences immediately to prevent "
 "Please generate new recovery codes in the preferences immediately to prevent "
@@ -2773,7 +2820,7 @@ msgstr "Eylem"
 msgid "Pre-release"
 msgid "Pre-release"
 msgstr "Ön sürüm"
 msgstr "Ön sürüm"
 
 
-#: src/routes/modules/preference.ts:10 src/views/preference/Preference.vue:151
+#: src/routes/modules/preference.ts:10 src/views/preference/Preference.vue:152
 #, fuzzy
 #, fuzzy
 msgid "Preference"
 msgid "Preference"
 msgstr "Tercih"
 msgstr "Tercih"
@@ -2934,22 +2981,22 @@ msgstr "Tekrar yükle"
 msgid "Reload Nginx"
 msgid "Reload Nginx"
 msgstr "Nginx'i yeniden yükleme"
 msgstr "Nginx'i yeniden yükleme"
 
 
-#: src/components/Notification/notifications.ts:144
+#: src/components/Notification/notifications.ts:10
 #, fuzzy
 #, fuzzy
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgstr "Siteyi sil: %{site_name}"
 msgstr "Siteyi sil: %{site_name}"
 
 
-#: src/components/Notification/notifications.ts:148
+#: src/components/Notification/notifications.ts:14
 #, fuzzy
 #, fuzzy
 msgid "Reload Nginx on %{node} successfully"
 msgid "Reload Nginx on %{node} successfully"
 msgstr "Nginx kullanıcı arayüzü %{node} üzerinde başarıyla yükseltildi 🎉"
 msgstr "Nginx kullanıcı arayüzü %{node} üzerinde başarıyla yükseltildi 🎉"
 
 
-#: src/components/Notification/notifications.ts:143
+#: src/components/Notification/notifications.ts:9
 #, fuzzy
 #, fuzzy
 msgid "Reload Remote Nginx Error"
 msgid "Reload Remote Nginx Error"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandır Hatası"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandır Hatası"
 
 
-#: src/components/Notification/notifications.ts:147
+#: src/components/Notification/notifications.ts:13
 #, fuzzy
 #, fuzzy
 msgid "Reload Remote Nginx Success"
 msgid "Reload Remote Nginx Success"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandırma Başarılı"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandırma Başarılı"
@@ -2994,67 +3041,67 @@ msgstr "Başarıyla kaldırıldı"
 msgid "Rename"
 msgid "Rename"
 msgstr "Yeniden Adlandır"
 msgstr "Yeniden Adlandır"
 
 
-#: src/components/Notification/notifications.ts:28
+#: src/components/Notification/notifications.ts:46
 #, fuzzy
 #, fuzzy
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} failed"
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} failed"
 msgstr ""
 msgstr ""
 "2] üzerinde %{orig_path}'ı %{new_path} olarak başarıyla yeniden adlandırın"
 "2] üzerinde %{orig_path}'ı %{new_path} olarak başarıyla yeniden adlandırın"
 
 
-#: src/components/Notification/notifications.ts:32
+#: src/components/Notification/notifications.ts:50
 #, fuzzy
 #, fuzzy
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} successfully"
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} successfully"
 msgstr ""
 msgstr ""
 "2] üzerinde %{orig_path}'ı %{new_path} olarak başarıyla yeniden adlandırın"
 "2] üzerinde %{orig_path}'ı %{new_path} olarak başarıyla yeniden adlandırın"
 
 
-#: src/components/Notification/notifications.ts:27 src/language/constants.ts:42
+#: src/components/Notification/notifications.ts:45 src/language/constants.ts:42
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Config Error"
 msgid "Rename Remote Config Error"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandır Hatası"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandır Hatası"
 
 
-#: src/components/Notification/notifications.ts:31 src/language/constants.ts:41
+#: src/components/Notification/notifications.ts:49 src/language/constants.ts:41
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Config Success"
 msgid "Rename Remote Config Success"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandırma Başarılı"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandırma Başarılı"
 
 
-#: src/components/Notification/notifications.ts:77 src/language/constants.ts:56
+#: src/components/Notification/notifications.ts:95 src/language/constants.ts:56
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Site Error"
 msgid "Rename Remote Site Error"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandır Hatası"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandır Hatası"
 
 
-#: src/components/Notification/notifications.ts:81 src/language/constants.ts:55
+#: src/components/Notification/notifications.ts:99 src/language/constants.ts:55
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Site Success"
 msgid "Rename Remote Site Success"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandırma Başarılı"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandırma Başarılı"
 
 
-#: src/components/Notification/notifications.ts:119
+#: src/components/Notification/notifications.ts:137
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Stream Error"
 msgid "Rename Remote Stream Error"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandır Hatası"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandır Hatası"
 
 
-#: src/components/Notification/notifications.ts:123
+#: src/components/Notification/notifications.ts:141
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Stream Success"
 msgid "Rename Remote Stream Success"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandırma Başarılı"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandırma Başarılı"
 
 
-#: src/components/Notification/notifications.ts:78
+#: src/components/Notification/notifications.ts:96
 #, fuzzy
 #, fuzzy
 msgid "Rename site %{name} to %{new_name} on %{node} failed"
 msgid "Rename site %{name} to %{new_name} on %{node} failed"
 msgstr ""
 msgstr ""
 "2] üzerinde %{orig_path}'ı %{new_path} olarak başarıyla yeniden adlandırın"
 "2] üzerinde %{orig_path}'ı %{new_path} olarak başarıyla yeniden adlandırın"
 
 
-#: src/components/Notification/notifications.ts:82
+#: src/components/Notification/notifications.ts:100
 #, fuzzy
 #, fuzzy
 msgid "Rename site %{name} to %{new_name} on %{node} successfully"
 msgid "Rename site %{name} to %{new_name} on %{node} successfully"
 msgstr ""
 msgstr ""
 "2] üzerinde %{orig_path}'ı %{new_path} olarak başarıyla yeniden adlandırın"
 "2] üzerinde %{orig_path}'ı %{new_path} olarak başarıyla yeniden adlandırın"
 
 
-#: src/components/Notification/notifications.ts:120
+#: src/components/Notification/notifications.ts:138
 #, fuzzy
 #, fuzzy
 msgid "Rename stream %{name} to %{new_name} on %{node} failed"
 msgid "Rename stream %{name} to %{new_name} on %{node} failed"
 msgstr ""
 msgstr ""
 "2] üzerinde %{orig_path}'ı %{new_path} olarak başarıyla yeniden adlandırın"
 "2] üzerinde %{orig_path}'ı %{new_path} olarak başarıyla yeniden adlandırın"
 
 
-#: src/components/Notification/notifications.ts:124
+#: src/components/Notification/notifications.ts:142
 #, fuzzy
 #, fuzzy
 msgid "Rename stream %{name} to %{new_name} on %{node} successfully"
 msgid "Rename stream %{name} to %{new_name} on %{node} successfully"
 msgstr ""
 msgstr ""
@@ -3125,24 +3172,24 @@ msgstr "Yeniden başlat"
 msgid "Restart Nginx"
 msgid "Restart Nginx"
 msgstr "Yeniden Başlatma"
 msgstr "Yeniden Başlatma"
 
 
-#: src/components/Notification/notifications.ts:152
+#: src/components/Notification/notifications.ts:18
 #, fuzzy
 #, fuzzy
 msgid "Restart Nginx on %{node} failed, response: %{resp}"
 msgid "Restart Nginx on %{node} failed, response: %{resp}"
 msgstr ""
 msgstr ""
 "%{conf_name} yapılandırmasını %{node_name} düğümünde etkinleştirme başarılı "
 "%{conf_name} yapılandırmasını %{node_name} düğümünde etkinleştirme başarılı "
 "oldu"
 "oldu"
 
 
-#: src/components/Notification/notifications.ts:156
+#: src/components/Notification/notifications.ts:22
 #, fuzzy
 #, fuzzy
 msgid "Restart Nginx on %{node} successfully"
 msgid "Restart Nginx on %{node} successfully"
 msgstr "Nginx kullanıcı arayüzü %{node} üzerinde başarıyla yükseltildi 🎉"
 msgstr "Nginx kullanıcı arayüzü %{node} üzerinde başarıyla yükseltildi 🎉"
 
 
-#: src/components/Notification/notifications.ts:151
+#: src/components/Notification/notifications.ts:17
 #, fuzzy
 #, fuzzy
 msgid "Restart Remote Nginx Error"
 msgid "Restart Remote Nginx Error"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandır Hatası"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandır Hatası"
 
 
-#: src/components/Notification/notifications.ts:155
+#: src/components/Notification/notifications.ts:21
 #, fuzzy
 #, fuzzy
 msgid "Restart Remote Nginx Success"
 msgid "Restart Remote Nginx Success"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandırma Başarılı"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandırma Başarılı"
@@ -3212,7 +3259,7 @@ msgstr "Çalışıyor"
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/ConfigEditor.vue:271
 #: src/views/config/ConfigEditor.vue:271
 #: src/views/preference/components/Passkey.vue:130
 #: src/views/preference/components/Passkey.vue:130
-#: src/views/preference/Preference.vue:221
+#: src/views/preference/Preference.vue:228
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:127
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:127
 #: src/views/site/site_edit/components/ConfigName.vue:52
 #: src/views/site/site_edit/components/ConfigName.vue:52
 #: src/views/site/site_edit/SiteEdit.vue:292
 #: src/views/site/site_edit/SiteEdit.vue:292
@@ -3233,43 +3280,45 @@ msgstr "Direktifi Kaydet"
 msgid "Save error %{msg}"
 msgid "Save error %{msg}"
 msgstr "Hatayı kaydet %{msg}"
 msgstr "Hatayı kaydet %{msg}"
 
 
-#: src/components/Notification/notifications.ts:85 src/language/constants.ts:48
+#: src/components/Notification/notifications.ts:103
+#: src/language/constants.ts:48
 #, fuzzy
 #, fuzzy
 msgid "Save Remote Site Error"
 msgid "Save Remote Site Error"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandır Hatası"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandır Hatası"
 
 
-#: src/components/Notification/notifications.ts:89 src/language/constants.ts:47
+#: src/components/Notification/notifications.ts:107
+#: src/language/constants.ts:47
 #, fuzzy
 #, fuzzy
 msgid "Save Remote Site Success"
 msgid "Save Remote Site Success"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandırma Başarılı"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandırma Başarılı"
 
 
-#: src/components/Notification/notifications.ts:127
+#: src/components/Notification/notifications.ts:145
 #, fuzzy
 #, fuzzy
 msgid "Save Remote Stream Error"
 msgid "Save Remote Stream Error"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandır Hatası"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandır Hatası"
 
 
-#: src/components/Notification/notifications.ts:131
+#: src/components/Notification/notifications.ts:149
 #, fuzzy
 #, fuzzy
 msgid "Save Remote Stream Success"
 msgid "Save Remote Stream Success"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandırma Başarılı"
 msgstr "Uzak Yapılandırmayı Yeniden Adlandırma Başarılı"
 
 
-#: src/components/Notification/notifications.ts:86
+#: src/components/Notification/notifications.ts:104
 #, fuzzy
 #, fuzzy
 msgid "Save site %{name} to %{node} failed"
 msgid "Save site %{name} to %{node} failed"
 msgstr "%{conf_name} başarıyla %{node_name} düğümüne kopyalandı"
 msgstr "%{conf_name} başarıyla %{node_name} düğümüne kopyalandı"
 
 
-#: src/components/Notification/notifications.ts:90
+#: src/components/Notification/notifications.ts:108
 #, fuzzy
 #, fuzzy
 msgid "Save site %{name} to %{node} successfully"
 msgid "Save site %{name} to %{node} successfully"
 msgstr "%{conf_name} başarıyla %{node_name} düğümüne kopyalandı"
 msgstr "%{conf_name} başarıyla %{node_name} düğümüne kopyalandı"
 
 
-#: src/components/Notification/notifications.ts:128
+#: src/components/Notification/notifications.ts:146
 #, fuzzy
 #, fuzzy
 msgid "Save stream %{name} to %{node} failed"
 msgid "Save stream %{name} to %{node} failed"
 msgstr ""
 msgstr ""
 "%{conf_name} yapılandırmasını %{node_name} düğümüne dağıtma başarısız oldu"
 "%{conf_name} yapılandırmasını %{node_name} düğümüne dağıtma başarısız oldu"
 
 
-#: src/components/Notification/notifications.ts:132
+#: src/components/Notification/notifications.ts:150
 #, fuzzy
 #, fuzzy
 msgid "Save stream %{name} to %{node} successfully"
 msgid "Save stream %{name} to %{node} successfully"
 msgstr "%{conf_name} başarıyla %{node_name} düğümüne kopyalandı"
 msgstr "%{conf_name} başarıyla %{node_name} düğümüne kopyalandı"
@@ -3277,7 +3326,7 @@ msgstr "%{conf_name} başarıyla %{node_name} düğümüne kopyalandı"
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:47
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:47
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:97
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:97
 #: src/views/certificate/CertificateEditor.vue:49
 #: src/views/certificate/CertificateEditor.vue:49
-#: src/views/preference/Preference.vue:123
+#: src/views/preference/Preference.vue:124
 #, fuzzy
 #, fuzzy
 msgid "Save successfully"
 msgid "Save successfully"
 msgstr "Başarıyla kaydedin"
 msgstr "Başarıyla kaydedin"
@@ -3301,6 +3350,10 @@ msgstr "Hesabı uygulamaya eklemek için QR kodunu cep telefonunuzla tarayın."
 msgid "SDK"
 msgid "SDK"
 msgstr "SDK"
 msgstr "SDK"
 
 
+#: src/views/preference/components/ExternalNotify/dingtalk.ts:13
+msgid "Secret (Optional)"
+msgstr ""
+
 #: src/views/preference/components/TOTP.vue:109
 #: src/views/preference/components/TOTP.vue:109
 #, fuzzy
 #, fuzzy
 msgid "Secret has been copied"
 msgid "Secret has been copied"
@@ -3335,7 +3388,7 @@ msgstr ""
 msgid "Send"
 msgid "Send"
 msgstr "Gönder"
 msgstr "Gönder"
 
 
-#: src/views/preference/Preference.vue:156
+#: src/views/preference/Preference.vue:157
 #, fuzzy
 #, fuzzy
 msgid "Server"
 msgid "Server"
 msgstr "Sunucu Bilgisi"
 msgstr "Sunucu Bilgisi"
@@ -3345,6 +3398,11 @@ msgstr "Sunucu Bilgisi"
 msgid "Server Info"
 msgid "Server Info"
 msgstr "Sunucu Bilgisi"
 msgstr "Sunucu Bilgisi"
 
 
+#: src/views/preference/components/ExternalNotify/bark.ts:13
+#, fuzzy
+msgid "Server URL"
+msgstr "Sunucu Bilgisi"
+
 #: src/views/site/cert/components/ObtainCert.vue:107
 #: src/views/site/cert/components/ObtainCert.vue:107
 #, fuzzy
 #, fuzzy
 msgid "server_name not found in directives"
 msgid "server_name not found in directives"
@@ -3535,7 +3593,7 @@ msgstr ""
 #: src/views/certificate/ACMEUser.vue:65
 #: src/views/certificate/ACMEUser.vue:65
 #: src/views/certificate/CertificateList/certColumns.tsx:65
 #: src/views/certificate/CertificateList/certColumns.tsx:65
 #: src/views/environments/list/envColumns.tsx:44
 #: src/views/environments/list/envColumns.tsx:44
-#: src/views/site/site_edit/RightSettings.vue:56
+#: src/views/site/site_edit/RightSettings.vue:55
 #: src/views/site/site_list/columns.tsx:80 src/views/stream/StreamList.vue:47
 #: src/views/site/site_list/columns.tsx:80 src/views/stream/StreamList.vue:47
 #, fuzzy
 #, fuzzy
 msgid "Status"
 msgid "Status"
@@ -3620,42 +3678,42 @@ msgstr "Eşitle"
 msgid "Sync Certificate"
 msgid "Sync Certificate"
 msgstr "Senkronizasyon Sertifikası"
 msgstr "Senkronizasyon Sertifikası"
 
 
-#: src/components/Notification/notifications.ts:10
+#: src/components/Notification/notifications.ts:28
 #, fuzzy
 #, fuzzy
 msgid "Sync Certificate %{cert_name} to %{env_name} failed"
 msgid "Sync Certificate %{cert_name} to %{env_name} failed"
 msgstr "Sertifika %{cert_name}'ı %{env_name} ile başarıyla senkronize edin"
 msgstr "Sertifika %{cert_name}'ı %{env_name} ile başarıyla senkronize edin"
 
 
-#: src/components/Notification/notifications.ts:14
+#: src/components/Notification/notifications.ts:32
 #, fuzzy
 #, fuzzy
 msgid "Sync Certificate %{cert_name} to %{env_name} successfully"
 msgid "Sync Certificate %{cert_name} to %{env_name} successfully"
 msgstr "Sertifika %{cert_name}'ı %{env_name} ile başarıyla senkronize edin"
 msgstr "Sertifika %{cert_name}'ı %{env_name} ile başarıyla senkronize edin"
 
 
-#: src/components/Notification/notifications.ts:9 src/language/constants.ts:39
+#: src/components/Notification/notifications.ts:27 src/language/constants.ts:39
 #, fuzzy
 #, fuzzy
 msgid "Sync Certificate Error"
 msgid "Sync Certificate Error"
 msgstr "Senkronizasyon Sertifikası Hatası"
 msgstr "Senkronizasyon Sertifikası Hatası"
 
 
-#: src/components/Notification/notifications.ts:13 src/language/constants.ts:38
+#: src/components/Notification/notifications.ts:31 src/language/constants.ts:38
 #, fuzzy
 #, fuzzy
 msgid "Sync Certificate Success"
 msgid "Sync Certificate Success"
 msgstr "Senkronizasyon Sertifikası Başarısı"
 msgstr "Senkronizasyon Sertifikası Başarısı"
 
 
-#: src/components/Notification/notifications.ts:20
+#: src/components/Notification/notifications.ts:38
 #, fuzzy
 #, fuzzy
 msgid "Sync config %{config_name} to %{env_name} failed"
 msgid "Sync config %{config_name} to %{env_name} failed"
 msgstr "Config %{config_name} ile %{env_name}'i başarıyla senkronize edin"
 msgstr "Config %{config_name} ile %{env_name}'i başarıyla senkronize edin"
 
 
-#: src/components/Notification/notifications.ts:24
+#: src/components/Notification/notifications.ts:42
 #, fuzzy
 #, fuzzy
 msgid "Sync config %{config_name} to %{env_name} successfully"
 msgid "Sync config %{config_name} to %{env_name} successfully"
 msgstr "Config %{config_name} ile %{env_name}'i başarıyla senkronize edin"
 msgstr "Config %{config_name} ile %{env_name}'i başarıyla senkronize edin"
 
 
-#: src/components/Notification/notifications.ts:19 src/language/constants.ts:45
+#: src/components/Notification/notifications.ts:37 src/language/constants.ts:45
 #, fuzzy
 #, fuzzy
 msgid "Sync Config Error"
 msgid "Sync Config Error"
 msgstr "Senkronizasyon Yapılandırma Hatası"
 msgstr "Senkronizasyon Yapılandırma Hatası"
 
 
-#: src/components/Notification/notifications.ts:23 src/language/constants.ts:44
+#: src/components/Notification/notifications.ts:41 src/language/constants.ts:44
 #, fuzzy
 #, fuzzy
 msgid "Sync Config Success"
 msgid "Sync Config Success"
 msgstr "Senkronizasyon Yapılandırması Başarılı"
 msgstr "Senkronizasyon Yapılandırması Başarılı"
@@ -3666,8 +3724,8 @@ msgstr "Senkronizasyon Yapılandırması Başarılı"
 msgid "Sync Nodes"
 msgid "Sync Nodes"
 msgstr "Şununla senkronize et"
 msgstr "Şununla senkronize et"
 
 
-#: src/views/site/site_edit/RightSettings.vue:102
-#: src/views/site/site_edit/RightSettings.vue:89
+#: src/views/site/site_edit/RightSettings.vue:101
+#: src/views/site/site_edit/RightSettings.vue:88
 #: src/views/stream/components/RightSettings.vue:111
 #: src/views/stream/components/RightSettings.vue:111
 #: src/views/stream/components/RightSettings.vue:124
 #: src/views/stream/components/RightSettings.vue:124
 #, fuzzy
 #, fuzzy
@@ -3679,7 +3737,7 @@ msgstr "Senkronizasyon Sertifikası"
 msgid "Sync to"
 msgid "Sync to"
 msgstr "Şununla senkronize et"
 msgstr "Şununla senkronize et"
 
 
-#: src/views/site/site_edit/RightSettings.vue:86
+#: src/views/site/site_edit/RightSettings.vue:85
 #: src/views/stream/components/RightSettings.vue:108
 #: src/views/stream/components/RightSettings.vue:108
 msgid "Synchronization"
 msgid "Synchronization"
 msgstr ""
 msgstr ""
@@ -3714,7 +3772,11 @@ msgstr "Nginx başarıyla yeniden başlatıldı"
 msgid "Task not found"
 msgid "Task not found"
 msgstr "Dosya bulunamadı"
 msgstr "Dosya bulunamadı"
 
 
-#: src/routes/modules/terminal.ts:10 src/views/preference/Preference.vue:180
+#: src/views/preference/components/ExternalNotify/telegram.ts:5
+msgid "Telegram"
+msgstr ""
+
+#: src/routes/modules/terminal.ts:10 src/views/preference/Preference.vue:187
 #: src/views/terminal/Terminal.vue:129
 #: src/views/terminal/Terminal.vue:129
 #, fuzzy
 #, fuzzy
 msgid "Terminal"
 msgid "Terminal"
@@ -4018,6 +4080,7 @@ msgstr "İki faktörlü kimlik doğrulama gerekiyor"
 #: src/views/certificate/CertificateList/certColumns.tsx:25
 #: src/views/certificate/CertificateList/certColumns.tsx:25
 #: src/views/nginx_log/NginxLogList.vue:21
 #: src/views/nginx_log/NginxLogList.vue:21
 #: src/views/notification/notificationColumns.tsx:9
 #: src/views/notification/notificationColumns.tsx:9
+#: src/views/preference/components/ExternalNotify/columns.ts:17
 #, fuzzy
 #, fuzzy
 msgid "Type"
 msgid "Type"
 msgstr "Tip"
 msgstr "Tip"
@@ -4036,7 +4099,7 @@ msgstr "Güncellendi"
 #: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:325
 #: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:325
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/environments/list/envColumns.tsx:90
-#: src/views/site/site_edit/RightSettings.vue:76
+#: src/views/site/site_edit/RightSettings.vue:75
 #: src/views/site/site_list/columns.tsx:110
 #: src/views/site/site_list/columns.tsx:110
 #: src/views/stream/components/RightSettings.vue:99
 #: src/views/stream/components/RightSettings.vue:99
 #: src/views/stream/StreamList.vue:67 src/views/user/userColumns.tsx:54
 #: src/views/stream/StreamList.vue:67 src/views/user/userColumns.tsx:54
@@ -4225,7 +4288,7 @@ msgstr ""
 "yeniden kaydeder. Genel olarak, bir geliştirme ortamında değilseniz ve CA "
 "yeniden kaydeder. Genel olarak, bir geliştirme ortamında değilseniz ve CA "
 "olarak Pebble kullanmıyorsanız bunu etkinleştirmeyin."
 "olarak Pebble kullanmıyorsanız bunu etkinleştirmeyin."
 
 
-#: src/views/site/site_edit/RightSettings.vue:92
+#: src/views/site/site_edit/RightSettings.vue:91
 msgid ""
 msgid ""
 "When you enable/disable, delete, or save this site, the nodes set in the "
 "When you enable/disable, delete, or save this site, the nodes set in the "
 "Node Group and the nodes selected below will be synchronized."
 "Node Group and the nodes selected below will be synchronized."

+ 164 - 102
app/src/language/vi_VN/app.po

@@ -30,6 +30,11 @@ msgstr "Log truy cập"
 msgid "Access Logs"
 msgid "Access Logs"
 msgstr "Log truy cập"
 msgstr "Log truy cập"
 
 
+#: src/views/preference/components/ExternalNotify/dingtalk.ts:9
+#, fuzzy
+msgid "Access Token"
+msgstr "Log truy cập"
+
 #: src/routes/modules/certificates.ts:20 src/views/certificate/ACMEUser.vue:113
 #: src/routes/modules/certificates.ts:20 src/views/certificate/ACMEUser.vue:113
 #: src/views/certificate/ACMEUserSelector.vue:85
 #: src/views/certificate/ACMEUserSelector.vue:85
 #, fuzzy
 #, fuzzy
@@ -45,6 +50,7 @@ msgstr "Người dùng"
 #: src/views/nginx_log/NginxLogList.vue:53
 #: src/views/nginx_log/NginxLogList.vue:53
 #: src/views/notification/notificationColumns.tsx:66
 #: src/views/notification/notificationColumns.tsx:66
 #: src/views/preference/AuthSettings.vue:30
 #: src/views/preference/AuthSettings.vue:30
+#: src/views/preference/components/ExternalNotify/columns.ts:46
 #: src/views/site/site_list/columns.tsx:117 src/views/stream/StreamList.vue:74
 #: src/views/site/site_list/columns.tsx:117 src/views/stream/StreamList.vue:74
 #: src/views/user/userColumns.tsx:60
 #: src/views/user/userColumns.tsx:60
 msgid "Action"
 msgid "Action"
@@ -113,7 +119,7 @@ msgstr ""
 msgid "All"
 msgid "All"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:137
+#: src/components/Notification/notifications.ts:155
 #: src/language/constants.ts:58
 #: src/language/constants.ts:58
 msgid "All Recovery Codes Have Been Used"
 msgid "All Recovery Codes Have Been Used"
 msgstr ""
 msgstr ""
@@ -139,7 +145,7 @@ msgstr ""
 msgid "API Type"
 msgid "API Type"
 msgstr "Loại"
 msgstr "Loại"
 
 
-#: src/views/preference/Preference.vue:162
+#: src/views/preference/Preference.vue:163
 msgid "App"
 msgid "App"
 msgstr ""
 msgstr ""
 
 
@@ -202,7 +208,7 @@ msgstr "Bạn chắc chắn muốn xóa nó "
 msgid "Are you sure you want to delete this item?"
 msgid "Are you sure you want to delete this item?"
 msgstr "Bạn chắc chắn muốn xóa nó "
 msgstr "Bạn chắc chắn muốn xóa nó "
 
 
-#: src/views/site/site_list/SiteList.vue:163
+#: src/views/site/site_list/SiteList.vue:167
 #: src/views/stream/StreamList.vue:227
 #: src/views/stream/StreamList.vue:227
 #, fuzzy
 #, fuzzy
 msgid "Are you sure you want to delete?"
 msgid "Are you sure you want to delete?"
@@ -253,7 +259,7 @@ msgstr ""
 msgid "Attempts"
 msgid "Attempts"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/Preference.vue:186
+#: src/views/preference/Preference.vue:193
 #, fuzzy
 #, fuzzy
 msgid "Auth"
 msgid "Auth"
 msgstr "Tác giả"
 msgstr "Tác giả"
@@ -339,12 +345,16 @@ msgstr ""
 msgid "Banned Until"
 msgid "Banned Until"
 msgstr ""
 msgstr ""
 
 
+#: src/views/preference/components/ExternalNotify/bark.ts:5
+msgid "Bark"
+msgstr ""
+
 #: src/views/site/site_add/SiteAdd.vue:95
 #: src/views/site/site_add/SiteAdd.vue:95
 msgid "Base information"
 msgid "Base information"
 msgstr "Thông tin"
 msgstr "Thông tin"
 
 
 #: src/views/config/ConfigEditor.vue:290
 #: src/views/config/ConfigEditor.vue:290
-#: src/views/site/site_edit/RightSettings.vue:53
+#: src/views/site/site_edit/RightSettings.vue:52
 #: src/views/stream/components/RightSettings.vue:79
 #: src/views/stream/components/RightSettings.vue:79
 #, fuzzy
 #, fuzzy
 msgid "Basic"
 msgid "Basic"
@@ -379,6 +389,10 @@ msgstr ""
 msgid "Block is nil"
 msgid "Block is nil"
 msgstr ""
 msgstr ""
 
 
+#: src/views/preference/components/ExternalNotify/telegram.ts:9
+msgid "Bot Token"
+msgstr ""
+
 #: src/views/system/About.vue:55
 #: src/views/system/About.vue:55
 msgid "Build with"
 msgid "Build with"
 msgstr "Xây dựng với"
 msgstr "Xây dựng với"
@@ -419,7 +433,7 @@ msgstr ""
 msgid "Cannot remove initial user"
 msgid "Cannot remove initial user"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/Preference.vue:192
+#: src/views/preference/Preference.vue:199
 #, fuzzy
 #, fuzzy
 msgid "Cert"
 msgid "Cert"
 msgstr "Tự động ký chứng chỉ SSL"
 msgstr "Tự động ký chứng chỉ SSL"
@@ -499,6 +513,10 @@ msgstr "Thay đổi chứng chỉ"
 msgid "Channel"
 msgid "Channel"
 msgstr "Kênh"
 msgstr "Kênh"
 
 
+#: src/views/preference/components/ExternalNotify/telegram.ts:13
+msgid "Chat ID"
+msgstr ""
+
 #: src/views/system/Upgrade.vue:185
 #: src/views/system/Upgrade.vue:185
 msgid "Check again"
 msgid "Check again"
 msgstr "Kiểm tra lại"
 msgstr "Kiểm tra lại"
@@ -699,6 +717,7 @@ msgstr ""
 
 
 #: src/views/environments/group/columns.ts:31
 #: src/views/environments/group/columns.ts:31
 #: src/views/notification/notificationColumns.tsx:59
 #: src/views/notification/notificationColumns.tsx:59
+#: src/views/preference/components/ExternalNotify/columns.ts:41
 #: src/views/preference/components/Passkey.vue:95
 #: src/views/preference/components/Passkey.vue:95
 #: src/views/user/userColumns.tsx:48
 #: src/views/user/userColumns.tsx:48
 msgid "Created at"
 msgid "Created at"
@@ -771,7 +790,7 @@ msgstr "Mô tả"
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/views/site/ngx_conf/NgxServer.vue:110
 #: src/views/site/ngx_conf/NgxServer.vue:110
 #: src/views/site/ngx_conf/NgxUpstream.vue:128
 #: src/views/site/ngx_conf/NgxUpstream.vue:128
-#: src/views/site/site_list/SiteList.vue:172
+#: src/views/site/site_list/SiteList.vue:176
 #: src/views/stream/StreamList.vue:236
 #: src/views/stream/StreamList.vue:236
 msgid "Delete"
 msgid "Delete"
 msgstr "Xoá"
 msgstr "Xoá"
@@ -781,46 +800,46 @@ msgstr "Xoá"
 msgid "Delete Permanently"
 msgid "Delete Permanently"
 msgstr ""
 msgstr ""
 
 
-#: src/components/Notification/notifications.ts:37 src/language/constants.ts:50
+#: src/components/Notification/notifications.ts:55 src/language/constants.ts:50
 #, fuzzy
 #, fuzzy
 msgid "Delete Remote Site Error"
 msgid "Delete Remote Site Error"
 msgstr "Gia hạn chứng chỉ SSL thất bại"
 msgstr "Gia hạn chứng chỉ SSL thất bại"
 
 
-#: src/components/Notification/notifications.ts:41 src/language/constants.ts:49
+#: src/components/Notification/notifications.ts:59 src/language/constants.ts:49
 #, fuzzy
 #, fuzzy
 msgid "Delete Remote Site Success"
 msgid "Delete Remote Site Success"
 msgstr "Gia hạn chứng chỉ SSL thành công"
 msgstr "Gia hạn chứng chỉ SSL thành công"
 
 
-#: src/components/Notification/notifications.ts:95
+#: src/components/Notification/notifications.ts:113
 #, fuzzy
 #, fuzzy
 msgid "Delete Remote Stream Error"
 msgid "Delete Remote Stream Error"
 msgstr "Gia hạn chứng chỉ SSL thất bại"
 msgstr "Gia hạn chứng chỉ SSL thất bại"
 
 
-#: src/components/Notification/notifications.ts:99
+#: src/components/Notification/notifications.ts:117
 #, fuzzy
 #, fuzzy
 msgid "Delete Remote Stream Success"
 msgid "Delete Remote Stream Success"
 msgstr "Gia hạn chứng chỉ SSL thành công"
 msgstr "Gia hạn chứng chỉ SSL thành công"
 
 
-#: src/components/Notification/notifications.ts:38
+#: src/components/Notification/notifications.ts:56
 #, fuzzy
 #, fuzzy
 msgid "Delete site %{name} from %{node} failed"
 msgid "Delete site %{name} from %{node} failed"
 msgstr "Triển khai %{conf_name} tới %{node_name} thất bại"
 msgstr "Triển khai %{conf_name} tới %{node_name} thất bại"
 
 
-#: src/components/Notification/notifications.ts:42
+#: src/components/Notification/notifications.ts:60
 #, fuzzy
 #, fuzzy
 msgid "Delete site %{name} from %{node} successfully"
 msgid "Delete site %{name} from %{node} successfully"
 msgstr "Nhân bản %{conf_name} thành %{node_name} thành công"
 msgstr "Nhân bản %{conf_name} thành %{node_name} thành công"
 
 
-#: src/views/site/site_list/SiteList.vue:94
+#: src/views/site/site_list/SiteList.vue:98
 msgid "Delete site: %{site_name}"
 msgid "Delete site: %{site_name}"
 msgstr "Xoá trang web: %{site_name}"
 msgstr "Xoá trang web: %{site_name}"
 
 
-#: src/components/Notification/notifications.ts:96
+#: src/components/Notification/notifications.ts:114
 #, fuzzy
 #, fuzzy
 msgid "Delete stream %{name} from %{node} failed"
 msgid "Delete stream %{name} from %{node} failed"
 msgstr "Triển khai %{conf_name} tới %{node_name} thất bại"
 msgstr "Triển khai %{conf_name} tới %{node_name} thất bại"
 
 
-#: src/components/Notification/notifications.ts:100
+#: src/components/Notification/notifications.ts:118
 #, fuzzy
 #, fuzzy
 msgid "Delete stream %{name} from %{node} successfully"
 msgid "Delete stream %{name} from %{node} successfully"
 msgstr "Nhân bản %{conf_name} thành %{node_name} thành công"
 msgstr "Nhân bản %{conf_name} thành %{node_name} thành công"
@@ -860,6 +879,14 @@ msgstr "Chi tiết"
 msgid "Development Mode"
 msgid "Development Mode"
 msgstr "Chế độ phát triển"
 msgstr "Chế độ phát triển"
 
 
+#: src/views/preference/components/ExternalNotify/bark.ts:9
+msgid "Device Key"
+msgstr ""
+
+#: src/views/preference/components/ExternalNotify/dingtalk.ts:5
+msgid "DingTalk"
+msgstr ""
+
 #: src/views/site/ngx_conf/directive/DirectiveAdd.vue:89
 #: src/views/site/ngx_conf/directive/DirectiveAdd.vue:89
 msgid "Directive"
 msgid "Directive"
 msgstr "Directive"
 msgstr "Directive"
@@ -894,62 +921,62 @@ msgstr "Tắt"
 msgid "Disable auto-renewal failed for %{name}"
 msgid "Disable auto-renewal failed for %{name}"
 msgstr "Tắt tự động gia hạn SSL cho %{name} thất bại"
 msgstr "Tắt tự động gia hạn SSL cho %{name} thất bại"
 
 
-#: src/components/Notification/notifications.ts:45 src/language/constants.ts:52
+#: src/components/Notification/notifications.ts:63 src/language/constants.ts:52
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Site Error"
 msgid "Disable Remote Site Error"
 msgstr "Gia hạn chứng chỉ SSL thất bại"
 msgstr "Gia hạn chứng chỉ SSL thất bại"
 
 
-#: src/components/Notification/notifications.ts:69
+#: src/components/Notification/notifications.ts:87
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Site Maintenance Error"
 msgid "Disable Remote Site Maintenance Error"
 msgstr "Gia hạn chứng chỉ SSL thất bại"
 msgstr "Gia hạn chứng chỉ SSL thất bại"
 
 
-#: src/components/Notification/notifications.ts:73
+#: src/components/Notification/notifications.ts:91
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Site Maintenance Success"
 msgid "Disable Remote Site Maintenance Success"
 msgstr "Gia hạn chứng chỉ SSL thành công"
 msgstr "Gia hạn chứng chỉ SSL thành công"
 
 
-#: src/components/Notification/notifications.ts:49 src/language/constants.ts:51
+#: src/components/Notification/notifications.ts:67 src/language/constants.ts:51
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Site Success"
 msgid "Disable Remote Site Success"
 msgstr "Gia hạn chứng chỉ SSL thành công"
 msgstr "Gia hạn chứng chỉ SSL thành công"
 
 
-#: src/components/Notification/notifications.ts:103
+#: src/components/Notification/notifications.ts:121
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Stream Error"
 msgid "Disable Remote Stream Error"
 msgstr "Gia hạn chứng chỉ SSL thất bại"
 msgstr "Gia hạn chứng chỉ SSL thất bại"
 
 
-#: src/components/Notification/notifications.ts:107
+#: src/components/Notification/notifications.ts:125
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Stream Success"
 msgid "Disable Remote Stream Success"
 msgstr "Gia hạn chứng chỉ SSL thành công"
 msgstr "Gia hạn chứng chỉ SSL thành công"
 
 
-#: src/components/Notification/notifications.ts:46
+#: src/components/Notification/notifications.ts:64
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} from %{node} failed"
 msgid "Disable site %{name} from %{node} failed"
 msgstr "Đã bật %{conf_name} trên %{node_name}"
 msgstr "Đã bật %{conf_name} trên %{node_name}"
 
 
-#: src/components/Notification/notifications.ts:50
+#: src/components/Notification/notifications.ts:68
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} from %{node} successfully"
 msgid "Disable site %{name} from %{node} successfully"
 msgstr "Đã bật %{conf_name} trên %{node_name}"
 msgstr "Đã bật %{conf_name} trên %{node_name}"
 
 
-#: src/components/Notification/notifications.ts:70
+#: src/components/Notification/notifications.ts:88
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} maintenance on %{node} failed"
 msgid "Disable site %{name} maintenance on %{node} failed"
 msgstr "Đã bật %{conf_name} trên %{node_name}"
 msgstr "Đã bật %{conf_name} trên %{node_name}"
 
 
-#: src/components/Notification/notifications.ts:74
+#: src/components/Notification/notifications.ts:92
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} maintenance on %{node} successfully"
 msgid "Disable site %{name} maintenance on %{node} successfully"
 msgstr "Đã bật %{conf_name} trên %{node_name}"
 msgstr "Đã bật %{conf_name} trên %{node_name}"
 
 
-#: src/components/Notification/notifications.ts:104
+#: src/components/Notification/notifications.ts:122
 #, fuzzy
 #, fuzzy
 msgid "Disable stream %{name} from %{node} failed"
 msgid "Disable stream %{name} from %{node} failed"
 msgstr "Không thể bật %{conf_name} trên %{node_name}"
 msgstr "Không thể bật %{conf_name} trên %{node_name}"
 
 
-#: src/components/Notification/notifications.ts:108
+#: src/components/Notification/notifications.ts:126
 #, fuzzy
 #, fuzzy
 msgid "Disable stream %{name} from %{node} successfully"
 msgid "Disable stream %{name} from %{node} successfully"
 msgstr "Đã bật %{conf_name} trên %{node_name}"
 msgstr "Đã bật %{conf_name} trên %{node_name}"
@@ -1066,7 +1093,7 @@ msgid ""
 msgstr ""
 msgstr ""
 
 
 #: src/views/site/site_list/SiteDuplicate.vue:72
 #: src/views/site/site_list/SiteDuplicate.vue:72
-#: src/views/site/site_list/SiteList.vue:158
+#: src/views/site/site_list/SiteList.vue:162
 #: src/views/stream/components/StreamDuplicate.vue:64
 #: src/views/stream/components/StreamDuplicate.vue:64
 #: src/views/stream/StreamList.vue:222
 #: src/views/stream/StreamList.vue:222
 msgid "Duplicate"
 msgid "Duplicate"
@@ -1139,62 +1166,62 @@ msgstr "Bật không thành công"
 msgid "Enable HTTPS"
 msgid "Enable HTTPS"
 msgstr "Bật TLS"
 msgstr "Bật TLS"
 
 
-#: src/components/Notification/notifications.ts:53 src/language/constants.ts:54
+#: src/components/Notification/notifications.ts:71 src/language/constants.ts:54
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Site Error"
 msgid "Enable Remote Site Error"
 msgstr "Gia hạn chứng chỉ SSL thất bại"
 msgstr "Gia hạn chứng chỉ SSL thất bại"
 
 
-#: src/components/Notification/notifications.ts:61
+#: src/components/Notification/notifications.ts:79
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Site Maintenance Error"
 msgid "Enable Remote Site Maintenance Error"
 msgstr "Gia hạn chứng chỉ SSL thất bại"
 msgstr "Gia hạn chứng chỉ SSL thất bại"
 
 
-#: src/components/Notification/notifications.ts:65
+#: src/components/Notification/notifications.ts:83
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Site Maintenance Success"
 msgid "Enable Remote Site Maintenance Success"
 msgstr "Gia hạn chứng chỉ SSL thành công"
 msgstr "Gia hạn chứng chỉ SSL thành công"
 
 
-#: src/components/Notification/notifications.ts:57 src/language/constants.ts:53
+#: src/components/Notification/notifications.ts:75 src/language/constants.ts:53
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Site Success"
 msgid "Enable Remote Site Success"
 msgstr "Gia hạn chứng chỉ SSL thành công"
 msgstr "Gia hạn chứng chỉ SSL thành công"
 
 
-#: src/components/Notification/notifications.ts:111
+#: src/components/Notification/notifications.ts:129
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Stream Error"
 msgid "Enable Remote Stream Error"
 msgstr "Gia hạn chứng chỉ SSL thất bại"
 msgstr "Gia hạn chứng chỉ SSL thất bại"
 
 
-#: src/components/Notification/notifications.ts:115
+#: src/components/Notification/notifications.ts:133
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Stream Success"
 msgid "Enable Remote Stream Success"
 msgstr "Gia hạn chứng chỉ SSL thành công"
 msgstr "Gia hạn chứng chỉ SSL thành công"
 
 
-#: src/components/Notification/notifications.ts:62
+#: src/components/Notification/notifications.ts:80
 #, fuzzy
 #, fuzzy
 msgid "Enable site %{name} maintenance on %{node} failed"
 msgid "Enable site %{name} maintenance on %{node} failed"
 msgstr "Không thể bật %{conf_name} trên %{node_name}"
 msgstr "Không thể bật %{conf_name} trên %{node_name}"
 
 
-#: src/components/Notification/notifications.ts:66
+#: src/components/Notification/notifications.ts:84
 #, fuzzy
 #, fuzzy
 msgid "Enable site %{name} maintenance on %{node} successfully"
 msgid "Enable site %{name} maintenance on %{node} successfully"
 msgstr "Đã bật %{conf_name} trên %{node_name}"
 msgstr "Đã bật %{conf_name} trên %{node_name}"
 
 
-#: src/components/Notification/notifications.ts:54
+#: src/components/Notification/notifications.ts:72
 #, fuzzy
 #, fuzzy
 msgid "Enable site %{name} on %{node} failed"
 msgid "Enable site %{name} on %{node} failed"
 msgstr "Không thể bật %{conf_name} trên %{node_name}"
 msgstr "Không thể bật %{conf_name} trên %{node_name}"
 
 
-#: src/components/Notification/notifications.ts:58
+#: src/components/Notification/notifications.ts:76
 #, fuzzy
 #, fuzzy
 msgid "Enable site %{name} on %{node} successfully"
 msgid "Enable site %{name} on %{node} successfully"
 msgstr "Đã bật %{conf_name} trên %{node_name}"
 msgstr "Đã bật %{conf_name} trên %{node_name}"
 
 
-#: src/components/Notification/notifications.ts:112
+#: src/components/Notification/notifications.ts:130
 #, fuzzy
 #, fuzzy
 msgid "Enable stream %{name} on %{node} failed"
 msgid "Enable stream %{name} on %{node} failed"
 msgstr "Không thể bật %{conf_name} trên %{node_name}"
 msgstr "Không thể bật %{conf_name} trên %{node_name}"
 
 
-#: src/components/Notification/notifications.ts:116
+#: src/components/Notification/notifications.ts:134
 #, fuzzy
 #, fuzzy
 msgid "Enable stream %{name} on %{node} successfully"
 msgid "Enable stream %{name} on %{node} successfully"
 msgstr "Đã bật %{conf_name} trên %{node_name}"
 msgstr "Đã bật %{conf_name} trên %{node_name}"
@@ -1286,6 +1313,11 @@ msgstr "Ngày hết hạn: %{date}"
 msgid "Export"
 msgid "Export"
 msgstr "Xuất"
 msgstr "Xuất"
 
 
+#: src/views/preference/ExternalNotify.vue:10
+#: src/views/preference/Preference.vue:169
+msgid "External Notify"
+msgstr ""
+
 #: src/views/site/cert/components/ObtainCertLive.vue:94
 #: src/views/site/cert/components/ObtainCertLive.vue:94
 #, fuzzy
 #, fuzzy
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
@@ -1688,7 +1720,7 @@ msgstr "Trang chủ"
 msgid "Host"
 msgid "Host"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/Preference.vue:174
+#: src/views/preference/Preference.vue:181
 msgid "HTTP"
 msgid "HTTP"
 msgstr ""
 msgstr ""
 
 
@@ -1746,12 +1778,12 @@ msgid "Import Certificate"
 msgstr "Chứng chỉ"
 msgstr "Chứng chỉ"
 
 
 #: src/views/nginx_log/NginxLogList.vue:137
 #: src/views/nginx_log/NginxLogList.vue:137
-#: src/views/site/site_list/SiteList.vue:128
+#: src/views/site/site_list/SiteList.vue:132
 msgid "Indexed"
 msgid "Indexed"
 msgstr ""
 msgstr ""
 
 
 #: src/views/nginx_log/NginxLogList.vue:134
 #: src/views/nginx_log/NginxLogList.vue:134
-#: src/views/site/site_list/SiteList.vue:125
+#: src/views/site/site_list/SiteList.vue:129
 msgid "Indexing..."
 msgid "Indexing..."
 msgstr ""
 msgstr ""
 
 
@@ -1836,6 +1868,11 @@ msgstr "E-mail không chính xác!"
 msgid "Invalid folder name"
 msgid "Invalid folder name"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/notification.ts:3
+#, fuzzy
+msgid "Invalid notifier config"
+msgstr "Hợp lệ"
+
 #: src/constants/errors/user.ts:4
 #: src/constants/errors/user.ts:4
 #, fuzzy
 #, fuzzy
 msgid "Invalid otp code"
 msgid "Invalid otp code"
@@ -1900,6 +1937,10 @@ msgstr ""
 msgid "Key Type"
 msgid "Key Type"
 msgstr "Loại"
 msgstr "Loại"
 
 
+#: src/views/preference/components/ExternalNotify/columns.ts:29
+msgid "Language"
+msgstr ""
+
 #: src/views/system/Upgrade.vue:179
 #: src/views/system/Upgrade.vue:179
 msgid "Last checked at"
 msgid "Last checked at"
 msgstr "Kiểm tra lần cuối lúc"
 msgstr "Kiểm tra lần cuối lúc"
@@ -2004,7 +2045,7 @@ msgstr "Đăng nhập thành công"
 msgid "Logout successful"
 msgid "Logout successful"
 msgstr "Đã đăng xuất"
 msgstr "Đã đăng xuất"
 
 
-#: src/views/preference/Preference.vue:210
+#: src/views/preference/Preference.vue:217
 msgid "Logrotate"
 msgid "Logrotate"
 msgstr ""
 msgstr ""
 
 
@@ -2047,7 +2088,7 @@ msgstr ""
 msgid "Manage Configs"
 msgid "Manage Configs"
 msgstr "Quản lý cấu hình"
 msgstr "Quản lý cấu hình"
 
 
-#: src/routes/modules/sites.ts:10 src/views/site/site_list/SiteList.vue:121
+#: src/routes/modules/sites.ts:10 src/views/site/site_list/SiteList.vue:125
 msgid "Manage Sites"
 msgid "Manage Sites"
 msgstr "Quản lý Website"
 msgstr "Quản lý Website"
 
 
@@ -2129,7 +2170,7 @@ msgstr "Single Directive"
 #: src/views/nginx_log/NginxLogList.vue:37
 #: src/views/nginx_log/NginxLogList.vue:37
 #: src/views/preference/components/AddPasskey.vue:75
 #: src/views/preference/components/AddPasskey.vue:75
 #: src/views/site/ngx_conf/NgxUpstream.vue:177
 #: src/views/site/ngx_conf/NgxUpstream.vue:177
-#: src/views/site/site_edit/RightSettings.vue:64
+#: src/views/site/site_edit/RightSettings.vue:63
 #: src/views/site/site_list/columns.tsx:17
 #: src/views/site/site_list/columns.tsx:17
 #: src/views/site/site_list/SiteDuplicate.vue:79
 #: src/views/site/site_list/SiteDuplicate.vue:79
 #: src/views/stream/components/RightSettings.vue:87
 #: src/views/stream/components/RightSettings.vue:87
@@ -2179,7 +2220,7 @@ msgstr "Đã có phiên bản mới"
 msgid "Next"
 msgid "Next"
 msgstr "Tiếp theo"
 msgstr "Tiếp theo"
 
 
-#: src/views/preference/Preference.vue:198
+#: src/views/preference/Preference.vue:205
 msgid "Nginx"
 msgid "Nginx"
 msgstr ""
 msgstr ""
 
 
@@ -2322,7 +2363,7 @@ msgstr "Lỗi phân tích cú pháp cấu hình Nginx"
 #: src/views/preference/CertSettings.vue:73
 #: src/views/preference/CertSettings.vue:73
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:97
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:97
 #: src/views/site/ngx_conf/LocationEditor.vue:88
 #: src/views/site/ngx_conf/LocationEditor.vue:88
-#: src/views/site/site_list/SiteList.vue:161
+#: src/views/site/site_list/SiteList.vue:165
 #: src/views/stream/StreamList.vue:225
 #: src/views/stream/StreamList.vue:225
 msgid "No"
 msgid "No"
 msgstr "Không"
 msgstr "Không"
@@ -2337,12 +2378,12 @@ msgstr "Hành động"
 msgid "No records selected"
 msgid "No records selected"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/Preference.vue:168
+#: src/views/preference/Preference.vue:175
 #, fuzzy
 #, fuzzy
 msgid "Node"
 msgid "Node"
 msgstr "Username"
 msgstr "Username"
 
 
-#: src/views/site/site_edit/RightSettings.vue:67
+#: src/views/site/site_edit/RightSettings.vue:66
 #: src/views/site/site_list/columns.tsx:63
 #: src/views/site/site_list/columns.tsx:63
 #: src/views/stream/components/RightSettings.vue:90
 #: src/views/stream/components/RightSettings.vue:90
 #: src/views/stream/StreamList.vue:30
 #: src/views/stream/StreamList.vue:30
@@ -2387,7 +2428,7 @@ msgstr "Không hợp lệ trước: %{date}"
 msgid "Note"
 msgid "Note"
 msgstr "Ghi chú"
 msgstr "Ghi chú"
 
 
-#: src/views/site/site_edit/RightSettings.vue:96
+#: src/views/site/site_edit/RightSettings.vue:95
 #: src/views/stream/components/RightSettings.vue:118
 #: src/views/stream/components/RightSettings.vue:118
 msgid ""
 msgid ""
 "Note, if the configuration file include other configurations or "
 "Note, if the configuration file include other configurations or "
@@ -2405,6 +2446,11 @@ msgstr "Thông báo"
 msgid "Notifications"
 msgid "Notifications"
 msgstr "Thông báo"
 msgstr "Thông báo"
 
 
+#: src/constants/errors/notification.ts:2
+#, fuzzy
+msgid "Notifier not found"
+msgstr "Không tìm thấy tệp tin"
+
 #: src/views/site/cert/components/ObtainCert.vue:182
 #: src/views/site/cert/components/ObtainCert.vue:182
 #, fuzzy
 #, fuzzy
 msgid "Obtain certificate"
 msgid "Obtain certificate"
@@ -2448,7 +2494,7 @@ msgstr ""
 #: src/views/site/ngx_conf/NgxServer.vue:79
 #: src/views/site/ngx_conf/NgxServer.vue:79
 #: src/views/site/ngx_conf/NgxUpstream.vue:33
 #: src/views/site/ngx_conf/NgxUpstream.vue:33
 #: src/views/site/site_edit/components/SiteStatusSegmented.vue:121
 #: src/views/site/site_edit/components/SiteStatusSegmented.vue:121
-#: src/views/site/site_list/SiteList.vue:162
+#: src/views/site/site_list/SiteList.vue:166
 #: src/views/stream/components/RightSettings.vue:54
 #: src/views/stream/components/RightSettings.vue:54
 #: src/views/stream/StreamList.vue:226
 #: src/views/stream/StreamList.vue:226
 #: src/views/system/Backup/BackupCreator.vue:149
 #: src/views/system/Backup/BackupCreator.vue:149
@@ -2471,7 +2517,7 @@ msgstr "Trực tuyến"
 msgid "Only zip files are allowed"
 msgid "Only zip files are allowed"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/Preference.vue:204
+#: src/views/preference/Preference.vue:211
 msgid "OpenAI"
 msgid "OpenAI"
 msgstr ""
 msgstr ""
 
 
@@ -2614,7 +2660,7 @@ msgstr ""
 "Trước tiên, vui lòng thêm thông tin xác thực trong Chứng chỉ > Thông tin xác "
 "Trước tiên, vui lòng thêm thông tin xác thực trong Chứng chỉ > Thông tin xác "
 "thực DNS, sau đó chọn nhà cung cấp DNS"
 "thực DNS, sau đó chọn nhà cung cấp DNS"
 
 
-#: src/components/Notification/notifications.ts:138
+#: src/components/Notification/notifications.ts:156
 #: src/language/constants.ts:59
 #: src/language/constants.ts:59
 msgid ""
 msgid ""
 "Please generate new recovery codes in the preferences immediately to prevent "
 "Please generate new recovery codes in the preferences immediately to prevent "
@@ -2707,7 +2753,7 @@ msgstr "Hành động"
 msgid "Pre-release"
 msgid "Pre-release"
 msgstr ""
 msgstr ""
 
 
-#: src/routes/modules/preference.ts:10 src/views/preference/Preference.vue:151
+#: src/routes/modules/preference.ts:10 src/views/preference/Preference.vue:152
 msgid "Preference"
 msgid "Preference"
 msgstr "Cài đặt"
 msgstr "Cài đặt"
 
 
@@ -2849,22 +2895,22 @@ msgstr "Tải lại"
 msgid "Reload Nginx"
 msgid "Reload Nginx"
 msgstr "Tải lại nginx"
 msgstr "Tải lại nginx"
 
 
-#: src/components/Notification/notifications.ts:144
+#: src/components/Notification/notifications.ts:10
 #, fuzzy
 #, fuzzy
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgstr "Xoá trang web: %{site_name}"
 msgstr "Xoá trang web: %{site_name}"
 
 
-#: src/components/Notification/notifications.ts:148
+#: src/components/Notification/notifications.ts:14
 #, fuzzy
 #, fuzzy
 msgid "Reload Nginx on %{node} successfully"
 msgid "Reload Nginx on %{node} successfully"
 msgstr "Cập nhật thành công"
 msgstr "Cập nhật thành công"
 
 
-#: src/components/Notification/notifications.ts:143
+#: src/components/Notification/notifications.ts:9
 #, fuzzy
 #, fuzzy
 msgid "Reload Remote Nginx Error"
 msgid "Reload Remote Nginx Error"
 msgstr "Gia hạn chứng chỉ SSL thất bại"
 msgstr "Gia hạn chứng chỉ SSL thất bại"
 
 
-#: src/components/Notification/notifications.ts:147
+#: src/components/Notification/notifications.ts:13
 #, fuzzy
 #, fuzzy
 msgid "Reload Remote Nginx Success"
 msgid "Reload Remote Nginx Success"
 msgstr "Gia hạn chứng chỉ SSL thành công"
 msgstr "Gia hạn chứng chỉ SSL thành công"
@@ -2906,62 +2952,62 @@ msgstr "Xoá thành công"
 msgid "Rename"
 msgid "Rename"
 msgstr "Username"
 msgstr "Username"
 
 
-#: src/components/Notification/notifications.ts:28
+#: src/components/Notification/notifications.ts:46
 #, fuzzy
 #, fuzzy
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} failed"
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} failed"
 msgstr "Nhân bản %{conf_name} thành %{node_name} thành công"
 msgstr "Nhân bản %{conf_name} thành %{node_name} thành công"
 
 
-#: src/components/Notification/notifications.ts:32
+#: src/components/Notification/notifications.ts:50
 #, fuzzy
 #, fuzzy
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} successfully"
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} successfully"
 msgstr "Nhân bản %{conf_name} thành %{node_name} thành công"
 msgstr "Nhân bản %{conf_name} thành %{node_name} thành công"
 
 
-#: src/components/Notification/notifications.ts:27 src/language/constants.ts:42
+#: src/components/Notification/notifications.ts:45 src/language/constants.ts:42
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Config Error"
 msgid "Rename Remote Config Error"
 msgstr "Gia hạn chứng chỉ SSL thất bại"
 msgstr "Gia hạn chứng chỉ SSL thất bại"
 
 
-#: src/components/Notification/notifications.ts:31 src/language/constants.ts:41
+#: src/components/Notification/notifications.ts:49 src/language/constants.ts:41
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Config Success"
 msgid "Rename Remote Config Success"
 msgstr "Gia hạn chứng chỉ SSL thành công"
 msgstr "Gia hạn chứng chỉ SSL thành công"
 
 
-#: src/components/Notification/notifications.ts:77 src/language/constants.ts:56
+#: src/components/Notification/notifications.ts:95 src/language/constants.ts:56
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Site Error"
 msgid "Rename Remote Site Error"
 msgstr "Gia hạn chứng chỉ SSL thất bại"
 msgstr "Gia hạn chứng chỉ SSL thất bại"
 
 
-#: src/components/Notification/notifications.ts:81 src/language/constants.ts:55
+#: src/components/Notification/notifications.ts:99 src/language/constants.ts:55
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Site Success"
 msgid "Rename Remote Site Success"
 msgstr "Gia hạn chứng chỉ SSL thành công"
 msgstr "Gia hạn chứng chỉ SSL thành công"
 
 
-#: src/components/Notification/notifications.ts:119
+#: src/components/Notification/notifications.ts:137
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Stream Error"
 msgid "Rename Remote Stream Error"
 msgstr "Gia hạn chứng chỉ SSL thất bại"
 msgstr "Gia hạn chứng chỉ SSL thất bại"
 
 
-#: src/components/Notification/notifications.ts:123
+#: src/components/Notification/notifications.ts:141
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Stream Success"
 msgid "Rename Remote Stream Success"
 msgstr "Gia hạn chứng chỉ SSL thành công"
 msgstr "Gia hạn chứng chỉ SSL thành công"
 
 
-#: src/components/Notification/notifications.ts:78
+#: src/components/Notification/notifications.ts:96
 #, fuzzy
 #, fuzzy
 msgid "Rename site %{name} to %{new_name} on %{node} failed"
 msgid "Rename site %{name} to %{new_name} on %{node} failed"
 msgstr "Nhân bản %{conf_name} thành %{node_name} thành công"
 msgstr "Nhân bản %{conf_name} thành %{node_name} thành công"
 
 
-#: src/components/Notification/notifications.ts:82
+#: src/components/Notification/notifications.ts:100
 #, fuzzy
 #, fuzzy
 msgid "Rename site %{name} to %{new_name} on %{node} successfully"
 msgid "Rename site %{name} to %{new_name} on %{node} successfully"
 msgstr "Nhân bản %{conf_name} thành %{node_name} thành công"
 msgstr "Nhân bản %{conf_name} thành %{node_name} thành công"
 
 
-#: src/components/Notification/notifications.ts:120
+#: src/components/Notification/notifications.ts:138
 #, fuzzy
 #, fuzzy
 msgid "Rename stream %{name} to %{new_name} on %{node} failed"
 msgid "Rename stream %{name} to %{new_name} on %{node} failed"
 msgstr "Nhân bản %{conf_name} thành %{node_name} thành công"
 msgstr "Nhân bản %{conf_name} thành %{node_name} thành công"
 
 
-#: src/components/Notification/notifications.ts:124
+#: src/components/Notification/notifications.ts:142
 #, fuzzy
 #, fuzzy
 msgid "Rename stream %{name} to %{new_name} on %{node} successfully"
 msgid "Rename stream %{name} to %{new_name} on %{node} successfully"
 msgstr "Nhân bản %{conf_name} thành %{node_name} thành công"
 msgstr "Nhân bản %{conf_name} thành %{node_name} thành công"
@@ -3028,22 +3074,22 @@ msgstr "Khởi động lại"
 msgid "Restart Nginx"
 msgid "Restart Nginx"
 msgstr "Đang khởi động lại"
 msgstr "Đang khởi động lại"
 
 
-#: src/components/Notification/notifications.ts:152
+#: src/components/Notification/notifications.ts:18
 #, fuzzy
 #, fuzzy
 msgid "Restart Nginx on %{node} failed, response: %{resp}"
 msgid "Restart Nginx on %{node} failed, response: %{resp}"
 msgstr "Đã bật %{conf_name} trên %{node_name}"
 msgstr "Đã bật %{conf_name} trên %{node_name}"
 
 
-#: src/components/Notification/notifications.ts:156
+#: src/components/Notification/notifications.ts:22
 #, fuzzy
 #, fuzzy
 msgid "Restart Nginx on %{node} successfully"
 msgid "Restart Nginx on %{node} successfully"
 msgstr "Cập nhật thành công"
 msgstr "Cập nhật thành công"
 
 
-#: src/components/Notification/notifications.ts:151
+#: src/components/Notification/notifications.ts:17
 #, fuzzy
 #, fuzzy
 msgid "Restart Remote Nginx Error"
 msgid "Restart Remote Nginx Error"
 msgstr "Gia hạn chứng chỉ SSL thất bại"
 msgstr "Gia hạn chứng chỉ SSL thất bại"
 
 
-#: src/components/Notification/notifications.ts:155
+#: src/components/Notification/notifications.ts:21
 #, fuzzy
 #, fuzzy
 msgid "Restart Remote Nginx Success"
 msgid "Restart Remote Nginx Success"
 msgstr "Gia hạn chứng chỉ SSL thành công"
 msgstr "Gia hạn chứng chỉ SSL thành công"
@@ -3111,7 +3157,7 @@ msgstr "Running"
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/ConfigEditor.vue:271
 #: src/views/config/ConfigEditor.vue:271
 #: src/views/preference/components/Passkey.vue:130
 #: src/views/preference/components/Passkey.vue:130
-#: src/views/preference/Preference.vue:221
+#: src/views/preference/Preference.vue:228
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:127
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:127
 #: src/views/site/site_edit/components/ConfigName.vue:52
 #: src/views/site/site_edit/components/ConfigName.vue:52
 #: src/views/site/site_edit/SiteEdit.vue:292
 #: src/views/site/site_edit/SiteEdit.vue:292
@@ -3129,42 +3175,44 @@ msgstr "Lưu Directive"
 msgid "Save error %{msg}"
 msgid "Save error %{msg}"
 msgstr "Đã xảy ra lỗi khi lưu %{msg}"
 msgstr "Đã xảy ra lỗi khi lưu %{msg}"
 
 
-#: src/components/Notification/notifications.ts:85 src/language/constants.ts:48
+#: src/components/Notification/notifications.ts:103
+#: src/language/constants.ts:48
 #, fuzzy
 #, fuzzy
 msgid "Save Remote Site Error"
 msgid "Save Remote Site Error"
 msgstr "Gia hạn chứng chỉ SSL thất bại"
 msgstr "Gia hạn chứng chỉ SSL thất bại"
 
 
-#: src/components/Notification/notifications.ts:89 src/language/constants.ts:47
+#: src/components/Notification/notifications.ts:107
+#: src/language/constants.ts:47
 #, fuzzy
 #, fuzzy
 msgid "Save Remote Site Success"
 msgid "Save Remote Site Success"
 msgstr "Gia hạn chứng chỉ SSL thành công"
 msgstr "Gia hạn chứng chỉ SSL thành công"
 
 
-#: src/components/Notification/notifications.ts:127
+#: src/components/Notification/notifications.ts:145
 #, fuzzy
 #, fuzzy
 msgid "Save Remote Stream Error"
 msgid "Save Remote Stream Error"
 msgstr "Gia hạn chứng chỉ SSL thất bại"
 msgstr "Gia hạn chứng chỉ SSL thất bại"
 
 
-#: src/components/Notification/notifications.ts:131
+#: src/components/Notification/notifications.ts:149
 #, fuzzy
 #, fuzzy
 msgid "Save Remote Stream Success"
 msgid "Save Remote Stream Success"
 msgstr "Gia hạn chứng chỉ SSL thành công"
 msgstr "Gia hạn chứng chỉ SSL thành công"
 
 
-#: src/components/Notification/notifications.ts:86
+#: src/components/Notification/notifications.ts:104
 #, fuzzy
 #, fuzzy
 msgid "Save site %{name} to %{node} failed"
 msgid "Save site %{name} to %{node} failed"
 msgstr "Nhân bản %{conf_name} thành %{node_name} thành công"
 msgstr "Nhân bản %{conf_name} thành %{node_name} thành công"
 
 
-#: src/components/Notification/notifications.ts:90
+#: src/components/Notification/notifications.ts:108
 #, fuzzy
 #, fuzzy
 msgid "Save site %{name} to %{node} successfully"
 msgid "Save site %{name} to %{node} successfully"
 msgstr "Nhân bản %{conf_name} thành %{node_name} thành công"
 msgstr "Nhân bản %{conf_name} thành %{node_name} thành công"
 
 
-#: src/components/Notification/notifications.ts:128
+#: src/components/Notification/notifications.ts:146
 #, fuzzy
 #, fuzzy
 msgid "Save stream %{name} to %{node} failed"
 msgid "Save stream %{name} to %{node} failed"
 msgstr "Triển khai %{conf_name} tới %{node_name} thất bại"
 msgstr "Triển khai %{conf_name} tới %{node_name} thất bại"
 
 
-#: src/components/Notification/notifications.ts:132
+#: src/components/Notification/notifications.ts:150
 #, fuzzy
 #, fuzzy
 msgid "Save stream %{name} to %{node} successfully"
 msgid "Save stream %{name} to %{node} successfully"
 msgstr "Nhân bản %{conf_name} thành %{node_name} thành công"
 msgstr "Nhân bản %{conf_name} thành %{node_name} thành công"
@@ -3172,7 +3220,7 @@ msgstr "Nhân bản %{conf_name} thành %{node_name} thành công"
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:47
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:47
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:97
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:97
 #: src/views/certificate/CertificateEditor.vue:49
 #: src/views/certificate/CertificateEditor.vue:49
-#: src/views/preference/Preference.vue:123
+#: src/views/preference/Preference.vue:124
 #, fuzzy
 #, fuzzy
 msgid "Save successfully"
 msgid "Save successfully"
 msgstr "Lưu thành công"
 msgstr "Lưu thành công"
@@ -3193,6 +3241,10 @@ msgstr ""
 msgid "SDK"
 msgid "SDK"
 msgstr ""
 msgstr ""
 
 
+#: src/views/preference/components/ExternalNotify/dingtalk.ts:13
+msgid "Secret (Optional)"
+msgstr ""
+
 #: src/views/preference/components/TOTP.vue:109
 #: src/views/preference/components/TOTP.vue:109
 msgid "Secret has been copied"
 msgid "Secret has been copied"
 msgstr ""
 msgstr ""
@@ -3223,7 +3275,7 @@ msgstr ""
 msgid "Send"
 msgid "Send"
 msgstr "Gửi"
 msgstr "Gửi"
 
 
-#: src/views/preference/Preference.vue:156
+#: src/views/preference/Preference.vue:157
 #, fuzzy
 #, fuzzy
 msgid "Server"
 msgid "Server"
 msgstr "Thông tin máy chủ"
 msgstr "Thông tin máy chủ"
@@ -3232,6 +3284,11 @@ msgstr "Thông tin máy chủ"
 msgid "Server Info"
 msgid "Server Info"
 msgstr "Thông tin máy chủ"
 msgstr "Thông tin máy chủ"
 
 
+#: src/views/preference/components/ExternalNotify/bark.ts:13
+#, fuzzy
+msgid "Server URL"
+msgstr "Thông tin máy chủ"
+
 #: src/views/site/cert/components/ObtainCert.vue:107
 #: src/views/site/cert/components/ObtainCert.vue:107
 msgid "server_name not found in directives"
 msgid "server_name not found in directives"
 msgstr "không tìm thấy server_name trong directives"
 msgstr "không tìm thấy server_name trong directives"
@@ -3407,7 +3464,7 @@ msgstr ""
 #: src/views/certificate/ACMEUser.vue:65
 #: src/views/certificate/ACMEUser.vue:65
 #: src/views/certificate/CertificateList/certColumns.tsx:65
 #: src/views/certificate/CertificateList/certColumns.tsx:65
 #: src/views/environments/list/envColumns.tsx:44
 #: src/views/environments/list/envColumns.tsx:44
-#: src/views/site/site_edit/RightSettings.vue:56
+#: src/views/site/site_edit/RightSettings.vue:55
 #: src/views/site/site_list/columns.tsx:80 src/views/stream/StreamList.vue:47
 #: src/views/site/site_list/columns.tsx:80 src/views/stream/StreamList.vue:47
 msgid "Status"
 msgid "Status"
 msgstr "Trạng thái"
 msgstr "Trạng thái"
@@ -3484,42 +3541,42 @@ msgstr ""
 msgid "Sync Certificate"
 msgid "Sync Certificate"
 msgstr "Gia hạn chứng chỉ SSL"
 msgstr "Gia hạn chứng chỉ SSL"
 
 
-#: src/components/Notification/notifications.ts:10
+#: src/components/Notification/notifications.ts:28
 #, fuzzy
 #, fuzzy
 msgid "Sync Certificate %{cert_name} to %{env_name} failed"
 msgid "Sync Certificate %{cert_name} to %{env_name} failed"
 msgstr "Nhân bản %{conf_name} thành %{node_name} thành công"
 msgstr "Nhân bản %{conf_name} thành %{node_name} thành công"
 
 
-#: src/components/Notification/notifications.ts:14
+#: src/components/Notification/notifications.ts:32
 #, fuzzy
 #, fuzzy
 msgid "Sync Certificate %{cert_name} to %{env_name} successfully"
 msgid "Sync Certificate %{cert_name} to %{env_name} successfully"
 msgstr "Nhân bản %{conf_name} thành %{node_name} thành công"
 msgstr "Nhân bản %{conf_name} thành %{node_name} thành công"
 
 
-#: src/components/Notification/notifications.ts:9 src/language/constants.ts:39
+#: src/components/Notification/notifications.ts:27 src/language/constants.ts:39
 #, fuzzy
 #, fuzzy
 msgid "Sync Certificate Error"
 msgid "Sync Certificate Error"
 msgstr "Gia hạn chứng chỉ SSL thất bại"
 msgstr "Gia hạn chứng chỉ SSL thất bại"
 
 
-#: src/components/Notification/notifications.ts:13 src/language/constants.ts:38
+#: src/components/Notification/notifications.ts:31 src/language/constants.ts:38
 #, fuzzy
 #, fuzzy
 msgid "Sync Certificate Success"
 msgid "Sync Certificate Success"
 msgstr "Gia hạn chứng chỉ SSL thành công"
 msgstr "Gia hạn chứng chỉ SSL thành công"
 
 
-#: src/components/Notification/notifications.ts:20
+#: src/components/Notification/notifications.ts:38
 #, fuzzy
 #, fuzzy
 msgid "Sync config %{config_name} to %{env_name} failed"
 msgid "Sync config %{config_name} to %{env_name} failed"
 msgstr "Nhân bản %{conf_name} thành %{node_name} thành công"
 msgstr "Nhân bản %{conf_name} thành %{node_name} thành công"
 
 
-#: src/components/Notification/notifications.ts:24
+#: src/components/Notification/notifications.ts:42
 #, fuzzy
 #, fuzzy
 msgid "Sync config %{config_name} to %{env_name} successfully"
 msgid "Sync config %{config_name} to %{env_name} successfully"
 msgstr "Nhân bản %{conf_name} thành %{node_name} thành công"
 msgstr "Nhân bản %{conf_name} thành %{node_name} thành công"
 
 
-#: src/components/Notification/notifications.ts:19 src/language/constants.ts:45
+#: src/components/Notification/notifications.ts:37 src/language/constants.ts:45
 #, fuzzy
 #, fuzzy
 msgid "Sync Config Error"
 msgid "Sync Config Error"
 msgstr "Gia hạn chứng chỉ SSL thất bại"
 msgstr "Gia hạn chứng chỉ SSL thất bại"
 
 
-#: src/components/Notification/notifications.ts:23 src/language/constants.ts:44
+#: src/components/Notification/notifications.ts:41 src/language/constants.ts:44
 #, fuzzy
 #, fuzzy
 msgid "Sync Config Success"
 msgid "Sync Config Success"
 msgstr "Gia hạn chứng chỉ SSL thành công"
 msgstr "Gia hạn chứng chỉ SSL thành công"
@@ -3529,8 +3586,8 @@ msgstr "Gia hạn chứng chỉ SSL thành công"
 msgid "Sync Nodes"
 msgid "Sync Nodes"
 msgstr ""
 msgstr ""
 
 
-#: src/views/site/site_edit/RightSettings.vue:102
-#: src/views/site/site_edit/RightSettings.vue:89
+#: src/views/site/site_edit/RightSettings.vue:101
+#: src/views/site/site_edit/RightSettings.vue:88
 #: src/views/stream/components/RightSettings.vue:111
 #: src/views/stream/components/RightSettings.vue:111
 #: src/views/stream/components/RightSettings.vue:124
 #: src/views/stream/components/RightSettings.vue:124
 #, fuzzy
 #, fuzzy
@@ -3541,7 +3598,7 @@ msgstr "Gia hạn chứng chỉ SSL"
 msgid "Sync to"
 msgid "Sync to"
 msgstr ""
 msgstr ""
 
 
-#: src/views/site/site_edit/RightSettings.vue:86
+#: src/views/site/site_edit/RightSettings.vue:85
 #: src/views/stream/components/RightSettings.vue:108
 #: src/views/stream/components/RightSettings.vue:108
 msgid "Synchronization"
 msgid "Synchronization"
 msgstr ""
 msgstr ""
@@ -3574,7 +3631,11 @@ msgstr "Restart Nginx thành công"
 msgid "Task not found"
 msgid "Task not found"
 msgstr "Không tìm thấy tệp tin"
 msgstr "Không tìm thấy tệp tin"
 
 
-#: src/routes/modules/terminal.ts:10 src/views/preference/Preference.vue:180
+#: src/views/preference/components/ExternalNotify/telegram.ts:5
+msgid "Telegram"
+msgstr ""
+
+#: src/routes/modules/terminal.ts:10 src/views/preference/Preference.vue:187
 #: src/views/terminal/Terminal.vue:129
 #: src/views/terminal/Terminal.vue:129
 msgid "Terminal"
 msgid "Terminal"
 msgstr "Terminal"
 msgstr "Terminal"
@@ -3823,6 +3884,7 @@ msgstr ""
 #: src/views/certificate/CertificateList/certColumns.tsx:25
 #: src/views/certificate/CertificateList/certColumns.tsx:25
 #: src/views/nginx_log/NginxLogList.vue:21
 #: src/views/nginx_log/NginxLogList.vue:21
 #: src/views/notification/notificationColumns.tsx:9
 #: src/views/notification/notificationColumns.tsx:9
+#: src/views/preference/components/ExternalNotify/columns.ts:17
 msgid "Type"
 msgid "Type"
 msgstr "Loại"
 msgstr "Loại"
 
 
@@ -3840,7 +3902,7 @@ msgstr "Cập nhật thành công"
 #: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:325
 #: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:325
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/environments/list/envColumns.tsx:90
-#: src/views/site/site_edit/RightSettings.vue:76
+#: src/views/site/site_edit/RightSettings.vue:75
 #: src/views/site/site_list/columns.tsx:110
 #: src/views/site/site_list/columns.tsx:110
 #: src/views/stream/components/RightSettings.vue:99
 #: src/views/stream/components/RightSettings.vue:99
 #: src/views/stream/StreamList.vue:67 src/views/user/userColumns.tsx:54
 #: src/views/stream/StreamList.vue:67 src/views/user/userColumns.tsx:54
@@ -4009,7 +4071,7 @@ msgid ""
 "Pebble as CA."
 "Pebble as CA."
 msgstr ""
 msgstr ""
 
 
-#: src/views/site/site_edit/RightSettings.vue:92
+#: src/views/site/site_edit/RightSettings.vue:91
 msgid ""
 msgid ""
 "When you enable/disable, delete, or save this site, the nodes set in the "
 "When you enable/disable, delete, or save this site, the nodes set in the "
 "Node Group and the nodes selected below will be synchronized."
 "Node Group and the nodes selected below will be synchronized."

+ 161 - 106
app/src/language/zh_CN/app.po

@@ -3,7 +3,7 @@ msgid ""
 msgstr ""
 msgstr ""
 "Project-Id-Version: \n"
 "Project-Id-Version: \n"
 "POT-Creation-Date: \n"
 "POT-Creation-Date: \n"
-"PO-Revision-Date: 2025-04-08 10:49+0800\n"
+"PO-Revision-Date: 2025-04-09 17:11+0800\n"
 "Last-Translator: 0xJacky <me@jackyu.cn>\n"
 "Last-Translator: 0xJacky <me@jackyu.cn>\n"
 "Language-Team: Chinese (Simplified Han script) <https://weblate.nginxui.com/"
 "Language-Team: Chinese (Simplified Han script) <https://weblate.nginxui.com/"
 "projects/nginx-ui/frontend/zh_Hans/>\n"
 "projects/nginx-ui/frontend/zh_Hans/>\n"
@@ -35,6 +35,10 @@ msgstr "访问日志"
 msgid "Access Logs"
 msgid "Access Logs"
 msgstr "访问日志"
 msgstr "访问日志"
 
 
+#: src/views/preference/components/ExternalNotify/dingtalk.ts:9
+msgid "Access Token"
+msgstr "Access Token"
+
 #: src/routes/modules/certificates.ts:20 src/views/certificate/ACMEUser.vue:113
 #: src/routes/modules/certificates.ts:20 src/views/certificate/ACMEUser.vue:113
 #: src/views/certificate/ACMEUserSelector.vue:85
 #: src/views/certificate/ACMEUserSelector.vue:85
 msgid "ACME User"
 msgid "ACME User"
@@ -49,6 +53,7 @@ msgstr "ACME 用户"
 #: src/views/nginx_log/NginxLogList.vue:53
 #: src/views/nginx_log/NginxLogList.vue:53
 #: src/views/notification/notificationColumns.tsx:66
 #: src/views/notification/notificationColumns.tsx:66
 #: src/views/preference/AuthSettings.vue:30
 #: src/views/preference/AuthSettings.vue:30
+#: src/views/preference/components/ExternalNotify/columns.ts:46
 #: src/views/site/site_list/columns.tsx:117 src/views/stream/StreamList.vue:74
 #: src/views/site/site_list/columns.tsx:117 src/views/stream/StreamList.vue:74
 #: src/views/user/userColumns.tsx:60
 #: src/views/user/userColumns.tsx:60
 msgid "Action"
 msgid "Action"
@@ -113,7 +118,7 @@ msgstr "然后,刷新此页面并再次点击添加 Passkey。"
 msgid "All"
 msgid "All"
 msgstr "全部"
 msgstr "全部"
 
 
-#: src/components/Notification/notifications.ts:137
+#: src/components/Notification/notifications.ts:155
 #: src/language/constants.ts:58
 #: src/language/constants.ts:58
 msgid "All Recovery Codes Have Been Used"
 msgid "All Recovery Codes Have Been Used"
 msgstr "所有恢复码都已被使用"
 msgstr "所有恢复码都已被使用"
@@ -138,7 +143,7 @@ msgstr "API Token"
 msgid "API Type"
 msgid "API Type"
 msgstr "API 类型"
 msgstr "API 类型"
 
 
-#: src/views/preference/Preference.vue:162
+#: src/views/preference/Preference.vue:163
 msgid "App"
 msgid "App"
 msgstr "App"
 msgstr "App"
 
 
@@ -191,7 +196,7 @@ msgstr "您确定要永久删除此项目吗?"
 msgid "Are you sure you want to delete this item?"
 msgid "Are you sure you want to delete this item?"
 msgstr "你确定要删除这个项目吗?"
 msgstr "你确定要删除这个项目吗?"
 
 
-#: src/views/site/site_list/SiteList.vue:163
+#: src/views/site/site_list/SiteList.vue:167
 #: src/views/stream/StreamList.vue:227
 #: src/views/stream/StreamList.vue:227
 msgid "Are you sure you want to delete?"
 msgid "Are you sure you want to delete?"
 msgstr "您确定要删除吗?"
 msgstr "您确定要删除吗?"
@@ -236,7 +241,7 @@ msgstr "尝试修复"
 msgid "Attempts"
 msgid "Attempts"
 msgstr "尝试次数"
 msgstr "尝试次数"
 
 
-#: src/views/preference/Preference.vue:186
+#: src/views/preference/Preference.vue:193
 msgid "Auth"
 msgid "Auth"
 msgstr "认证"
 msgstr "认证"
 
 
@@ -317,12 +322,16 @@ msgstr "禁止 IP 列表"
 msgid "Banned Until"
 msgid "Banned Until"
 msgstr "禁用至"
 msgstr "禁用至"
 
 
+#: src/views/preference/components/ExternalNotify/bark.ts:5
+msgid "Bark"
+msgstr "Bark"
+
 #: src/views/site/site_add/SiteAdd.vue:95
 #: src/views/site/site_add/SiteAdd.vue:95
 msgid "Base information"
 msgid "Base information"
 msgstr "基本信息"
 msgstr "基本信息"
 
 
 #: src/views/config/ConfigEditor.vue:290
 #: src/views/config/ConfigEditor.vue:290
-#: src/views/site/site_edit/RightSettings.vue:53
+#: src/views/site/site_edit/RightSettings.vue:52
 #: src/views/stream/components/RightSettings.vue:79
 #: src/views/stream/components/RightSettings.vue:79
 msgid "Basic"
 msgid "Basic"
 msgstr "基本"
 msgstr "基本"
@@ -353,6 +362,10 @@ msgstr "以下是您选定的需要批量修改的项目"
 msgid "Block is nil"
 msgid "Block is nil"
 msgstr "区块为空"
 msgstr "区块为空"
 
 
+#: src/views/preference/components/ExternalNotify/telegram.ts:9
+msgid "Bot Token"
+msgstr "机器人令牌"
+
 #: src/views/system/About.vue:55
 #: src/views/system/About.vue:55
 msgid "Build with"
 msgid "Build with"
 msgstr "构建基于"
 msgstr "构建基于"
@@ -392,7 +405,7 @@ msgstr "无法比较:内容缺失"
 msgid "Cannot remove initial user"
 msgid "Cannot remove initial user"
 msgstr "不可删除初始用户"
 msgstr "不可删除初始用户"
 
 
-#: src/views/preference/Preference.vue:192
+#: src/views/preference/Preference.vue:199
 msgid "Cert"
 msgid "Cert"
 msgstr "证书"
 msgstr "证书"
 
 
@@ -458,6 +471,10 @@ msgstr "变更后的路径"
 msgid "Channel"
 msgid "Channel"
 msgstr "通道"
 msgstr "通道"
 
 
+#: src/views/preference/components/ExternalNotify/telegram.ts:13
+msgid "Chat ID"
+msgstr "聊天 ID"
+
 #: src/views/system/Upgrade.vue:185
 #: src/views/system/Upgrade.vue:185
 msgid "Check again"
 msgid "Check again"
 msgstr "重新检查"
 msgstr "重新检查"
@@ -652,6 +669,7 @@ msgstr ""
 
 
 #: src/views/environments/group/columns.ts:31
 #: src/views/environments/group/columns.ts:31
 #: src/views/notification/notificationColumns.tsx:59
 #: src/views/notification/notificationColumns.tsx:59
+#: src/views/preference/components/ExternalNotify/columns.ts:41
 #: src/views/preference/components/Passkey.vue:95
 #: src/views/preference/components/Passkey.vue:95
 #: src/views/user/userColumns.tsx:48
 #: src/views/user/userColumns.tsx:48
 msgid "Created at"
 msgid "Created at"
@@ -721,7 +739,7 @@ msgstr "解密失败"
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/views/site/ngx_conf/NgxServer.vue:110
 #: src/views/site/ngx_conf/NgxServer.vue:110
 #: src/views/site/ngx_conf/NgxUpstream.vue:128
 #: src/views/site/ngx_conf/NgxUpstream.vue:128
-#: src/views/site/site_list/SiteList.vue:172
+#: src/views/site/site_list/SiteList.vue:176
 #: src/views/stream/StreamList.vue:236
 #: src/views/stream/StreamList.vue:236
 msgid "Delete"
 msgid "Delete"
 msgstr "删除"
 msgstr "删除"
@@ -731,39 +749,39 @@ msgstr "删除"
 msgid "Delete Permanently"
 msgid "Delete Permanently"
 msgstr "彻底删除"
 msgstr "彻底删除"
 
 
-#: src/components/Notification/notifications.ts:37 src/language/constants.ts:50
+#: src/components/Notification/notifications.ts:55 src/language/constants.ts:50
 msgid "Delete Remote Site Error"
 msgid "Delete Remote Site Error"
 msgstr "删除远程站点错误"
 msgstr "删除远程站点错误"
 
 
-#: src/components/Notification/notifications.ts:41 src/language/constants.ts:49
+#: src/components/Notification/notifications.ts:59 src/language/constants.ts:49
 msgid "Delete Remote Site Success"
 msgid "Delete Remote Site Success"
 msgstr "删除远程站点成功"
 msgstr "删除远程站点成功"
 
 
-#: src/components/Notification/notifications.ts:95
+#: src/components/Notification/notifications.ts:113
 msgid "Delete Remote Stream Error"
 msgid "Delete Remote Stream Error"
 msgstr "删除远程 Stream 错误"
 msgstr "删除远程 Stream 错误"
 
 
-#: src/components/Notification/notifications.ts:99
+#: src/components/Notification/notifications.ts:117
 msgid "Delete Remote Stream Success"
 msgid "Delete Remote Stream Success"
 msgstr "删除远程 Stream 成功"
 msgstr "删除远程 Stream 成功"
 
 
-#: src/components/Notification/notifications.ts:38
+#: src/components/Notification/notifications.ts:56
 msgid "Delete site %{name} from %{node} failed"
 msgid "Delete site %{name} from %{node} failed"
 msgstr "部署 %{name} 到 %{node} 失败"
 msgstr "部署 %{name} 到 %{node} 失败"
 
 
-#: src/components/Notification/notifications.ts:42
+#: src/components/Notification/notifications.ts:60
 msgid "Delete site %{name} from %{node} successfully"
 msgid "Delete site %{name} from %{node} successfully"
 msgstr "成功从 %{node} 中删除站点 %{name}"
 msgstr "成功从 %{node} 中删除站点 %{name}"
 
 
-#: src/views/site/site_list/SiteList.vue:94
+#: src/views/site/site_list/SiteList.vue:98
 msgid "Delete site: %{site_name}"
 msgid "Delete site: %{site_name}"
 msgstr "删除站点: %{site_name}"
 msgstr "删除站点: %{site_name}"
 
 
-#: src/components/Notification/notifications.ts:96
+#: src/components/Notification/notifications.ts:114
 msgid "Delete stream %{name} from %{node} failed"
 msgid "Delete stream %{name} from %{node} failed"
 msgstr "部署 %{name} 到 %{node} 失败"
 msgstr "部署 %{name} 到 %{node} 失败"
 
 
-#: src/components/Notification/notifications.ts:100
+#: src/components/Notification/notifications.ts:118
 msgid "Delete stream %{name} from %{node} successfully"
 msgid "Delete stream %{name} from %{node} successfully"
 msgstr "成功从 %{node} 中删除站点 %{name}"
 msgstr "成功从 %{node} 中删除站点 %{name}"
 
 
@@ -800,6 +818,14 @@ msgstr "详情"
 msgid "Development Mode"
 msgid "Development Mode"
 msgstr "开发模式"
 msgstr "开发模式"
 
 
+#: src/views/preference/components/ExternalNotify/bark.ts:9
+msgid "Device Key"
+msgstr "设备密钥"
+
+#: src/views/preference/components/ExternalNotify/dingtalk.ts:5
+msgid "DingTalk"
+msgstr "钉钉"
+
 #: src/views/site/ngx_conf/directive/DirectiveAdd.vue:89
 #: src/views/site/ngx_conf/directive/DirectiveAdd.vue:89
 msgid "Directive"
 msgid "Directive"
 msgstr "指令"
 msgstr "指令"
@@ -832,51 +858,51 @@ msgstr "禁用"
 msgid "Disable auto-renewal failed for %{name}"
 msgid "Disable auto-renewal failed for %{name}"
 msgstr "关闭 %{name} 自动续签失败"
 msgstr "关闭 %{name} 自动续签失败"
 
 
-#: src/components/Notification/notifications.ts:45 src/language/constants.ts:52
+#: src/components/Notification/notifications.ts:63 src/language/constants.ts:52
 msgid "Disable Remote Site Error"
 msgid "Disable Remote Site Error"
 msgstr "禁用远程站点错误"
 msgstr "禁用远程站点错误"
 
 
-#: src/components/Notification/notifications.ts:69
+#: src/components/Notification/notifications.ts:87
 msgid "Disable Remote Site Maintenance Error"
 msgid "Disable Remote Site Maintenance Error"
 msgstr "禁用远程站点维护错误"
 msgstr "禁用远程站点维护错误"
 
 
-#: src/components/Notification/notifications.ts:73
+#: src/components/Notification/notifications.ts:91
 msgid "Disable Remote Site Maintenance Success"
 msgid "Disable Remote Site Maintenance Success"
 msgstr "禁用远程站点维护成功"
 msgstr "禁用远程站点维护成功"
 
 
-#: src/components/Notification/notifications.ts:49 src/language/constants.ts:51
+#: src/components/Notification/notifications.ts:67 src/language/constants.ts:51
 msgid "Disable Remote Site Success"
 msgid "Disable Remote Site Success"
 msgstr "禁用远程站点成功"
 msgstr "禁用远程站点成功"
 
 
-#: src/components/Notification/notifications.ts:103
+#: src/components/Notification/notifications.ts:121
 msgid "Disable Remote Stream Error"
 msgid "Disable Remote Stream Error"
 msgstr "禁用远程 Stream 错误"
 msgstr "禁用远程 Stream 错误"
 
 
-#: src/components/Notification/notifications.ts:107
+#: src/components/Notification/notifications.ts:125
 msgid "Disable Remote Stream Success"
 msgid "Disable Remote Stream Success"
 msgstr "禁用远程 Stream成功"
 msgstr "禁用远程 Stream成功"
 
 
-#: src/components/Notification/notifications.ts:46
+#: src/components/Notification/notifications.ts:64
 msgid "Disable site %{name} from %{node} failed"
 msgid "Disable site %{name} from %{node} failed"
 msgstr "在 %{node} 上禁用 %{name} 成功"
 msgstr "在 %{node} 上禁用 %{name} 成功"
 
 
-#: src/components/Notification/notifications.ts:50
+#: src/components/Notification/notifications.ts:68
 msgid "Disable site %{name} from %{node} successfully"
 msgid "Disable site %{name} from %{node} successfully"
 msgstr "在 %{node} 上禁用 %{name} 成功"
 msgstr "在 %{node} 上禁用 %{name} 成功"
 
 
-#: src/components/Notification/notifications.ts:70
+#: src/components/Notification/notifications.ts:88
 msgid "Disable site %{name} maintenance on %{node} failed"
 msgid "Disable site %{name} maintenance on %{node} failed"
 msgstr "停用站点 %{name} 维护 %{node} 失败"
 msgstr "停用站点 %{name} 维护 %{node} 失败"
 
 
-#: src/components/Notification/notifications.ts:74
+#: src/components/Notification/notifications.ts:92
 msgid "Disable site %{name} maintenance on %{node} successfully"
 msgid "Disable site %{name} maintenance on %{node} successfully"
 msgstr "成功停用站点 %{name} 上 %{node} 的维护功能"
 msgstr "成功停用站点 %{name} 上 %{node} 的维护功能"
 
 
-#: src/components/Notification/notifications.ts:104
+#: src/components/Notification/notifications.ts:122
 msgid "Disable stream %{name} from %{node} failed"
 msgid "Disable stream %{name} from %{node} failed"
 msgstr "在 %{node} 中启用 %{name} 失败"
 msgstr "在 %{node} 中启用 %{name} 失败"
 
 
-#: src/components/Notification/notifications.ts:108
+#: src/components/Notification/notifications.ts:126
 msgid "Disable stream %{name} from %{node} successfully"
 msgid "Disable stream %{name} from %{node} successfully"
 msgstr "在 %{node} 上禁用 %{name} 成功"
 msgstr "在 %{node} 上禁用 %{name} 成功"
 
 
@@ -984,7 +1010,7 @@ msgstr ""
 "使用 Passkey。"
 "使用 Passkey。"
 
 
 #: src/views/site/site_list/SiteDuplicate.vue:72
 #: src/views/site/site_list/SiteDuplicate.vue:72
-#: src/views/site/site_list/SiteList.vue:158
+#: src/views/site/site_list/SiteList.vue:162
 #: src/views/stream/components/StreamDuplicate.vue:64
 #: src/views/stream/components/StreamDuplicate.vue:64
 #: src/views/stream/StreamList.vue:222
 #: src/views/stream/StreamList.vue:222
 msgid "Duplicate"
 msgid "Duplicate"
@@ -1049,51 +1075,51 @@ msgstr "启用失败"
 msgid "Enable HTTPS"
 msgid "Enable HTTPS"
 msgstr "启用 HTTPS"
 msgstr "启用 HTTPS"
 
 
-#: src/components/Notification/notifications.ts:53 src/language/constants.ts:54
+#: src/components/Notification/notifications.ts:71 src/language/constants.ts:54
 msgid "Enable Remote Site Error"
 msgid "Enable Remote Site Error"
 msgstr "启用远程站点错误"
 msgstr "启用远程站点错误"
 
 
-#: src/components/Notification/notifications.ts:61
+#: src/components/Notification/notifications.ts:79
 msgid "Enable Remote Site Maintenance Error"
 msgid "Enable Remote Site Maintenance Error"
 msgstr "在 %{node} 上启用 %{site} 失败"
 msgstr "在 %{node} 上启用 %{site} 失败"
 
 
-#: src/components/Notification/notifications.ts:65
+#: src/components/Notification/notifications.ts:83
 msgid "Enable Remote Site Maintenance Success"
 msgid "Enable Remote Site Maintenance Success"
 msgstr "成功启用远程站点维护"
 msgstr "成功启用远程站点维护"
 
 
-#: src/components/Notification/notifications.ts:57 src/language/constants.ts:53
+#: src/components/Notification/notifications.ts:75 src/language/constants.ts:53
 msgid "Enable Remote Site Success"
 msgid "Enable Remote Site Success"
 msgstr "启用远程站点成功"
 msgstr "启用远程站点成功"
 
 
-#: src/components/Notification/notifications.ts:111
+#: src/components/Notification/notifications.ts:129
 msgid "Enable Remote Stream Error"
 msgid "Enable Remote Stream Error"
 msgstr "启用远程 Steam 错误"
 msgstr "启用远程 Steam 错误"
 
 
-#: src/components/Notification/notifications.ts:115
+#: src/components/Notification/notifications.ts:133
 msgid "Enable Remote Stream Success"
 msgid "Enable Remote Stream Success"
 msgstr "启用远程 Stream 成功"
 msgstr "启用远程 Stream 成功"
 
 
-#: src/components/Notification/notifications.ts:62
+#: src/components/Notification/notifications.ts:80
 msgid "Enable site %{name} maintenance on %{node} failed"
 msgid "Enable site %{name} maintenance on %{node} failed"
 msgstr "在 %{node} 中为 %{name} 启用维护模式失败"
 msgstr "在 %{node} 中为 %{name} 启用维护模式失败"
 
 
-#: src/components/Notification/notifications.ts:66
+#: src/components/Notification/notifications.ts:84
 msgid "Enable site %{name} maintenance on %{node} successfully"
 msgid "Enable site %{name} maintenance on %{node} successfully"
 msgstr "在 %{node} 上成功启用站点 %{name} 维护模式"
 msgstr "在 %{node} 上成功启用站点 %{name} 维护模式"
 
 
-#: src/components/Notification/notifications.ts:54
+#: src/components/Notification/notifications.ts:72
 msgid "Enable site %{name} on %{node} failed"
 msgid "Enable site %{name} on %{node} failed"
 msgstr "在 %{node} 中启用 %{name} 失败"
 msgstr "在 %{node} 中启用 %{name} 失败"
 
 
-#: src/components/Notification/notifications.ts:58
+#: src/components/Notification/notifications.ts:76
 msgid "Enable site %{name} on %{node} successfully"
 msgid "Enable site %{name} on %{node} successfully"
 msgstr "在 %{node} 上启用 %{name} 成功"
 msgstr "在 %{node} 上启用 %{name} 成功"
 
 
-#: src/components/Notification/notifications.ts:112
+#: src/components/Notification/notifications.ts:130
 msgid "Enable stream %{name} on %{node} failed"
 msgid "Enable stream %{name} on %{node} failed"
 msgstr "在 %{node} 中启用 %{name} 失败"
 msgstr "在 %{node} 中启用 %{name} 失败"
 
 
-#: src/components/Notification/notifications.ts:116
+#: src/components/Notification/notifications.ts:134
 msgid "Enable stream %{name} on %{node} successfully"
 msgid "Enable stream %{name} on %{node} successfully"
 msgstr "在 %{node} 上启用 %{name} 成功"
 msgstr "在 %{node} 上启用 %{name} 成功"
 
 
@@ -1179,6 +1205,11 @@ msgstr "过期时间: %{date}"
 msgid "Export"
 msgid "Export"
 msgstr "导出"
 msgstr "导出"
 
 
+#: src/views/preference/ExternalNotify.vue:10
+#: src/views/preference/Preference.vue:169
+msgid "External Notify"
+msgstr "外部通知"
+
 #: src/views/site/cert/components/ObtainCertLive.vue:94
 #: src/views/site/cert/components/ObtainCertLive.vue:94
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
 msgstr "获取证书失败"
 msgstr "获取证书失败"
@@ -1539,7 +1570,7 @@ msgstr "首页"
 msgid "Host"
 msgid "Host"
 msgstr "主机"
 msgstr "主机"
 
 
-#: src/views/preference/Preference.vue:174
+#: src/views/preference/Preference.vue:181
 msgid "HTTP"
 msgid "HTTP"
 msgstr "HTTP"
 msgstr "HTTP"
 
 
@@ -1598,12 +1629,12 @@ msgid "Import Certificate"
 msgstr "导入证书"
 msgstr "导入证书"
 
 
 #: src/views/nginx_log/NginxLogList.vue:137
 #: src/views/nginx_log/NginxLogList.vue:137
-#: src/views/site/site_list/SiteList.vue:128
+#: src/views/site/site_list/SiteList.vue:132
 msgid "Indexed"
 msgid "Indexed"
 msgstr "已索引"
 msgstr "已索引"
 
 
 #: src/views/nginx_log/NginxLogList.vue:134
 #: src/views/nginx_log/NginxLogList.vue:134
-#: src/views/site/site_list/SiteList.vue:125
+#: src/views/site/site_list/SiteList.vue:129
 msgid "Indexing..."
 msgid "Indexing..."
 msgstr "索引中..."
 msgstr "索引中..."
 
 
@@ -1683,6 +1714,10 @@ msgstr "文件名无效"
 msgid "Invalid folder name"
 msgid "Invalid folder name"
 msgstr "无效文件夹名"
 msgstr "无效文件夹名"
 
 
+#: src/constants/errors/notification.ts:3
+msgid "Invalid notifier config"
+msgstr "通知配置无效"
+
 #: src/constants/errors/user.ts:4
 #: src/constants/errors/user.ts:4
 msgid "Invalid otp code"
 msgid "Invalid otp code"
 msgstr "无效的 OTP 代码"
 msgstr "无效的 OTP 代码"
@@ -1743,6 +1778,10 @@ msgstr ""
 msgid "Key Type"
 msgid "Key Type"
 msgstr "密钥类型"
 msgstr "密钥类型"
 
 
+#: src/views/preference/components/ExternalNotify/columns.ts:29
+msgid "Language"
+msgstr "语言"
+
 #: src/views/system/Upgrade.vue:179
 #: src/views/system/Upgrade.vue:179
 msgid "Last checked at"
 msgid "Last checked at"
 msgstr "最后检查时间"
 msgstr "最后检查时间"
@@ -1838,7 +1877,7 @@ msgstr "登录成功"
 msgid "Logout successful"
 msgid "Logout successful"
 msgstr "登出成功"
 msgstr "登出成功"
 
 
-#: src/views/preference/Preference.vue:210
+#: src/views/preference/Preference.vue:217
 msgid "Logrotate"
 msgid "Logrotate"
 msgstr "Logrotate"
 msgstr "Logrotate"
 
 
@@ -1882,7 +1921,7 @@ msgstr ""
 msgid "Manage Configs"
 msgid "Manage Configs"
 msgstr "配置管理"
 msgstr "配置管理"
 
 
-#: src/routes/modules/sites.ts:10 src/views/site/site_list/SiteList.vue:121
+#: src/routes/modules/sites.ts:10 src/views/site/site_list/SiteList.vue:125
 msgid "Manage Sites"
 msgid "Manage Sites"
 msgstr "网站管理"
 msgstr "网站管理"
 
 
@@ -1958,7 +1997,7 @@ msgstr "多行指令"
 #: src/views/nginx_log/NginxLogList.vue:37
 #: src/views/nginx_log/NginxLogList.vue:37
 #: src/views/preference/components/AddPasskey.vue:75
 #: src/views/preference/components/AddPasskey.vue:75
 #: src/views/site/ngx_conf/NgxUpstream.vue:177
 #: src/views/site/ngx_conf/NgxUpstream.vue:177
-#: src/views/site/site_edit/RightSettings.vue:64
+#: src/views/site/site_edit/RightSettings.vue:63
 #: src/views/site/site_list/columns.tsx:17
 #: src/views/site/site_list/columns.tsx:17
 #: src/views/site/site_list/SiteDuplicate.vue:79
 #: src/views/site/site_list/SiteDuplicate.vue:79
 #: src/views/stream/components/RightSettings.vue:87
 #: src/views/stream/components/RightSettings.vue:87
@@ -2005,7 +2044,7 @@ msgstr "新版本发布"
 msgid "Next"
 msgid "Next"
 msgstr "下一步"
 msgstr "下一步"
 
 
-#: src/views/preference/Preference.vue:198
+#: src/views/preference/Preference.vue:205
 msgid "Nginx"
 msgid "Nginx"
 msgstr "Nginx"
 msgstr "Nginx"
 
 
@@ -2138,7 +2177,7 @@ msgstr "Nginx UI 配置已恢复,几秒钟后将自动重启。"
 #: src/views/preference/CertSettings.vue:73
 #: src/views/preference/CertSettings.vue:73
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:97
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:97
 #: src/views/site/ngx_conf/LocationEditor.vue:88
 #: src/views/site/ngx_conf/LocationEditor.vue:88
-#: src/views/site/site_list/SiteList.vue:161
+#: src/views/site/site_list/SiteList.vue:165
 #: src/views/stream/StreamList.vue:225
 #: src/views/stream/StreamList.vue:225
 msgid "No"
 msgid "No"
 msgstr "取消"
 msgstr "取消"
@@ -2152,11 +2191,11 @@ msgstr "无操作"
 msgid "No records selected"
 msgid "No records selected"
 msgstr "未选择记录"
 msgstr "未选择记录"
 
 
-#: src/views/preference/Preference.vue:168
+#: src/views/preference/Preference.vue:175
 msgid "Node"
 msgid "Node"
 msgstr "节点"
 msgstr "节点"
 
 
-#: src/views/site/site_edit/RightSettings.vue:67
+#: src/views/site/site_edit/RightSettings.vue:66
 #: src/views/site/site_list/columns.tsx:63
 #: src/views/site/site_list/columns.tsx:63
 #: src/views/stream/components/RightSettings.vue:90
 #: src/views/stream/components/RightSettings.vue:90
 #: src/views/stream/StreamList.vue:30
 #: src/views/stream/StreamList.vue:30
@@ -2197,7 +2236,7 @@ msgstr "此前无效: %{date}"
 msgid "Note"
 msgid "Note"
 msgstr "注意"
 msgstr "注意"
 
 
-#: src/views/site/site_edit/RightSettings.vue:96
+#: src/views/site/site_edit/RightSettings.vue:95
 #: src/views/stream/components/RightSettings.vue:118
 #: src/views/stream/components/RightSettings.vue:118
 msgid ""
 msgid ""
 "Note, if the configuration file include other configurations or "
 "Note, if the configuration file include other configurations or "
@@ -2213,6 +2252,10 @@ msgstr "通知"
 msgid "Notifications"
 msgid "Notifications"
 msgstr "通知"
 msgstr "通知"
 
 
+#: src/constants/errors/notification.ts:2
+msgid "Notifier not found"
+msgstr "未找到通知程序"
+
 #: src/views/site/cert/components/ObtainCert.vue:182
 #: src/views/site/cert/components/ObtainCert.vue:182
 msgid "Obtain certificate"
 msgid "Obtain certificate"
 msgstr "获取证书"
 msgstr "获取证书"
@@ -2255,7 +2298,7 @@ msgstr "确定"
 #: src/views/site/ngx_conf/NgxServer.vue:79
 #: src/views/site/ngx_conf/NgxServer.vue:79
 #: src/views/site/ngx_conf/NgxUpstream.vue:33
 #: src/views/site/ngx_conf/NgxUpstream.vue:33
 #: src/views/site/site_edit/components/SiteStatusSegmented.vue:121
 #: src/views/site/site_edit/components/SiteStatusSegmented.vue:121
-#: src/views/site/site_list/SiteList.vue:162
+#: src/views/site/site_list/SiteList.vue:166
 #: src/views/stream/components/RightSettings.vue:54
 #: src/views/stream/components/RightSettings.vue:54
 #: src/views/stream/StreamList.vue:226
 #: src/views/stream/StreamList.vue:226
 #: src/views/system/Backup/BackupCreator.vue:149
 #: src/views/system/Backup/BackupCreator.vue:149
@@ -2278,7 +2321,7 @@ msgstr "在线"
 msgid "Only zip files are allowed"
 msgid "Only zip files are allowed"
 msgstr "只允许使用zip文件"
 msgstr "只允许使用zip文件"
 
 
-#: src/views/preference/Preference.vue:204
+#: src/views/preference/Preference.vue:211
 msgid "OpenAI"
 msgid "OpenAI"
 msgstr "OpenAI"
 msgstr "OpenAI"
 
 
@@ -2419,7 +2462,7 @@ msgstr ""
 "请首先在 “证书”> “DNS 凭证” 中添加凭证,然后在下方选择一个凭证,请求 DNS 提供"
 "请首先在 “证书”> “DNS 凭证” 中添加凭证,然后在下方选择一个凭证,请求 DNS 提供"
 "商的 API。"
 "商的 API。"
 
 
-#: src/components/Notification/notifications.ts:138
+#: src/components/Notification/notifications.ts:156
 #: src/language/constants.ts:59
 #: src/language/constants.ts:59
 msgid ""
 msgid ""
 "Please generate new recovery codes in the preferences immediately to prevent "
 "Please generate new recovery codes in the preferences immediately to prevent "
@@ -2505,7 +2548,7 @@ msgstr "同步后操作"
 msgid "Pre-release"
 msgid "Pre-release"
 msgstr "预发布"
 msgstr "预发布"
 
 
-#: src/routes/modules/preference.ts:10 src/views/preference/Preference.vue:151
+#: src/routes/modules/preference.ts:10 src/views/preference/Preference.vue:152
 msgid "Preference"
 msgid "Preference"
 msgstr "偏好设置"
 msgstr "偏好设置"
 
 
@@ -2639,19 +2682,19 @@ msgstr "重载"
 msgid "Reload Nginx"
 msgid "Reload Nginx"
 msgstr "重载 Nginx"
 msgstr "重载 Nginx"
 
 
-#: src/components/Notification/notifications.ts:144
+#: src/components/Notification/notifications.ts:10
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgstr "在 %{node} 上重载 Nginx 失败,响应:%{resp}"
 msgstr "在 %{node} 上重载 Nginx 失败,响应:%{resp}"
 
 
-#: src/components/Notification/notifications.ts:148
+#: src/components/Notification/notifications.ts:14
 msgid "Reload Nginx on %{node} successfully"
 msgid "Reload Nginx on %{node} successfully"
 msgstr "在 %{node} 上重载 Nginx 成功"
 msgstr "在 %{node} 上重载 Nginx 成功"
 
 
-#: src/components/Notification/notifications.ts:143
+#: src/components/Notification/notifications.ts:9
 msgid "Reload Remote Nginx Error"
 msgid "Reload Remote Nginx Error"
 msgstr "重载远程 Nginx 错误"
 msgstr "重载远程 Nginx 错误"
 
 
-#: src/components/Notification/notifications.ts:147
+#: src/components/Notification/notifications.ts:13
 msgid "Reload Remote Nginx Success"
 msgid "Reload Remote Nginx Success"
 msgstr "重载远程 Nginx 成功"
 msgstr "重载远程 Nginx 成功"
 
 
@@ -2689,51 +2732,51 @@ msgstr "删除成功"
 msgid "Rename"
 msgid "Rename"
 msgstr "重命名"
 msgstr "重命名"
 
 
-#: src/components/Notification/notifications.ts:28
+#: src/components/Notification/notifications.ts:46
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} failed"
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} failed"
 msgstr "成功将 %{env_name} 上的 %{orig_path} 重命名为 %{new_path}"
 msgstr "成功将 %{env_name} 上的 %{orig_path} 重命名为 %{new_path}"
 
 
-#: src/components/Notification/notifications.ts:32
+#: src/components/Notification/notifications.ts:50
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} successfully"
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} successfully"
 msgstr "成功将 %{env_name} 上的 %{orig_path} 重命名为 %{new_path}"
 msgstr "成功将 %{env_name} 上的 %{orig_path} 重命名为 %{new_path}"
 
 
-#: src/components/Notification/notifications.ts:27 src/language/constants.ts:42
+#: src/components/Notification/notifications.ts:45 src/language/constants.ts:42
 msgid "Rename Remote Config Error"
 msgid "Rename Remote Config Error"
 msgstr "远程配置重命名错误"
 msgstr "远程配置重命名错误"
 
 
-#: src/components/Notification/notifications.ts:31 src/language/constants.ts:41
+#: src/components/Notification/notifications.ts:49 src/language/constants.ts:41
 msgid "Rename Remote Config Success"
 msgid "Rename Remote Config Success"
 msgstr "重命名远程配置成功"
 msgstr "重命名远程配置成功"
 
 
-#: src/components/Notification/notifications.ts:77 src/language/constants.ts:56
+#: src/components/Notification/notifications.ts:95 src/language/constants.ts:56
 msgid "Rename Remote Site Error"
 msgid "Rename Remote Site Error"
 msgstr "重命名远程站点错误"
 msgstr "重命名远程站点错误"
 
 
-#: src/components/Notification/notifications.ts:81 src/language/constants.ts:55
+#: src/components/Notification/notifications.ts:99 src/language/constants.ts:55
 msgid "Rename Remote Site Success"
 msgid "Rename Remote Site Success"
 msgstr "重命名远程站点成功"
 msgstr "重命名远程站点成功"
 
 
-#: src/components/Notification/notifications.ts:119
+#: src/components/Notification/notifications.ts:137
 msgid "Rename Remote Stream Error"
 msgid "Rename Remote Stream Error"
 msgstr "重命名远程 Stream 错误"
 msgstr "重命名远程 Stream 错误"
 
 
-#: src/components/Notification/notifications.ts:123
+#: src/components/Notification/notifications.ts:141
 msgid "Rename Remote Stream Success"
 msgid "Rename Remote Stream Success"
 msgstr "重命名远程 Stream成功"
 msgstr "重命名远程 Stream成功"
 
 
-#: src/components/Notification/notifications.ts:78
+#: src/components/Notification/notifications.ts:96
 msgid "Rename site %{name} to %{new_name} on %{node} failed"
 msgid "Rename site %{name} to %{new_name} on %{node} failed"
 msgstr "在 %{node} 上将站点 %{name} 重命名为 %{new_name} 成功"
 msgstr "在 %{node} 上将站点 %{name} 重命名为 %{new_name} 成功"
 
 
-#: src/components/Notification/notifications.ts:82
+#: src/components/Notification/notifications.ts:100
 msgid "Rename site %{name} to %{new_name} on %{node} successfully"
 msgid "Rename site %{name} to %{new_name} on %{node} successfully"
 msgstr "在 %{node} 上将站点 %{name} 重命名为 %{new_name} 成功"
 msgstr "在 %{node} 上将站点 %{name} 重命名为 %{new_name} 成功"
 
 
-#: src/components/Notification/notifications.ts:120
+#: src/components/Notification/notifications.ts:138
 msgid "Rename stream %{name} to %{new_name} on %{node} failed"
 msgid "Rename stream %{name} to %{new_name} on %{node} failed"
 msgstr "在 %{node} 上将站点 %{name} 重命名为 %{new_name} 成功"
 msgstr "在 %{node} 上将站点 %{name} 重命名为 %{new_name} 成功"
 
 
-#: src/components/Notification/notifications.ts:124
+#: src/components/Notification/notifications.ts:142
 msgid "Rename stream %{name} to %{new_name} on %{node} successfully"
 msgid "Rename stream %{name} to %{new_name} on %{node} successfully"
 msgstr "在 %{node} 上将站点 %{name} 重命名为 %{new_name} 成功"
 msgstr "在 %{node} 上将站点 %{name} 重命名为 %{new_name} 成功"
 
 
@@ -2791,19 +2834,19 @@ msgstr "重启"
 msgid "Restart Nginx"
 msgid "Restart Nginx"
 msgstr "重启 Nginx"
 msgstr "重启 Nginx"
 
 
-#: src/components/Notification/notifications.ts:152
+#: src/components/Notification/notifications.ts:18
 msgid "Restart Nginx on %{node} failed, response: %{resp}"
 msgid "Restart Nginx on %{node} failed, response: %{resp}"
 msgstr "在 %{node} 上重启 Nginx 失败,响应:%{resp}"
 msgstr "在 %{node} 上重启 Nginx 失败,响应:%{resp}"
 
 
-#: src/components/Notification/notifications.ts:156
+#: src/components/Notification/notifications.ts:22
 msgid "Restart Nginx on %{node} successfully"
 msgid "Restart Nginx on %{node} successfully"
 msgstr "在 %{node} 上重启 Nginx 成功"
 msgstr "在 %{node} 上重启 Nginx 成功"
 
 
-#: src/components/Notification/notifications.ts:151
+#: src/components/Notification/notifications.ts:17
 msgid "Restart Remote Nginx Error"
 msgid "Restart Remote Nginx Error"
 msgstr "重启远程 Nginx 错误"
 msgstr "重启远程 Nginx 错误"
 
 
-#: src/components/Notification/notifications.ts:155
+#: src/components/Notification/notifications.ts:21
 msgid "Restart Remote Nginx Success"
 msgid "Restart Remote Nginx Success"
 msgstr "重启远程 Nginx 成功"
 msgstr "重启远程 Nginx 成功"
 
 
@@ -2865,7 +2908,7 @@ msgstr "运行中"
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/ConfigEditor.vue:271
 #: src/views/config/ConfigEditor.vue:271
 #: src/views/preference/components/Passkey.vue:130
 #: src/views/preference/components/Passkey.vue:130
-#: src/views/preference/Preference.vue:221
+#: src/views/preference/Preference.vue:228
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:127
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:127
 #: src/views/site/site_edit/components/ConfigName.vue:52
 #: src/views/site/site_edit/components/ConfigName.vue:52
 #: src/views/site/site_edit/SiteEdit.vue:292
 #: src/views/site/site_edit/SiteEdit.vue:292
@@ -2883,42 +2926,44 @@ msgstr "保存指令"
 msgid "Save error %{msg}"
 msgid "Save error %{msg}"
 msgstr "保存错误 %{msg}"
 msgstr "保存错误 %{msg}"
 
 
-#: src/components/Notification/notifications.ts:85 src/language/constants.ts:48
+#: src/components/Notification/notifications.ts:103
+#: src/language/constants.ts:48
 msgid "Save Remote Site Error"
 msgid "Save Remote Site Error"
 msgstr "保存远程站点错误"
 msgstr "保存远程站点错误"
 
 
-#: src/components/Notification/notifications.ts:89 src/language/constants.ts:47
+#: src/components/Notification/notifications.ts:107
+#: src/language/constants.ts:47
 msgid "Save Remote Site Success"
 msgid "Save Remote Site Success"
 msgstr "保存远程站点成功"
 msgstr "保存远程站点成功"
 
 
-#: src/components/Notification/notifications.ts:127
+#: src/components/Notification/notifications.ts:145
 msgid "Save Remote Stream Error"
 msgid "Save Remote Stream Error"
 msgstr "保存远程 Stream 错误"
 msgstr "保存远程 Stream 错误"
 
 
-#: src/components/Notification/notifications.ts:131
+#: src/components/Notification/notifications.ts:149
 msgid "Save Remote Stream Success"
 msgid "Save Remote Stream Success"
 msgstr "保存远程 Stream 成功"
 msgstr "保存远程 Stream 成功"
 
 
-#: src/components/Notification/notifications.ts:86
+#: src/components/Notification/notifications.ts:104
 msgid "Save site %{name} to %{node} failed"
 msgid "Save site %{name} to %{node} failed"
 msgstr "成功将站点 %{name} 保存到 %{node} 中"
 msgstr "成功将站点 %{name} 保存到 %{node} 中"
 
 
-#: src/components/Notification/notifications.ts:90
+#: src/components/Notification/notifications.ts:108
 msgid "Save site %{name} to %{node} successfully"
 msgid "Save site %{name} to %{node} successfully"
 msgstr "成功将站点 %{name} 保存到 %{node} 中"
 msgstr "成功将站点 %{name} 保存到 %{node} 中"
 
 
-#: src/components/Notification/notifications.ts:128
+#: src/components/Notification/notifications.ts:146
 msgid "Save stream %{name} to %{node} failed"
 msgid "Save stream %{name} to %{node} failed"
 msgstr "部署 %{name} 到 %{node} 失败"
 msgstr "部署 %{name} 到 %{node} 失败"
 
 
-#: src/components/Notification/notifications.ts:132
+#: src/components/Notification/notifications.ts:150
 msgid "Save stream %{name} to %{node} successfully"
 msgid "Save stream %{name} to %{node} successfully"
 msgstr "成功将站点 %{name} 保存到 %{node} 中"
 msgstr "成功将站点 %{name} 保存到 %{node} 中"
 
 
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:47
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:47
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:97
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:97
 #: src/views/certificate/CertificateEditor.vue:49
 #: src/views/certificate/CertificateEditor.vue:49
-#: src/views/preference/Preference.vue:123
+#: src/views/preference/Preference.vue:124
 msgid "Save successfully"
 msgid "Save successfully"
 msgstr "保存成功"
 msgstr "保存成功"
 
 
@@ -2938,6 +2983,10 @@ msgstr "用手机扫描二维码,将账户添加到应用程序中。"
 msgid "SDK"
 msgid "SDK"
 msgstr "SDK"
 msgstr "SDK"
 
 
+#: src/views/preference/components/ExternalNotify/dingtalk.ts:13
+msgid "Secret (Optional)"
+msgstr "秘密(可选)"
+
 #: src/views/preference/components/TOTP.vue:109
 #: src/views/preference/components/TOTP.vue:109
 msgid "Secret has been copied"
 msgid "Secret has been copied"
 msgstr "密钥已复制"
 msgstr "密钥已复制"
@@ -2968,7 +3017,7 @@ msgstr "自我检查"
 msgid "Send"
 msgid "Send"
 msgstr "上传"
 msgstr "上传"
 
 
-#: src/views/preference/Preference.vue:156
+#: src/views/preference/Preference.vue:157
 msgid "Server"
 msgid "Server"
 msgstr "服务器"
 msgstr "服务器"
 
 
@@ -2976,6 +3025,10 @@ msgstr "服务器"
 msgid "Server Info"
 msgid "Server Info"
 msgstr "服务器信息"
 msgstr "服务器信息"
 
 
+#: src/views/preference/components/ExternalNotify/bark.ts:13
+msgid "Server URL"
+msgstr "服务器 URL"
+
 #: src/views/site/cert/components/ObtainCert.vue:107
 #: src/views/site/cert/components/ObtainCert.vue:107
 msgid "server_name not found in directives"
 msgid "server_name not found in directives"
 msgstr "未在指令集合中找到 server_name"
 msgstr "未在指令集合中找到 server_name"
@@ -3141,7 +3194,7 @@ msgstr "开始还原"
 #: src/views/certificate/ACMEUser.vue:65
 #: src/views/certificate/ACMEUser.vue:65
 #: src/views/certificate/CertificateList/certColumns.tsx:65
 #: src/views/certificate/CertificateList/certColumns.tsx:65
 #: src/views/environments/list/envColumns.tsx:44
 #: src/views/environments/list/envColumns.tsx:44
-#: src/views/site/site_edit/RightSettings.vue:56
+#: src/views/site/site_edit/RightSettings.vue:55
 #: src/views/site/site_list/columns.tsx:80 src/views/stream/StreamList.vue:47
 #: src/views/site/site_list/columns.tsx:80 src/views/stream/StreamList.vue:47
 msgid "Status"
 msgid "Status"
 msgstr "状态"
 msgstr "状态"
@@ -3215,35 +3268,35 @@ msgstr "同步"
 msgid "Sync Certificate"
 msgid "Sync Certificate"
 msgstr "同步证书"
 msgstr "同步证书"
 
 
-#: src/components/Notification/notifications.ts:10
+#: src/components/Notification/notifications.ts:28
 msgid "Sync Certificate %{cert_name} to %{env_name} failed"
 msgid "Sync Certificate %{cert_name} to %{env_name} failed"
 msgstr "证书 %{cert_name} 已成功同步到 %{env_name}"
 msgstr "证书 %{cert_name} 已成功同步到 %{env_name}"
 
 
-#: src/components/Notification/notifications.ts:14
+#: src/components/Notification/notifications.ts:32
 msgid "Sync Certificate %{cert_name} to %{env_name} successfully"
 msgid "Sync Certificate %{cert_name} to %{env_name} successfully"
 msgstr "证书 %{cert_name} 已成功同步到 %{env_name}"
 msgstr "证书 %{cert_name} 已成功同步到 %{env_name}"
 
 
-#: src/components/Notification/notifications.ts:9 src/language/constants.ts:39
+#: src/components/Notification/notifications.ts:27 src/language/constants.ts:39
 msgid "Sync Certificate Error"
 msgid "Sync Certificate Error"
 msgstr "同步证书错误"
 msgstr "同步证书错误"
 
 
-#: src/components/Notification/notifications.ts:13 src/language/constants.ts:38
+#: src/components/Notification/notifications.ts:31 src/language/constants.ts:38
 msgid "Sync Certificate Success"
 msgid "Sync Certificate Success"
 msgstr "同步证书成功"
 msgstr "同步证书成功"
 
 
-#: src/components/Notification/notifications.ts:20
+#: src/components/Notification/notifications.ts:38
 msgid "Sync config %{config_name} to %{env_name} failed"
 msgid "Sync config %{config_name} to %{env_name} failed"
 msgstr "配置 %{config_name} 成功同步到 %{env_name}"
 msgstr "配置 %{config_name} 成功同步到 %{env_name}"
 
 
-#: src/components/Notification/notifications.ts:24
+#: src/components/Notification/notifications.ts:42
 msgid "Sync config %{config_name} to %{env_name} successfully"
 msgid "Sync config %{config_name} to %{env_name} successfully"
 msgstr "配置 %{config_name} 成功同步到 %{env_name}"
 msgstr "配置 %{config_name} 成功同步到 %{env_name}"
 
 
-#: src/components/Notification/notifications.ts:19 src/language/constants.ts:45
+#: src/components/Notification/notifications.ts:37 src/language/constants.ts:45
 msgid "Sync Config Error"
 msgid "Sync Config Error"
 msgstr "同步配置错误"
 msgstr "同步配置错误"
 
 
-#: src/components/Notification/notifications.ts:23 src/language/constants.ts:44
+#: src/components/Notification/notifications.ts:41 src/language/constants.ts:44
 msgid "Sync Config Success"
 msgid "Sync Config Success"
 msgstr "同步配置成功"
 msgstr "同步配置成功"
 
 
@@ -3252,8 +3305,8 @@ msgstr "同步配置成功"
 msgid "Sync Nodes"
 msgid "Sync Nodes"
 msgstr "同步节点"
 msgstr "同步节点"
 
 
-#: src/views/site/site_edit/RightSettings.vue:102
-#: src/views/site/site_edit/RightSettings.vue:89
+#: src/views/site/site_edit/RightSettings.vue:101
+#: src/views/site/site_edit/RightSettings.vue:88
 #: src/views/stream/components/RightSettings.vue:111
 #: src/views/stream/components/RightSettings.vue:111
 #: src/views/stream/components/RightSettings.vue:124
 #: src/views/stream/components/RightSettings.vue:124
 msgid "Sync strategy"
 msgid "Sync strategy"
@@ -3263,7 +3316,7 @@ msgstr "同步策略"
 msgid "Sync to"
 msgid "Sync to"
 msgstr "同步到"
 msgstr "同步到"
 
 
-#: src/views/site/site_edit/RightSettings.vue:86
+#: src/views/site/site_edit/RightSettings.vue:85
 #: src/views/stream/components/RightSettings.vue:108
 #: src/views/stream/components/RightSettings.vue:108
 msgid "Synchronization"
 msgid "Synchronization"
 msgstr "同步"
 msgstr "同步"
@@ -3292,7 +3345,11 @@ msgstr "系统恢复成功。"
 msgid "Task not found"
 msgid "Task not found"
 msgstr "未找到任务"
 msgstr "未找到任务"
 
 
-#: src/routes/modules/terminal.ts:10 src/views/preference/Preference.vue:180
+#: src/views/preference/components/ExternalNotify/telegram.ts:5
+msgid "Telegram"
+msgstr "Telegram"
+
+#: src/routes/modules/terminal.ts:10 src/views/preference/Preference.vue:187
 #: src/views/terminal/Terminal.vue:129
 #: src/views/terminal/Terminal.vue:129
 msgid "Terminal"
 msgid "Terminal"
 msgstr "终端"
 msgstr "终端"
@@ -3541,6 +3598,7 @@ msgstr "需要两步验证"
 #: src/views/certificate/CertificateList/certColumns.tsx:25
 #: src/views/certificate/CertificateList/certColumns.tsx:25
 #: src/views/nginx_log/NginxLogList.vue:21
 #: src/views/nginx_log/NginxLogList.vue:21
 #: src/views/notification/notificationColumns.tsx:9
 #: src/views/notification/notificationColumns.tsx:9
+#: src/views/preference/components/ExternalNotify/columns.ts:17
 msgid "Type"
 msgid "Type"
 msgstr "类型"
 msgstr "类型"
 
 
@@ -3557,7 +3615,7 @@ msgstr "更新成功"
 #: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:325
 #: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:325
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/environments/list/envColumns.tsx:90
-#: src/views/site/site_edit/RightSettings.vue:76
+#: src/views/site/site_edit/RightSettings.vue:75
 #: src/views/site/site_list/columns.tsx:110
 #: src/views/site/site_list/columns.tsx:110
 #: src/views/stream/components/RightSettings.vue:99
 #: src/views/stream/components/RightSettings.vue:99
 #: src/views/stream/StreamList.vue:67 src/views/user/userColumns.tsx:54
 #: src/views/stream/StreamList.vue:67 src/views/user/userColumns.tsx:54
@@ -3717,7 +3775,7 @@ msgstr ""
 "启用后,Nginx UI 将在启动时自动重新注册用户。一般情况下,除非在开发环境中使"
 "启用后,Nginx UI 将在启动时自动重新注册用户。一般情况下,除非在开发环境中使"
 "用 Pebble 作为 CA,否则不要启用此功能。"
 "用 Pebble 作为 CA,否则不要启用此功能。"
 
 
-#: src/views/site/site_edit/RightSettings.vue:92
+#: src/views/site/site_edit/RightSettings.vue:91
 msgid ""
 msgid ""
 "When you enable/disable, delete, or save this site, the nodes set in the "
 "When you enable/disable, delete, or save this site, the nodes set in the "
 "Node Group and the nodes selected below will be synchronized."
 "Node Group and the nodes selected below will be synchronized."
@@ -4053,9 +4111,6 @@ msgstr "你的 Passkeys"
 #~ msgid "The Operation of Sites, Configs and Certification will redo on this"
 #~ msgid "The Operation of Sites, Configs and Certification will redo on this"
 #~ msgstr "网站、配置和证书的操作同步到该环境"
 #~ msgstr "网站、配置和证书的操作同步到该环境"
 
 
-#~ msgid "Token"
-#~ msgstr "Token"
-
 #~ msgid "Git"
 #~ msgid "Git"
 #~ msgstr "Git"
 #~ msgstr "Git"
 
 

+ 165 - 105
app/src/language/zh_TW/app.po

@@ -40,6 +40,11 @@ msgstr "訪問日誌"
 msgid "Access Logs"
 msgid "Access Logs"
 msgstr "訪問日誌"
 msgstr "訪問日誌"
 
 
+#: src/views/preference/components/ExternalNotify/dingtalk.ts:9
+#, fuzzy
+msgid "Access Token"
+msgstr "訪問日誌"
+
 #: src/routes/modules/certificates.ts:20 src/views/certificate/ACMEUser.vue:113
 #: src/routes/modules/certificates.ts:20 src/views/certificate/ACMEUser.vue:113
 #: src/views/certificate/ACMEUserSelector.vue:85
 #: src/views/certificate/ACMEUserSelector.vue:85
 msgid "ACME User"
 msgid "ACME User"
@@ -54,6 +59,7 @@ msgstr "ACME 用戶"
 #: src/views/nginx_log/NginxLogList.vue:53
 #: src/views/nginx_log/NginxLogList.vue:53
 #: src/views/notification/notificationColumns.tsx:66
 #: src/views/notification/notificationColumns.tsx:66
 #: src/views/preference/AuthSettings.vue:30
 #: src/views/preference/AuthSettings.vue:30
+#: src/views/preference/components/ExternalNotify/columns.ts:46
 #: src/views/site/site_list/columns.tsx:117 src/views/stream/StreamList.vue:74
 #: src/views/site/site_list/columns.tsx:117 src/views/stream/StreamList.vue:74
 #: src/views/user/userColumns.tsx:60
 #: src/views/user/userColumns.tsx:60
 msgid "Action"
 msgid "Action"
@@ -118,7 +124,7 @@ msgstr "然後,重新整理此頁面並再次點選新增通行密鑰。"
 msgid "All"
 msgid "All"
 msgstr "全部"
 msgstr "全部"
 
 
-#: src/components/Notification/notifications.ts:137
+#: src/components/Notification/notifications.ts:155
 #: src/language/constants.ts:58
 #: src/language/constants.ts:58
 msgid "All Recovery Codes Have Been Used"
 msgid "All Recovery Codes Have Been Used"
 msgstr "所有恢復碼都已使用完畢"
 msgstr "所有恢復碼都已使用完畢"
@@ -143,7 +149,7 @@ msgstr "API Token"
 msgid "API Type"
 msgid "API Type"
 msgstr "API 類型"
 msgstr "API 類型"
 
 
-#: src/views/preference/Preference.vue:162
+#: src/views/preference/Preference.vue:163
 #, fuzzy
 #, fuzzy
 msgid "App"
 msgid "App"
 msgstr "套用"
 msgstr "套用"
@@ -197,7 +203,7 @@ msgstr "您確定要永久刪除此項目嗎?"
 msgid "Are you sure you want to delete this item?"
 msgid "Are you sure you want to delete this item?"
 msgstr "您確定要刪除此項目嗎?"
 msgstr "您確定要刪除此項目嗎?"
 
 
-#: src/views/site/site_list/SiteList.vue:163
+#: src/views/site/site_list/SiteList.vue:167
 #: src/views/stream/StreamList.vue:227
 #: src/views/stream/StreamList.vue:227
 msgid "Are you sure you want to delete?"
 msgid "Are you sure you want to delete?"
 msgstr "您確定要刪除嗎?"
 msgstr "您確定要刪除嗎?"
@@ -244,7 +250,7 @@ msgstr "嘗試修復"
 msgid "Attempts"
 msgid "Attempts"
 msgstr "嘗試次數"
 msgstr "嘗試次數"
 
 
-#: src/views/preference/Preference.vue:186
+#: src/views/preference/Preference.vue:193
 msgid "Auth"
 msgid "Auth"
 msgstr "身份驗證"
 msgstr "身份驗證"
 
 
@@ -328,12 +334,16 @@ msgstr "被禁止的 IP"
 msgid "Banned Until"
 msgid "Banned Until"
 msgstr "禁止至"
 msgstr "禁止至"
 
 
+#: src/views/preference/components/ExternalNotify/bark.ts:5
+msgid "Bark"
+msgstr ""
+
 #: src/views/site/site_add/SiteAdd.vue:95
 #: src/views/site/site_add/SiteAdd.vue:95
 msgid "Base information"
 msgid "Base information"
 msgstr "基本資訊"
 msgstr "基本資訊"
 
 
 #: src/views/config/ConfigEditor.vue:290
 #: src/views/config/ConfigEditor.vue:290
-#: src/views/site/site_edit/RightSettings.vue:53
+#: src/views/site/site_edit/RightSettings.vue:52
 #: src/views/stream/components/RightSettings.vue:79
 #: src/views/stream/components/RightSettings.vue:79
 msgid "Basic"
 msgid "Basic"
 msgstr "基本"
 msgstr "基本"
@@ -364,6 +374,11 @@ msgstr "以下是您要批次修改的選定項目"
 msgid "Block is nil"
 msgid "Block is nil"
 msgstr "區塊為 nil"
 msgstr "區塊為 nil"
 
 
+#: src/views/preference/components/ExternalNotify/telegram.ts:9
+#, fuzzy
+msgid "Bot Token"
+msgstr "Token"
+
 #: src/views/system/About.vue:55
 #: src/views/system/About.vue:55
 msgid "Build with"
 msgid "Build with"
 msgstr "構建基於"
 msgstr "構建基於"
@@ -403,7 +418,7 @@ msgstr ""
 msgid "Cannot remove initial user"
 msgid "Cannot remove initial user"
 msgstr "無法移除初始使用者"
 msgstr "無法移除初始使用者"
 
 
-#: src/views/preference/Preference.vue:192
+#: src/views/preference/Preference.vue:199
 msgid "Cert"
 msgid "Cert"
 msgstr "證書"
 msgstr "證書"
 
 
@@ -470,6 +485,10 @@ msgstr "變更後路徑"
 msgid "Channel"
 msgid "Channel"
 msgstr "通道"
 msgstr "通道"
 
 
+#: src/views/preference/components/ExternalNotify/telegram.ts:13
+msgid "Chat ID"
+msgstr ""
+
 #: src/views/system/Upgrade.vue:185
 #: src/views/system/Upgrade.vue:185
 msgid "Check again"
 msgid "Check again"
 msgstr "再次檢查"
 msgstr "再次檢查"
@@ -668,6 +687,7 @@ msgstr ""
 
 
 #: src/views/environments/group/columns.ts:31
 #: src/views/environments/group/columns.ts:31
 #: src/views/notification/notificationColumns.tsx:59
 #: src/views/notification/notificationColumns.tsx:59
+#: src/views/preference/components/ExternalNotify/columns.ts:41
 #: src/views/preference/components/Passkey.vue:95
 #: src/views/preference/components/Passkey.vue:95
 #: src/views/user/userColumns.tsx:48
 #: src/views/user/userColumns.tsx:48
 msgid "Created at"
 msgid "Created at"
@@ -738,7 +758,7 @@ msgstr "解密失敗"
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/views/site/ngx_conf/NgxServer.vue:110
 #: src/views/site/ngx_conf/NgxServer.vue:110
 #: src/views/site/ngx_conf/NgxUpstream.vue:128
 #: src/views/site/ngx_conf/NgxUpstream.vue:128
-#: src/views/site/site_list/SiteList.vue:172
+#: src/views/site/site_list/SiteList.vue:176
 #: src/views/stream/StreamList.vue:236
 #: src/views/stream/StreamList.vue:236
 msgid "Delete"
 msgid "Delete"
 msgstr "刪除"
 msgstr "刪除"
@@ -748,39 +768,39 @@ msgstr "刪除"
 msgid "Delete Permanently"
 msgid "Delete Permanently"
 msgstr "永久刪除"
 msgstr "永久刪除"
 
 
-#: src/components/Notification/notifications.ts:37 src/language/constants.ts:50
+#: src/components/Notification/notifications.ts:55 src/language/constants.ts:50
 msgid "Delete Remote Site Error"
 msgid "Delete Remote Site Error"
 msgstr "刪除遠端網站錯誤"
 msgstr "刪除遠端網站錯誤"
 
 
-#: src/components/Notification/notifications.ts:41 src/language/constants.ts:49
+#: src/components/Notification/notifications.ts:59 src/language/constants.ts:49
 msgid "Delete Remote Site Success"
 msgid "Delete Remote Site Success"
 msgstr "刪除遠端網站成功"
 msgstr "刪除遠端網站成功"
 
 
-#: src/components/Notification/notifications.ts:95
+#: src/components/Notification/notifications.ts:113
 msgid "Delete Remote Stream Error"
 msgid "Delete Remote Stream Error"
 msgstr "刪除遠端串流錯誤"
 msgstr "刪除遠端串流錯誤"
 
 
-#: src/components/Notification/notifications.ts:99
+#: src/components/Notification/notifications.ts:117
 msgid "Delete Remote Stream Success"
 msgid "Delete Remote Stream Success"
 msgstr "刪除遠端串流成功"
 msgstr "刪除遠端串流成功"
 
 
-#: src/components/Notification/notifications.ts:38
+#: src/components/Notification/notifications.ts:56
 msgid "Delete site %{name} from %{node} failed"
 msgid "Delete site %{name} from %{node} failed"
 msgstr "從 %{node} 刪除網站 %{name} 失敗"
 msgstr "從 %{node} 刪除網站 %{name} 失敗"
 
 
-#: src/components/Notification/notifications.ts:42
+#: src/components/Notification/notifications.ts:60
 msgid "Delete site %{name} from %{node} successfully"
 msgid "Delete site %{name} from %{node} successfully"
 msgstr "成功從 %{node} 移除站點 %{name}"
 msgstr "成功從 %{node} 移除站點 %{name}"
 
 
-#: src/views/site/site_list/SiteList.vue:94
+#: src/views/site/site_list/SiteList.vue:98
 msgid "Delete site: %{site_name}"
 msgid "Delete site: %{site_name}"
 msgstr "刪除網站:%{site_name}"
 msgstr "刪除網站:%{site_name}"
 
 
-#: src/components/Notification/notifications.ts:96
+#: src/components/Notification/notifications.ts:114
 msgid "Delete stream %{name} from %{node} failed"
 msgid "Delete stream %{name} from %{node} failed"
 msgstr "部署 %{conf_name} 至 %{node} 失敗"
 msgstr "部署 %{conf_name} 至 %{node} 失敗"
 
 
-#: src/components/Notification/notifications.ts:100
+#: src/components/Notification/notifications.ts:118
 msgid "Delete stream %{name} from %{node} successfully"
 msgid "Delete stream %{name} from %{node} successfully"
 msgstr "成功從 %{node} 移除站點 %{name}"
 msgstr "成功從 %{node} 移除站點 %{name}"
 
 
@@ -817,6 +837,14 @@ msgstr "詳細資料"
 msgid "Development Mode"
 msgid "Development Mode"
 msgstr "開發模式"
 msgstr "開發模式"
 
 
+#: src/views/preference/components/ExternalNotify/bark.ts:9
+msgid "Device Key"
+msgstr ""
+
+#: src/views/preference/components/ExternalNotify/dingtalk.ts:5
+msgid "DingTalk"
+msgstr ""
+
 #: src/views/site/ngx_conf/directive/DirectiveAdd.vue:89
 #: src/views/site/ngx_conf/directive/DirectiveAdd.vue:89
 msgid "Directive"
 msgid "Directive"
 msgstr "指令"
 msgstr "指令"
@@ -850,58 +878,58 @@ msgstr "停用"
 msgid "Disable auto-renewal failed for %{name}"
 msgid "Disable auto-renewal failed for %{name}"
 msgstr "關閉 %{name} 自動續簽失敗"
 msgstr "關閉 %{name} 自動續簽失敗"
 
 
-#: src/components/Notification/notifications.ts:45 src/language/constants.ts:52
+#: src/components/Notification/notifications.ts:63 src/language/constants.ts:52
 msgid "Disable Remote Site Error"
 msgid "Disable Remote Site Error"
 msgstr "禁用遠端站点錯誤"
 msgstr "禁用遠端站点錯誤"
 
 
-#: src/components/Notification/notifications.ts:69
+#: src/components/Notification/notifications.ts:87
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Site Maintenance Error"
 msgid "Disable Remote Site Maintenance Error"
 msgstr "禁用遠端站点錯誤"
 msgstr "禁用遠端站点錯誤"
 
 
-#: src/components/Notification/notifications.ts:73
+#: src/components/Notification/notifications.ts:91
 #, fuzzy
 #, fuzzy
 msgid "Disable Remote Site Maintenance Success"
 msgid "Disable Remote Site Maintenance Success"
 msgstr "禁用遠端站点成功"
 msgstr "禁用遠端站点成功"
 
 
-#: src/components/Notification/notifications.ts:49 src/language/constants.ts:51
+#: src/components/Notification/notifications.ts:67 src/language/constants.ts:51
 msgid "Disable Remote Site Success"
 msgid "Disable Remote Site Success"
 msgstr "禁用遠端站点成功"
 msgstr "禁用遠端站点成功"
 
 
-#: src/components/Notification/notifications.ts:103
+#: src/components/Notification/notifications.ts:121
 msgid "Disable Remote Stream Error"
 msgid "Disable Remote Stream Error"
 msgstr "禁用遠端串流錯誤"
 msgstr "禁用遠端串流錯誤"
 
 
-#: src/components/Notification/notifications.ts:107
+#: src/components/Notification/notifications.ts:125
 msgid "Disable Remote Stream Success"
 msgid "Disable Remote Stream Success"
 msgstr "禁用遠端串流成功"
 msgstr "禁用遠端串流成功"
 
 
-#: src/components/Notification/notifications.ts:46
+#: src/components/Notification/notifications.ts:64
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} from %{node} failed"
 msgid "Disable site %{name} from %{node} failed"
 msgstr "成功禁用 %{node} 中的站点 %{site}"
 msgstr "成功禁用 %{node} 中的站点 %{site}"
 
 
-#: src/components/Notification/notifications.ts:50
+#: src/components/Notification/notifications.ts:68
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} from %{node} successfully"
 msgid "Disable site %{name} from %{node} successfully"
 msgstr "成功禁用 %{node} 中的站点 %{site}"
 msgstr "成功禁用 %{node} 中的站点 %{site}"
 
 
-#: src/components/Notification/notifications.ts:70
+#: src/components/Notification/notifications.ts:88
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} maintenance on %{node} failed"
 msgid "Disable site %{name} maintenance on %{node} failed"
 msgstr "成功禁用 %{node} 中的站点 %{site}"
 msgstr "成功禁用 %{node} 中的站点 %{site}"
 
 
-#: src/components/Notification/notifications.ts:74
+#: src/components/Notification/notifications.ts:92
 #, fuzzy
 #, fuzzy
 msgid "Disable site %{name} maintenance on %{node} successfully"
 msgid "Disable site %{name} maintenance on %{node} successfully"
 msgstr "成功禁用 %{node} 中的站点 %{site}"
 msgstr "成功禁用 %{node} 中的站点 %{site}"
 
 
-#: src/components/Notification/notifications.ts:104
+#: src/components/Notification/notifications.ts:122
 #, fuzzy
 #, fuzzy
 msgid "Disable stream %{name} from %{node} failed"
 msgid "Disable stream %{name} from %{node} failed"
 msgstr "在 %{node_name} 啟用 %{conf_name} 失敗"
 msgstr "在 %{node_name} 啟用 %{conf_name} 失敗"
 
 
-#: src/components/Notification/notifications.ts:108
+#: src/components/Notification/notifications.ts:126
 #, fuzzy
 #, fuzzy
 msgid "Disable stream %{name} from %{node} successfully"
 msgid "Disable stream %{name} from %{node} successfully"
 msgstr "成功禁用 %{node} 中的站点 %{site}"
 msgstr "成功禁用 %{node} 中的站点 %{site}"
@@ -1011,7 +1039,7 @@ msgstr ""
 "通行密鑰。"
 "通行密鑰。"
 
 
 #: src/views/site/site_list/SiteDuplicate.vue:72
 #: src/views/site/site_list/SiteDuplicate.vue:72
-#: src/views/site/site_list/SiteList.vue:158
+#: src/views/site/site_list/SiteList.vue:162
 #: src/views/stream/components/StreamDuplicate.vue:64
 #: src/views/stream/components/StreamDuplicate.vue:64
 #: src/views/stream/StreamList.vue:222
 #: src/views/stream/StreamList.vue:222
 msgid "Duplicate"
 msgid "Duplicate"
@@ -1078,60 +1106,60 @@ msgstr "啟用失敗"
 msgid "Enable HTTPS"
 msgid "Enable HTTPS"
 msgstr "啟用 TOTP"
 msgstr "啟用 TOTP"
 
 
-#: src/components/Notification/notifications.ts:53 src/language/constants.ts:54
+#: src/components/Notification/notifications.ts:71 src/language/constants.ts:54
 msgid "Enable Remote Site Error"
 msgid "Enable Remote Site Error"
 msgstr "啟用遠端站點錯誤"
 msgstr "啟用遠端站點錯誤"
 
 
-#: src/components/Notification/notifications.ts:61
+#: src/components/Notification/notifications.ts:79
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Site Maintenance Error"
 msgid "Enable Remote Site Maintenance Error"
 msgstr "啟用遠端站點錯誤"
 msgstr "啟用遠端站點錯誤"
 
 
-#: src/components/Notification/notifications.ts:65
+#: src/components/Notification/notifications.ts:83
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Site Maintenance Success"
 msgid "Enable Remote Site Maintenance Success"
 msgstr "啟用遠端站點成功"
 msgstr "啟用遠端站點成功"
 
 
-#: src/components/Notification/notifications.ts:57 src/language/constants.ts:53
+#: src/components/Notification/notifications.ts:75 src/language/constants.ts:53
 msgid "Enable Remote Site Success"
 msgid "Enable Remote Site Success"
 msgstr "啟用遠端站點成功"
 msgstr "啟用遠端站點成功"
 
 
-#: src/components/Notification/notifications.ts:111
+#: src/components/Notification/notifications.ts:129
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Stream Error"
 msgid "Enable Remote Stream Error"
 msgstr "啟用遠端站點錯誤"
 msgstr "啟用遠端站點錯誤"
 
 
-#: src/components/Notification/notifications.ts:115
+#: src/components/Notification/notifications.ts:133
 #, fuzzy
 #, fuzzy
 msgid "Enable Remote Stream Success"
 msgid "Enable Remote Stream Success"
 msgstr "啟用遠端站點成功"
 msgstr "啟用遠端站點成功"
 
 
-#: src/components/Notification/notifications.ts:62
+#: src/components/Notification/notifications.ts:80
 #, fuzzy
 #, fuzzy
 msgid "Enable site %{name} maintenance on %{node} failed"
 msgid "Enable site %{name} maintenance on %{node} failed"
 msgstr "在 %{node_name} 啟用 %{conf_name} 失敗"
 msgstr "在 %{node_name} 啟用 %{conf_name} 失敗"
 
 
-#: src/components/Notification/notifications.ts:66
+#: src/components/Notification/notifications.ts:84
 #, fuzzy
 #, fuzzy
 msgid "Enable site %{name} maintenance on %{node} successfully"
 msgid "Enable site %{name} maintenance on %{node} successfully"
 msgstr "成功啟用站點 %{site} 在 %{node}"
 msgstr "成功啟用站點 %{site} 在 %{node}"
 
 
-#: src/components/Notification/notifications.ts:54
+#: src/components/Notification/notifications.ts:72
 #, fuzzy
 #, fuzzy
 msgid "Enable site %{name} on %{node} failed"
 msgid "Enable site %{name} on %{node} failed"
 msgstr "在 %{node_name} 啟用 %{conf_name} 失敗"
 msgstr "在 %{node_name} 啟用 %{conf_name} 失敗"
 
 
-#: src/components/Notification/notifications.ts:58
+#: src/components/Notification/notifications.ts:76
 #, fuzzy
 #, fuzzy
 msgid "Enable site %{name} on %{node} successfully"
 msgid "Enable site %{name} on %{node} successfully"
 msgstr "成功啟用站點 %{site} 在 %{node}"
 msgstr "成功啟用站點 %{site} 在 %{node}"
 
 
-#: src/components/Notification/notifications.ts:112
+#: src/components/Notification/notifications.ts:130
 #, fuzzy
 #, fuzzy
 msgid "Enable stream %{name} on %{node} failed"
 msgid "Enable stream %{name} on %{node} failed"
 msgstr "在 %{node_name} 啟用 %{conf_name} 失敗"
 msgstr "在 %{node_name} 啟用 %{conf_name} 失敗"
 
 
-#: src/components/Notification/notifications.ts:116
+#: src/components/Notification/notifications.ts:134
 #, fuzzy
 #, fuzzy
 msgid "Enable stream %{name} on %{node} successfully"
 msgid "Enable stream %{name} on %{node} successfully"
 msgstr "成功啟用站點 %{site} 在 %{node}"
 msgstr "成功啟用站點 %{site} 在 %{node}"
@@ -1219,6 +1247,11 @@ msgstr "過期時間:%{date}"
 msgid "Export"
 msgid "Export"
 msgstr "匯出"
 msgstr "匯出"
 
 
+#: src/views/preference/ExternalNotify.vue:10
+#: src/views/preference/Preference.vue:169
+msgid "External Notify"
+msgstr ""
+
 #: src/views/site/cert/components/ObtainCertLive.vue:94
 #: src/views/site/cert/components/ObtainCertLive.vue:94
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
 msgstr "獲取憑證失敗"
 msgstr "獲取憑證失敗"
@@ -1619,7 +1652,7 @@ msgstr "首頁"
 msgid "Host"
 msgid "Host"
 msgstr "HTTP 監聽主機"
 msgstr "HTTP 監聽主機"
 
 
-#: src/views/preference/Preference.vue:174
+#: src/views/preference/Preference.vue:181
 #, fuzzy
 #, fuzzy
 msgid "HTTP"
 msgid "HTTP"
 msgstr "HTTP01"
 msgstr "HTTP01"
@@ -1678,13 +1711,13 @@ msgid "Import Certificate"
 msgstr "導入憑證"
 msgstr "導入憑證"
 
 
 #: src/views/nginx_log/NginxLogList.vue:137
 #: src/views/nginx_log/NginxLogList.vue:137
-#: src/views/site/site_list/SiteList.vue:128
+#: src/views/site/site_list/SiteList.vue:132
 #, fuzzy
 #, fuzzy
 msgid "Indexed"
 msgid "Indexed"
 msgstr "網站首頁 (index)"
 msgstr "網站首頁 (index)"
 
 
 #: src/views/nginx_log/NginxLogList.vue:134
 #: src/views/nginx_log/NginxLogList.vue:134
-#: src/views/site/site_list/SiteList.vue:125
+#: src/views/site/site_list/SiteList.vue:129
 msgid "Indexing..."
 msgid "Indexing..."
 msgstr ""
 msgstr ""
 
 
@@ -1768,6 +1801,11 @@ msgstr "無效的檔案名"
 msgid "Invalid folder name"
 msgid "Invalid folder name"
 msgstr "無效的資料夾名稱"
 msgstr "無效的資料夾名稱"
 
 
+#: src/constants/errors/notification.ts:3
+#, fuzzy
+msgid "Invalid notifier config"
+msgstr "無效的 OTP 代碼"
+
 #: src/constants/errors/user.ts:4
 #: src/constants/errors/user.ts:4
 msgid "Invalid otp code"
 msgid "Invalid otp code"
 msgstr "無效的 OTP 代碼"
 msgstr "無效的 OTP 代碼"
@@ -1829,6 +1867,10 @@ msgstr ""
 msgid "Key Type"
 msgid "Key Type"
 msgstr "密鑰類型"
 msgstr "密鑰類型"
 
 
+#: src/views/preference/components/ExternalNotify/columns.ts:29
+msgid "Language"
+msgstr ""
+
 #: src/views/system/Upgrade.vue:179
 #: src/views/system/Upgrade.vue:179
 msgid "Last checked at"
 msgid "Last checked at"
 msgstr "上次檢查時間"
 msgstr "上次檢查時間"
@@ -1925,7 +1967,7 @@ msgstr "登入成功"
 msgid "Logout successful"
 msgid "Logout successful"
 msgstr "登出成功"
 msgstr "登出成功"
 
 
-#: src/views/preference/Preference.vue:210
+#: src/views/preference/Preference.vue:217
 msgid "Logrotate"
 msgid "Logrotate"
 msgstr "Logrotate"
 msgstr "Logrotate"
 
 
@@ -1970,7 +2012,7 @@ msgstr ""
 msgid "Manage Configs"
 msgid "Manage Configs"
 msgstr "管理設定"
 msgstr "管理設定"
 
 
-#: src/routes/modules/sites.ts:10 src/views/site/site_list/SiteList.vue:121
+#: src/routes/modules/sites.ts:10 src/views/site/site_list/SiteList.vue:125
 msgid "Manage Sites"
 msgid "Manage Sites"
 msgstr "管理網站"
 msgstr "管理網站"
 
 
@@ -2046,7 +2088,7 @@ msgstr "多行指令"
 #: src/views/nginx_log/NginxLogList.vue:37
 #: src/views/nginx_log/NginxLogList.vue:37
 #: src/views/preference/components/AddPasskey.vue:75
 #: src/views/preference/components/AddPasskey.vue:75
 #: src/views/site/ngx_conf/NgxUpstream.vue:177
 #: src/views/site/ngx_conf/NgxUpstream.vue:177
-#: src/views/site/site_edit/RightSettings.vue:64
+#: src/views/site/site_edit/RightSettings.vue:63
 #: src/views/site/site_list/columns.tsx:17
 #: src/views/site/site_list/columns.tsx:17
 #: src/views/site/site_list/SiteDuplicate.vue:79
 #: src/views/site/site_list/SiteDuplicate.vue:79
 #: src/views/stream/components/RightSettings.vue:87
 #: src/views/stream/components/RightSettings.vue:87
@@ -2094,7 +2136,7 @@ msgstr "新版本發布"
 msgid "Next"
 msgid "Next"
 msgstr "下一步"
 msgstr "下一步"
 
 
-#: src/views/preference/Preference.vue:198
+#: src/views/preference/Preference.vue:205
 msgid "Nginx"
 msgid "Nginx"
 msgstr "Nginx"
 msgstr "Nginx"
 
 
@@ -2234,7 +2276,7 @@ msgstr "Nginx 設定解析錯誤"
 #: src/views/preference/CertSettings.vue:73
 #: src/views/preference/CertSettings.vue:73
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:97
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:97
 #: src/views/site/ngx_conf/LocationEditor.vue:88
 #: src/views/site/ngx_conf/LocationEditor.vue:88
-#: src/views/site/site_list/SiteList.vue:161
+#: src/views/site/site_list/SiteList.vue:165
 #: src/views/stream/StreamList.vue:225
 #: src/views/stream/StreamList.vue:225
 msgid "No"
 msgid "No"
 msgstr "取消"
 msgstr "取消"
@@ -2249,12 +2291,12 @@ msgstr "操作"
 msgid "No records selected"
 msgid "No records selected"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/Preference.vue:168
+#: src/views/preference/Preference.vue:175
 #, fuzzy
 #, fuzzy
 msgid "Node"
 msgid "Node"
 msgstr "節點名稱"
 msgstr "節點名稱"
 
 
-#: src/views/site/site_edit/RightSettings.vue:67
+#: src/views/site/site_edit/RightSettings.vue:66
 #: src/views/site/site_list/columns.tsx:63
 #: src/views/site/site_list/columns.tsx:63
 #: src/views/stream/components/RightSettings.vue:90
 #: src/views/stream/components/RightSettings.vue:90
 #: src/views/stream/StreamList.vue:30
 #: src/views/stream/StreamList.vue:30
@@ -2298,7 +2340,7 @@ msgstr "此前無效: %{date}"
 msgid "Note"
 msgid "Note"
 msgstr "備註"
 msgstr "備註"
 
 
-#: src/views/site/site_edit/RightSettings.vue:96
+#: src/views/site/site_edit/RightSettings.vue:95
 #: src/views/stream/components/RightSettings.vue:118
 #: src/views/stream/components/RightSettings.vue:118
 msgid ""
 msgid ""
 "Note, if the configuration file include other configurations or "
 "Note, if the configuration file include other configurations or "
@@ -2314,6 +2356,11 @@ msgstr "通知"
 msgid "Notifications"
 msgid "Notifications"
 msgstr "通知"
 msgstr "通知"
 
 
+#: src/constants/errors/notification.ts:2
+#, fuzzy
+msgid "Notifier not found"
+msgstr "站點未找到"
+
 #: src/views/site/cert/components/ObtainCert.vue:182
 #: src/views/site/cert/components/ObtainCert.vue:182
 msgid "Obtain certificate"
 msgid "Obtain certificate"
 msgstr "取得憑證"
 msgstr "取得憑證"
@@ -2356,7 +2403,7 @@ msgstr "確定"
 #: src/views/site/ngx_conf/NgxServer.vue:79
 #: src/views/site/ngx_conf/NgxServer.vue:79
 #: src/views/site/ngx_conf/NgxUpstream.vue:33
 #: src/views/site/ngx_conf/NgxUpstream.vue:33
 #: src/views/site/site_edit/components/SiteStatusSegmented.vue:121
 #: src/views/site/site_edit/components/SiteStatusSegmented.vue:121
-#: src/views/site/site_list/SiteList.vue:162
+#: src/views/site/site_list/SiteList.vue:166
 #: src/views/stream/components/RightSettings.vue:54
 #: src/views/stream/components/RightSettings.vue:54
 #: src/views/stream/StreamList.vue:226
 #: src/views/stream/StreamList.vue:226
 #: src/views/system/Backup/BackupCreator.vue:149
 #: src/views/system/Backup/BackupCreator.vue:149
@@ -2379,7 +2426,7 @@ msgstr "線上"
 msgid "Only zip files are allowed"
 msgid "Only zip files are allowed"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/Preference.vue:204
+#: src/views/preference/Preference.vue:211
 msgid "OpenAI"
 msgid "OpenAI"
 msgstr "OpenAI"
 msgstr "OpenAI"
 
 
@@ -2522,7 +2569,7 @@ msgstr ""
 "請先在「憑證」 > 「DNS 認證」中新增認證,然後選擇以下認證之一以請求 DNS 供應"
 "請先在「憑證」 > 「DNS 認證」中新增認證,然後選擇以下認證之一以請求 DNS 供應"
 "商的 API。"
 "商的 API。"
 
 
-#: src/components/Notification/notifications.ts:138
+#: src/components/Notification/notifications.ts:156
 #: src/language/constants.ts:59
 #: src/language/constants.ts:59
 msgid ""
 msgid ""
 "Please generate new recovery codes in the preferences immediately to prevent "
 "Please generate new recovery codes in the preferences immediately to prevent "
@@ -2613,7 +2660,7 @@ msgstr "批次操作"
 msgid "Pre-release"
 msgid "Pre-release"
 msgstr "預先發布"
 msgstr "預先發布"
 
 
-#: src/routes/modules/preference.ts:10 src/views/preference/Preference.vue:151
+#: src/routes/modules/preference.ts:10 src/views/preference/Preference.vue:152
 msgid "Preference"
 msgid "Preference"
 msgstr "偏好設定"
 msgstr "偏好設定"
 
 
@@ -2747,22 +2794,22 @@ msgstr "重新載入"
 msgid "Reload Nginx"
 msgid "Reload Nginx"
 msgstr "正在重新載入 Nginx"
 msgstr "正在重新載入 Nginx"
 
 
-#: src/components/Notification/notifications.ts:144
+#: src/components/Notification/notifications.ts:10
 #, fuzzy
 #, fuzzy
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgstr "從 %{node} 移除站點 %{site} 時發生錯誤,回應:%{resp}"
 msgstr "從 %{node} 移除站點 %{site} 時發生錯誤,回應:%{resp}"
 
 
-#: src/components/Notification/notifications.ts:148
+#: src/components/Notification/notifications.ts:14
 #, fuzzy
 #, fuzzy
 msgid "Reload Nginx on %{node} successfully"
 msgid "Reload Nginx on %{node} successfully"
 msgstr "成功升級 %{node} 上的 Nginx UI 🎉"
 msgstr "成功升級 %{node} 上的 Nginx UI 🎉"
 
 
-#: src/components/Notification/notifications.ts:143
+#: src/components/Notification/notifications.ts:9
 #, fuzzy
 #, fuzzy
 msgid "Reload Remote Nginx Error"
 msgid "Reload Remote Nginx Error"
 msgstr "重命名遠端遠端站點時發生錯誤"
 msgstr "重命名遠端遠端站點時發生錯誤"
 
 
-#: src/components/Notification/notifications.ts:147
+#: src/components/Notification/notifications.ts:13
 #, fuzzy
 #, fuzzy
 msgid "Reload Remote Nginx Success"
 msgid "Reload Remote Nginx Success"
 msgstr "重新命名遠端站點成功"
 msgstr "重新命名遠端站點成功"
@@ -2801,57 +2848,57 @@ msgstr "移除成功"
 msgid "Rename"
 msgid "Rename"
 msgstr "重命名"
 msgstr "重命名"
 
 
-#: src/components/Notification/notifications.ts:28
+#: src/components/Notification/notifications.ts:46
 #, fuzzy
 #, fuzzy
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} failed"
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} failed"
 msgstr "成功將 %{env_name} 上的 %{orig_path} 重命名為 %{new_path}"
 msgstr "成功將 %{env_name} 上的 %{orig_path} 重命名為 %{new_path}"
 
 
-#: src/components/Notification/notifications.ts:32
+#: src/components/Notification/notifications.ts:50
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} successfully"
 msgid "Rename %{orig_path} to %{new_path} on %{env_name} successfully"
 msgstr "成功將 %{env_name} 上的 %{orig_path} 重命名為 %{new_path}"
 msgstr "成功將 %{env_name} 上的 %{orig_path} 重命名為 %{new_path}"
 
 
-#: src/components/Notification/notifications.ts:27 src/language/constants.ts:42
+#: src/components/Notification/notifications.ts:45 src/language/constants.ts:42
 msgid "Rename Remote Config Error"
 msgid "Rename Remote Config Error"
 msgstr "重命名遠端配置錯誤"
 msgstr "重命名遠端配置錯誤"
 
 
-#: src/components/Notification/notifications.ts:31 src/language/constants.ts:41
+#: src/components/Notification/notifications.ts:49 src/language/constants.ts:41
 msgid "Rename Remote Config Success"
 msgid "Rename Remote Config Success"
 msgstr "重新命名遠端配置成功"
 msgstr "重新命名遠端配置成功"
 
 
-#: src/components/Notification/notifications.ts:77 src/language/constants.ts:56
+#: src/components/Notification/notifications.ts:95 src/language/constants.ts:56
 msgid "Rename Remote Site Error"
 msgid "Rename Remote Site Error"
 msgstr "重命名遠端遠端站點時發生錯誤"
 msgstr "重命名遠端遠端站點時發生錯誤"
 
 
-#: src/components/Notification/notifications.ts:81 src/language/constants.ts:55
+#: src/components/Notification/notifications.ts:99 src/language/constants.ts:55
 msgid "Rename Remote Site Success"
 msgid "Rename Remote Site Success"
 msgstr "重新命名遠端站點成功"
 msgstr "重新命名遠端站點成功"
 
 
-#: src/components/Notification/notifications.ts:119
+#: src/components/Notification/notifications.ts:137
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Stream Error"
 msgid "Rename Remote Stream Error"
 msgstr "重命名遠端遠端站點時發生錯誤"
 msgstr "重命名遠端遠端站點時發生錯誤"
 
 
-#: src/components/Notification/notifications.ts:123
+#: src/components/Notification/notifications.ts:141
 #, fuzzy
 #, fuzzy
 msgid "Rename Remote Stream Success"
 msgid "Rename Remote Stream Success"
 msgstr "重新命名遠端站點成功"
 msgstr "重新命名遠端站點成功"
 
 
-#: src/components/Notification/notifications.ts:78
+#: src/components/Notification/notifications.ts:96
 #, fuzzy
 #, fuzzy
 msgid "Rename site %{name} to %{new_name} on %{node} failed"
 msgid "Rename site %{name} to %{new_name} on %{node} failed"
 msgstr "成功將站點 %{site} 重新命名為 %{new_site} 於 %{node}"
 msgstr "成功將站點 %{site} 重新命名為 %{new_site} 於 %{node}"
 
 
-#: src/components/Notification/notifications.ts:82
+#: src/components/Notification/notifications.ts:100
 #, fuzzy
 #, fuzzy
 msgid "Rename site %{name} to %{new_name} on %{node} successfully"
 msgid "Rename site %{name} to %{new_name} on %{node} successfully"
 msgstr "成功將站點 %{site} 重新命名為 %{new_site} 於 %{node}"
 msgstr "成功將站點 %{site} 重新命名為 %{new_site} 於 %{node}"
 
 
-#: src/components/Notification/notifications.ts:120
+#: src/components/Notification/notifications.ts:138
 #, fuzzy
 #, fuzzy
 msgid "Rename stream %{name} to %{new_name} on %{node} failed"
 msgid "Rename stream %{name} to %{new_name} on %{node} failed"
 msgstr "成功將站點 %{site} 重新命名為 %{new_site} 於 %{node}"
 msgstr "成功將站點 %{site} 重新命名為 %{new_site} 於 %{node}"
 
 
-#: src/components/Notification/notifications.ts:124
+#: src/components/Notification/notifications.ts:142
 #, fuzzy
 #, fuzzy
 msgid "Rename stream %{name} to %{new_name} on %{node} successfully"
 msgid "Rename stream %{name} to %{new_name} on %{node} successfully"
 msgstr "成功將站點 %{site} 重新命名為 %{new_site} 於 %{node}"
 msgstr "成功將站點 %{site} 重新命名為 %{new_site} 於 %{node}"
@@ -2911,22 +2958,22 @@ msgstr "重新啟動"
 msgid "Restart Nginx"
 msgid "Restart Nginx"
 msgstr "正在重新啟動"
 msgstr "正在重新啟動"
 
 
-#: src/components/Notification/notifications.ts:152
+#: src/components/Notification/notifications.ts:18
 #, fuzzy
 #, fuzzy
 msgid "Restart Nginx on %{node} failed, response: %{resp}"
 msgid "Restart Nginx on %{node} failed, response: %{resp}"
 msgstr "啟用站點 %{site} 在 %{node} 時發生錯誤,回應:%{resp}"
 msgstr "啟用站點 %{site} 在 %{node} 時發生錯誤,回應:%{resp}"
 
 
-#: src/components/Notification/notifications.ts:156
+#: src/components/Notification/notifications.ts:22
 #, fuzzy
 #, fuzzy
 msgid "Restart Nginx on %{node} successfully"
 msgid "Restart Nginx on %{node} successfully"
 msgstr "成功升級 %{node} 上的 Nginx UI 🎉"
 msgstr "成功升級 %{node} 上的 Nginx UI 🎉"
 
 
-#: src/components/Notification/notifications.ts:151
+#: src/components/Notification/notifications.ts:17
 #, fuzzy
 #, fuzzy
 msgid "Restart Remote Nginx Error"
 msgid "Restart Remote Nginx Error"
 msgstr "重命名遠端遠端站點時發生錯誤"
 msgstr "重命名遠端遠端站點時發生錯誤"
 
 
-#: src/components/Notification/notifications.ts:155
+#: src/components/Notification/notifications.ts:21
 #, fuzzy
 #, fuzzy
 msgid "Restart Remote Nginx Success"
 msgid "Restart Remote Nginx Success"
 msgstr "重新命名遠端站點成功"
 msgstr "重新命名遠端站點成功"
@@ -2993,7 +3040,7 @@ msgstr "執行中"
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/ConfigEditor.vue:271
 #: src/views/config/ConfigEditor.vue:271
 #: src/views/preference/components/Passkey.vue:130
 #: src/views/preference/components/Passkey.vue:130
-#: src/views/preference/Preference.vue:221
+#: src/views/preference/Preference.vue:228
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:127
 #: src/views/site/ngx_conf/directive/DirectiveEditorItem.vue:127
 #: src/views/site/site_edit/components/ConfigName.vue:52
 #: src/views/site/site_edit/components/ConfigName.vue:52
 #: src/views/site/site_edit/SiteEdit.vue:292
 #: src/views/site/site_edit/SiteEdit.vue:292
@@ -3011,40 +3058,42 @@ msgstr "儲存指令"
 msgid "Save error %{msg}"
 msgid "Save error %{msg}"
 msgstr "儲存錯誤 %{msg}"
 msgstr "儲存錯誤 %{msg}"
 
 
-#: src/components/Notification/notifications.ts:85 src/language/constants.ts:48
+#: src/components/Notification/notifications.ts:103
+#: src/language/constants.ts:48
 msgid "Save Remote Site Error"
 msgid "Save Remote Site Error"
 msgstr "儲存遠端站點時發生錯誤"
 msgstr "儲存遠端站點時發生錯誤"
 
 
-#: src/components/Notification/notifications.ts:89 src/language/constants.ts:47
+#: src/components/Notification/notifications.ts:107
+#: src/language/constants.ts:47
 msgid "Save Remote Site Success"
 msgid "Save Remote Site Success"
 msgstr "儲存遠端站點成功"
 msgstr "儲存遠端站點成功"
 
 
-#: src/components/Notification/notifications.ts:127
+#: src/components/Notification/notifications.ts:145
 #, fuzzy
 #, fuzzy
 msgid "Save Remote Stream Error"
 msgid "Save Remote Stream Error"
 msgstr "儲存遠端站點時發生錯誤"
 msgstr "儲存遠端站點時發生錯誤"
 
 
-#: src/components/Notification/notifications.ts:131
+#: src/components/Notification/notifications.ts:149
 #, fuzzy
 #, fuzzy
 msgid "Save Remote Stream Success"
 msgid "Save Remote Stream Success"
 msgstr "儲存遠端站點成功"
 msgstr "儲存遠端站點成功"
 
 
-#: src/components/Notification/notifications.ts:86
+#: src/components/Notification/notifications.ts:104
 #, fuzzy
 #, fuzzy
 msgid "Save site %{name} to %{node} failed"
 msgid "Save site %{name} to %{node} failed"
 msgstr "成功將站點 %{site} 儲存至 %{node}"
 msgstr "成功將站點 %{site} 儲存至 %{node}"
 
 
-#: src/components/Notification/notifications.ts:90
+#: src/components/Notification/notifications.ts:108
 #, fuzzy
 #, fuzzy
 msgid "Save site %{name} to %{node} successfully"
 msgid "Save site %{name} to %{node} successfully"
 msgstr "成功將站點 %{site} 儲存至 %{node}"
 msgstr "成功將站點 %{site} 儲存至 %{node}"
 
 
-#: src/components/Notification/notifications.ts:128
+#: src/components/Notification/notifications.ts:146
 #, fuzzy
 #, fuzzy
 msgid "Save stream %{name} to %{node} failed"
 msgid "Save stream %{name} to %{node} failed"
 msgstr "部署 %{conf_name} 至 %{node_name} 失敗"
 msgstr "部署 %{conf_name} 至 %{node_name} 失敗"
 
 
-#: src/components/Notification/notifications.ts:132
+#: src/components/Notification/notifications.ts:150
 #, fuzzy
 #, fuzzy
 msgid "Save stream %{name} to %{node} successfully"
 msgid "Save stream %{name} to %{node} successfully"
 msgstr "成功將站點 %{site} 儲存至 %{node}"
 msgstr "成功將站點 %{site} 儲存至 %{node}"
@@ -3052,7 +3101,7 @@ msgstr "成功將站點 %{site} 儲存至 %{node}"
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:47
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:47
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:97
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:97
 #: src/views/certificate/CertificateEditor.vue:49
 #: src/views/certificate/CertificateEditor.vue:49
-#: src/views/preference/Preference.vue:123
+#: src/views/preference/Preference.vue:124
 msgid "Save successfully"
 msgid "Save successfully"
 msgstr "儲存成功"
 msgstr "儲存成功"
 
 
@@ -3072,6 +3121,10 @@ msgstr "用手機掃描二維碼將賬戶添加到應用程序中。"
 msgid "SDK"
 msgid "SDK"
 msgstr "SDK"
 msgstr "SDK"
 
 
+#: src/views/preference/components/ExternalNotify/dingtalk.ts:13
+msgid "Secret (Optional)"
+msgstr ""
+
 #: src/views/preference/components/TOTP.vue:109
 #: src/views/preference/components/TOTP.vue:109
 msgid "Secret has been copied"
 msgid "Secret has been copied"
 msgstr "密鑰已複製"
 msgstr "密鑰已複製"
@@ -3103,7 +3156,7 @@ msgstr "自我檢測"
 msgid "Send"
 msgid "Send"
 msgstr "傳送"
 msgstr "傳送"
 
 
-#: src/views/preference/Preference.vue:156
+#: src/views/preference/Preference.vue:157
 #, fuzzy
 #, fuzzy
 msgid "Server"
 msgid "Server"
 msgstr "伺服器資訊"
 msgstr "伺服器資訊"
@@ -3112,6 +3165,11 @@ msgstr "伺服器資訊"
 msgid "Server Info"
 msgid "Server Info"
 msgstr "伺服器資訊"
 msgstr "伺服器資訊"
 
 
+#: src/views/preference/components/ExternalNotify/bark.ts:13
+#, fuzzy
+msgid "Server URL"
+msgstr "伺服器資訊"
+
 #: src/views/site/cert/components/ObtainCert.vue:107
 #: src/views/site/cert/components/ObtainCert.vue:107
 msgid "server_name not found in directives"
 msgid "server_name not found in directives"
 msgstr "在指令中未找到 server_name"
 msgstr "在指令中未找到 server_name"
@@ -3284,7 +3342,7 @@ msgstr ""
 #: src/views/certificate/ACMEUser.vue:65
 #: src/views/certificate/ACMEUser.vue:65
 #: src/views/certificate/CertificateList/certColumns.tsx:65
 #: src/views/certificate/CertificateList/certColumns.tsx:65
 #: src/views/environments/list/envColumns.tsx:44
 #: src/views/environments/list/envColumns.tsx:44
-#: src/views/site/site_edit/RightSettings.vue:56
+#: src/views/site/site_edit/RightSettings.vue:55
 #: src/views/site/site_list/columns.tsx:80 src/views/stream/StreamList.vue:47
 #: src/views/site/site_list/columns.tsx:80 src/views/stream/StreamList.vue:47
 msgid "Status"
 msgid "Status"
 msgstr "狀態"
 msgstr "狀態"
@@ -3361,38 +3419,38 @@ msgstr "同步"
 msgid "Sync Certificate"
 msgid "Sync Certificate"
 msgstr "同步憑證"
 msgstr "同步憑證"
 
 
-#: src/components/Notification/notifications.ts:10
+#: src/components/Notification/notifications.ts:28
 #, fuzzy
 #, fuzzy
 msgid "Sync Certificate %{cert_name} to %{env_name} failed"
 msgid "Sync Certificate %{cert_name} to %{env_name} failed"
 msgstr "同步憑證 %{cert_name} 到 %{env_name} 成功"
 msgstr "同步憑證 %{cert_name} 到 %{env_name} 成功"
 
 
-#: src/components/Notification/notifications.ts:14
+#: src/components/Notification/notifications.ts:32
 msgid "Sync Certificate %{cert_name} to %{env_name} successfully"
 msgid "Sync Certificate %{cert_name} to %{env_name} successfully"
 msgstr "同步憑證 %{cert_name} 到 %{env_name} 成功"
 msgstr "同步憑證 %{cert_name} 到 %{env_name} 成功"
 
 
-#: src/components/Notification/notifications.ts:9 src/language/constants.ts:39
+#: src/components/Notification/notifications.ts:27 src/language/constants.ts:39
 msgid "Sync Certificate Error"
 msgid "Sync Certificate Error"
 msgstr "同步憑證錯誤"
 msgstr "同步憑證錯誤"
 
 
-#: src/components/Notification/notifications.ts:13 src/language/constants.ts:38
+#: src/components/Notification/notifications.ts:31 src/language/constants.ts:38
 msgid "Sync Certificate Success"
 msgid "Sync Certificate Success"
 msgstr "同步憑證成功"
 msgstr "同步憑證成功"
 
 
-#: src/components/Notification/notifications.ts:20
+#: src/components/Notification/notifications.ts:38
 #, fuzzy
 #, fuzzy
 msgid "Sync config %{config_name} to %{env_name} failed"
 msgid "Sync config %{config_name} to %{env_name} failed"
 msgstr "同步配置 %{config_name} 到 %{env_name} 成功"
 msgstr "同步配置 %{config_name} 到 %{env_name} 成功"
 
 
-#: src/components/Notification/notifications.ts:24
+#: src/components/Notification/notifications.ts:42
 #, fuzzy
 #, fuzzy
 msgid "Sync config %{config_name} to %{env_name} successfully"
 msgid "Sync config %{config_name} to %{env_name} successfully"
 msgstr "同步配置 %{config_name} 到 %{env_name} 成功"
 msgstr "同步配置 %{config_name} 到 %{env_name} 成功"
 
 
-#: src/components/Notification/notifications.ts:19 src/language/constants.ts:45
+#: src/components/Notification/notifications.ts:37 src/language/constants.ts:45
 msgid "Sync Config Error"
 msgid "Sync Config Error"
 msgstr "同步配置錯誤"
 msgstr "同步配置錯誤"
 
 
-#: src/components/Notification/notifications.ts:23 src/language/constants.ts:44
+#: src/components/Notification/notifications.ts:41 src/language/constants.ts:44
 msgid "Sync Config Success"
 msgid "Sync Config Success"
 msgstr "同步配置成功"
 msgstr "同步配置成功"
 
 
@@ -3401,8 +3459,8 @@ msgstr "同步配置成功"
 msgid "Sync Nodes"
 msgid "Sync Nodes"
 msgstr "同步節點"
 msgstr "同步節點"
 
 
-#: src/views/site/site_edit/RightSettings.vue:102
-#: src/views/site/site_edit/RightSettings.vue:89
+#: src/views/site/site_edit/RightSettings.vue:101
+#: src/views/site/site_edit/RightSettings.vue:88
 #: src/views/stream/components/RightSettings.vue:111
 #: src/views/stream/components/RightSettings.vue:111
 #: src/views/stream/components/RightSettings.vue:124
 #: src/views/stream/components/RightSettings.vue:124
 msgid "Sync strategy"
 msgid "Sync strategy"
@@ -3412,7 +3470,7 @@ msgstr "同步策略"
 msgid "Sync to"
 msgid "Sync to"
 msgstr "同步到"
 msgstr "同步到"
 
 
-#: src/views/site/site_edit/RightSettings.vue:86
+#: src/views/site/site_edit/RightSettings.vue:85
 #: src/views/stream/components/RightSettings.vue:108
 #: src/views/stream/components/RightSettings.vue:108
 msgid "Synchronization"
 msgid "Synchronization"
 msgstr "同步"
 msgstr "同步"
@@ -3444,7 +3502,11 @@ msgstr "Nginx 重啟成功"
 msgid "Task not found"
 msgid "Task not found"
 msgstr "找不到任務"
 msgstr "找不到任務"
 
 
-#: src/routes/modules/terminal.ts:10 src/views/preference/Preference.vue:180
+#: src/views/preference/components/ExternalNotify/telegram.ts:5
+msgid "Telegram"
+msgstr ""
+
+#: src/routes/modules/terminal.ts:10 src/views/preference/Preference.vue:187
 #: src/views/terminal/Terminal.vue:129
 #: src/views/terminal/Terminal.vue:129
 msgid "Terminal"
 msgid "Terminal"
 msgstr "終端機"
 msgstr "終端機"
@@ -3694,6 +3756,7 @@ msgstr "需要多重因素驗證"
 #: src/views/certificate/CertificateList/certColumns.tsx:25
 #: src/views/certificate/CertificateList/certColumns.tsx:25
 #: src/views/nginx_log/NginxLogList.vue:21
 #: src/views/nginx_log/NginxLogList.vue:21
 #: src/views/notification/notificationColumns.tsx:9
 #: src/views/notification/notificationColumns.tsx:9
+#: src/views/preference/components/ExternalNotify/columns.ts:17
 msgid "Type"
 msgid "Type"
 msgstr "類型"
 msgstr "類型"
 
 
@@ -3710,7 +3773,7 @@ msgstr "更新成功"
 #: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:325
 #: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:325
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/environments/list/envColumns.tsx:90
-#: src/views/site/site_edit/RightSettings.vue:76
+#: src/views/site/site_edit/RightSettings.vue:75
 #: src/views/site/site_list/columns.tsx:110
 #: src/views/site/site_list/columns.tsx:110
 #: src/views/stream/components/RightSettings.vue:99
 #: src/views/stream/components/RightSettings.vue:99
 #: src/views/stream/StreamList.vue:67 src/views/user/userColumns.tsx:54
 #: src/views/stream/StreamList.vue:67 src/views/user/userColumns.tsx:54
@@ -3869,7 +3932,7 @@ msgstr ""
 "啟用後,Nginx UI 將在啟動時自動重新註冊使用者。通常,除非您處於開發環境並使"
 "啟用後,Nginx UI 將在啟動時自動重新註冊使用者。通常,除非您處於開發環境並使"
 "用 Pebble 作為 CA,否則不建議啟用此功能。"
 "用 Pebble 作為 CA,否則不建議啟用此功能。"
 
 
-#: src/views/site/site_edit/RightSettings.vue:92
+#: src/views/site/site_edit/RightSettings.vue:91
 #, fuzzy
 #, fuzzy
 msgid ""
 msgid ""
 "When you enable/disable, delete, or save this site, the nodes set in the "
 "When you enable/disable, delete, or save this site, the nodes set in the "
@@ -4160,9 +4223,6 @@ msgstr "您的通行密鑰"
 #~ msgid "Theme"
 #~ msgid "Theme"
 #~ msgstr "主題"
 #~ msgstr "主題"
 
 
-#~ msgid "Token"
-#~ msgstr "Token"
-
 #~ msgid "Git"
 #~ msgid "Git"
 #~ msgstr "Git"
 #~ msgstr "Git"
 
 

+ 25 - 0
app/src/views/preference/ExternalNotify.vue

@@ -0,0 +1,25 @@
+<script setup lang="ts">
+import externalNotify from '@/api/external_notify'
+import { StdCurd } from '@/components/StdDesign/StdDataDisplay'
+import columns from './components/ExternalNotify/columns'
+import ExternalNotifyEditor from './components/ExternalNotify/ExternalNotifyEditor.vue'
+</script>
+
+<template>
+  <StdCurd
+    :title="$gettext('External Notify')"
+    :columns="columns"
+    :api="externalNotify"
+    disable-view
+    disable-query-params
+  >
+    <template #edit="{ data }">
+      <ExternalNotifyEditor
+        v-model="data.config"
+        :type="data.type"
+      />
+    </template>
+  </StdCurd>
+</template>
+
+<style scoped lang="less"></style>

+ 9 - 2
app/src/views/preference/Preference.vue

@@ -7,6 +7,7 @@ import { useSettingsStore } from '@/pinia'
 import AppSettings from '@/views/preference/AppSettings.vue'
 import AppSettings from '@/views/preference/AppSettings.vue'
 import AuthSettings from '@/views/preference/AuthSettings.vue'
 import AuthSettings from '@/views/preference/AuthSettings.vue'
 import CertSettings from '@/views/preference/CertSettings.vue'
 import CertSettings from '@/views/preference/CertSettings.vue'
+import ExternalNotify from '@/views/preference/ExternalNotify.vue'
 import HTTPSettings from '@/views/preference/HTTPSettings.vue'
 import HTTPSettings from '@/views/preference/HTTPSettings.vue'
 import LogrotateSettings from '@/views/preference/LogrotateSettings.vue'
 import LogrotateSettings from '@/views/preference/LogrotateSettings.vue'
 import NginxSettings from '@/views/preference/NginxSettings.vue'
 import NginxSettings from '@/views/preference/NginxSettings.vue'
@@ -163,6 +164,12 @@ onMounted(() => {
         >
         >
           <AppSettings />
           <AppSettings />
         </ATabPane>
         </ATabPane>
+        <ATabPane
+          key="external_notify"
+          :tab="$gettext('External Notify')"
+        >
+          <ExternalNotify />
+        </ATabPane>
         <ATabPane
         <ATabPane
           key="node"
           key="node"
           :tab="$gettext('Node')"
           :tab="$gettext('Node')"
@@ -213,7 +220,7 @@ onMounted(() => {
         </ATabPane>
         </ATabPane>
       </ATabs>
       </ATabs>
     </div>
     </div>
-    <FooterToolBar>
+    <FooterToolBar v-if="activeKey !== 'external_notify'">
       <AButton
       <AButton
         type="primary"
         type="primary"
         @click="save"
         @click="save"
@@ -227,7 +234,7 @@ onMounted(() => {
 <style lang="less" scoped>
 <style lang="less" scoped>
 .preference-container {
 .preference-container {
   width: 100%;
   width: 100%;
-  max-width: 750px;
+  max-width: 850px;
   margin: 0 auto;
   margin: 0 auto;
   padding: 0 10px;
   padding: 0 10px;
 }
 }

+ 46 - 0
app/src/views/preference/components/ExternalNotify/ExternalNotifyEditor.vue

@@ -0,0 +1,46 @@
+<script setup lang="ts">
+import type { Column } from '@/components/StdDesign/types'
+import type { ExternalNotifyConfig } from './types'
+import StdDataEntry, { input } from '@/components/StdDesign/StdDataEntry'
+import configMap from './index'
+
+const props = defineProps<{
+  type?: string
+}>()
+
+const modelValue = defineModel<Record<string, string>>({ default: reactive({}) })
+
+const currentConfig = computed<ExternalNotifyConfig | undefined>(() => {
+  return configMap[props.type?.toLowerCase() ?? '']
+})
+
+const columns = computed<Column[]>(() => {
+  if (!currentConfig.value)
+    return []
+
+  return currentConfig.value.config.map(item => ({
+    title: item.label,
+    dataIndex: item.key,
+    key: item.key,
+    edit: {
+      type: input,
+      config: {
+        label: item.label,
+        required: true,
+      },
+    },
+  }))
+})
+</script>
+
+<template>
+  <StdDataEntry
+    v-if="currentConfig"
+    v-model:data-source="modelValue"
+    :data-list="columns"
+  />
+</template>
+
+<style scoped lang="less">
+
+</style>

+ 18 - 0
app/src/views/preference/components/ExternalNotify/bark.ts

@@ -0,0 +1,18 @@
+// This file is auto-generated by notification generator. DO NOT EDIT.
+import type { ExternalNotifyConfig } from './types'
+
+const BarkConfig: ExternalNotifyConfig = {
+  name: () => $gettext('Bark'),
+  config: [
+    {
+      key: 'device_key',
+      label: () => $gettext('Device Key'),
+    },
+    {
+      key: 'server_url',
+      label: () => $gettext('Server URL'),
+    },
+  ],
+}
+
+export default BarkConfig

+ 50 - 0
app/src/views/preference/components/ExternalNotify/columns.ts

@@ -0,0 +1,50 @@
+import type { Column } from '@/components/StdDesign/types'
+import { datetime, mask } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
+import { select } from '@/components/StdDesign/StdDataEntry'
+import gettext from '@/gettext'
+import configMap from './index'
+
+const languageAvailable = gettext.available
+
+const configTypeMask = Object.keys(configMap).reduce((acc, key) => {
+  acc[key] = configMap[key].name()
+  return acc
+}, {})
+
+const columns: Column[] = [
+  {
+    dataIndex: 'type',
+    title: () => $gettext('Type'),
+    customRender: mask(configTypeMask),
+    edit: {
+      type: select,
+      mask: configTypeMask,
+      config: {
+        required: true,
+      },
+    },
+  },
+  {
+    dataIndex: 'language',
+    title: () => $gettext('Language'),
+    customRender: mask(languageAvailable),
+    edit: {
+      type: select,
+      mask: languageAvailable,
+      config: {
+        required: true,
+      },
+    },
+  },
+  {
+    dataIndex: 'created_at',
+    title: () => $gettext('Created at'),
+    customRender: datetime,
+  },
+  {
+    dataIndex: 'action',
+    title: () => $gettext('Action'),
+  },
+]
+
+export default columns

+ 18 - 0
app/src/views/preference/components/ExternalNotify/dingtalk.ts

@@ -0,0 +1,18 @@
+// This file is auto-generated by notification generator. DO NOT EDIT.
+import type { ExternalNotifyConfig } from './types'
+
+const DingTalkConfig: ExternalNotifyConfig = {
+  name: () => $gettext('DingTalk'),
+  config: [
+    {
+      key: 'access_token',
+      label: () => $gettext('Access Token'),
+    },
+    {
+      key: 'secret',
+      label: () => $gettext('Secret (Optional)'),
+    },
+  ],
+}
+
+export default DingTalkConfig

+ 12 - 0
app/src/views/preference/components/ExternalNotify/index.ts

@@ -0,0 +1,12 @@
+// This file is auto-generated by notification generator. DO NOT EDIT.
+import BarkConfig from './bark'
+import DingTalkConfig from './dingtalk'
+import TelegramConfig from './telegram'
+
+const configMap = {
+  bark: BarkConfig,
+  dingtalk: DingTalkConfig,
+  telegram: TelegramConfig,
+}
+
+export default configMap

+ 18 - 0
app/src/views/preference/components/ExternalNotify/telegram.ts

@@ -0,0 +1,18 @@
+// This file is auto-generated by notification generator. DO NOT EDIT.
+import type { ExternalNotifyConfig } from './types'
+
+const TelegramConfig: ExternalNotifyConfig = {
+  name: () => $gettext('Telegram'),
+  config: [
+    {
+      key: 'bot_token',
+      label: () => $gettext('Bot Token'),
+    },
+    {
+      key: 'chat_id',
+      label: () => $gettext('Chat ID'),
+    },
+  ],
+}
+
+export default TelegramConfig

+ 9 - 0
app/src/views/preference/components/ExternalNotify/types.d.ts

@@ -0,0 +1,9 @@
+export interface ExternalNotifyConfigItem {
+  key: string
+  label: () => string
+}
+
+export interface ExternalNotifyConfig {
+  name: () => string
+  config: ExternalNotifyConfigItem[]
+}

+ 269 - 0
cmd/external_notifier/generate.go

@@ -0,0 +1,269 @@
+package main
+
+import (
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"go/token"
+	"os"
+	"path/filepath"
+	"regexp"
+	"sort"
+	"strings"
+	"text/template"
+)
+
+// Structure to hold extracted notifier information
+type NotifierInfo struct {
+	Name      string
+	Fields    []FieldInfo
+	FileName  string
+	ConfigKey string
+}
+
+// Structure to hold field information for notifier
+type FieldInfo struct {
+	Name  string
+	Key   string
+	Title string
+}
+
+// Template for the TypeScript config file
+const tsConfigTemplate = `// This file is auto-generated by notification generator. DO NOT EDIT.
+import type { ExternalNotifyConfig } from './types'
+
+const {{.Name}}Config: ExternalNotifyConfig = {
+  name: () => $gettext('{{.Name}}'),
+  config: [
+    {{- range .Fields}}
+    {
+      key: '{{.Key}}',
+      label: () => $gettext('{{.Title}}'),
+    },
+    {{- end}}
+  ],
+}
+
+export default {{.Name}}Config
+`
+
+// Regular expression to extract @external_notifier annotation
+var externalNotifierRegex = regexp.MustCompile(`@external_notifier\((\w+)\)`)
+
+func main() {
+	if err := GenerateExternalNotifiers(); err != nil {
+		fmt.Printf("error generating external notifier configs: %v\n", err)
+	}
+}
+
+// GenerateExternalNotifiers generates TypeScript config files for external notifiers
+func GenerateExternalNotifiers() error {
+	fmt.Println("Generating external notifier configs...")
+
+	// Notification package path
+	notificationPkgPath := "internal/notification"
+	outputDir := "app/src/views/preference/components/ExternalNotify"
+
+	// Create output directory if it doesn't exist
+	if err := os.MkdirAll(outputDir, 0755); err != nil {
+		return fmt.Errorf("error creating output directory: %w", err)
+	}
+
+	// Get all Go files in the notification package
+	files, err := filepath.Glob(filepath.Join(notificationPkgPath, "*.go"))
+	if err != nil {
+		return fmt.Errorf("error scanning notification package: %w", err)
+	}
+
+	// Collect all notifier info
+	notifiers := []NotifierInfo{}
+
+	for _, file := range files {
+		notifier, found := extractNotifierInfo(file)
+		if found {
+			notifiers = append(notifiers, notifier)
+			fmt.Printf("Found notifier: %s in %s\n", notifier.Name, file)
+		}
+	}
+
+	// Generate TypeScript config files
+	for _, notifier := range notifiers {
+		if err := generateTSConfig(notifier, outputDir); err != nil {
+			return fmt.Errorf("error generating config for %s: %w", notifier.Name, err)
+		}
+	}
+
+	// Update index.ts
+	if err := updateIndexFile(notifiers, outputDir); err != nil {
+		return fmt.Errorf("error updating index.ts: %w", err)
+	}
+
+	fmt.Println("Generation completed successfully!")
+	return nil
+}
+
+// Extract notifier information from a Go file
+func extractNotifierInfo(filePath string) (NotifierInfo, bool) {
+	// Create the FileSet
+	fset := token.NewFileSet()
+
+	// Parse the file
+	file, err := parser.ParseFile(fset, filePath, nil, parser.ParseComments)
+	if err != nil {
+		fmt.Printf("Error parsing file %s: %v\n", filePath, err)
+		return NotifierInfo{}, false
+	}
+
+	var notifierInfo NotifierInfo
+	found := false
+
+	// Look for the type declaration with the @external_notifier annotation
+	for _, decl := range file.Decls {
+		genDecl, ok := decl.(*ast.GenDecl)
+		if !ok || genDecl.Tok != token.TYPE {
+			continue
+		}
+
+		for _, spec := range genDecl.Specs {
+			typeSpec, ok := spec.(*ast.TypeSpec)
+			if !ok {
+				continue
+			}
+
+			structType, ok := typeSpec.Type.(*ast.StructType)
+			if !ok {
+				continue
+			}
+
+			// Check if we have a comment with @external_notifier
+			if genDecl.Doc != nil {
+				for _, comment := range genDecl.Doc.List {
+					matches := externalNotifierRegex.FindStringSubmatch(comment.Text)
+					if len(matches) > 1 {
+						notifierInfo.Name = matches[1]
+						notifierInfo.ConfigKey = strings.ToLower(typeSpec.Name.Name)
+						notifierInfo.FileName = strings.ToLower(matches[1])
+						found = true
+
+						// Extract fields
+						for _, field := range structType.Fields.List {
+							if len(field.Names) > 0 {
+								fieldName := field.Names[0].Name
+
+								// Get json tag and title from field tags
+								var jsonKey, title string
+								if field.Tag != nil {
+									tagValue := strings.Trim(field.Tag.Value, "`")
+
+									// Extract json key
+									jsonRegex := regexp.MustCompile(`json:"([^"]+)"`)
+									jsonMatches := jsonRegex.FindStringSubmatch(tagValue)
+									if len(jsonMatches) > 1 {
+										jsonKey = jsonMatches[1]
+									}
+
+									// Extract title
+									titleRegex := regexp.MustCompile(`title:"([^"]+)"`)
+									titleMatches := titleRegex.FindStringSubmatch(tagValue)
+									if len(titleMatches) > 1 {
+										title = titleMatches[1]
+									}
+								}
+
+								if jsonKey == "" {
+									jsonKey = strings.ToLower(fieldName)
+								}
+
+								if title == "" {
+									title = fieldName
+								}
+
+								notifierInfo.Fields = append(notifierInfo.Fields, FieldInfo{
+									Name:  fieldName,
+									Key:   jsonKey,
+									Title: title,
+								})
+							}
+						}
+						break
+					}
+				}
+			}
+
+			if found {
+				break
+			}
+		}
+
+		if found {
+			break
+		}
+	}
+
+	return notifierInfo, found
+}
+
+// Generate TypeScript config file for a notifier
+func generateTSConfig(notifier NotifierInfo, outputDir string) error {
+	// Create template
+	tmpl, err := template.New("tsConfig").Parse(tsConfigTemplate)
+	if err != nil {
+		return fmt.Errorf("error creating template: %w", err)
+	}
+
+	// Create output file
+	outputFile := filepath.Join(outputDir, notifier.FileName+".ts")
+	file, err := os.Create(outputFile)
+	if err != nil {
+		return fmt.Errorf("error creating output file %s: %w", outputFile, err)
+	}
+	defer file.Close()
+
+	// Execute template
+	err = tmpl.Execute(file, notifier)
+	if err != nil {
+		return fmt.Errorf("error executing template: %w", err)
+	}
+
+	fmt.Printf("Generated TypeScript config for %s at %s\n", notifier.Name, outputFile)
+	return nil
+}
+
+// Update index.ts file
+func updateIndexFile(notifiers []NotifierInfo, outputDir string) error {
+	// Create content for index.ts
+	var imports strings.Builder
+	var configMap strings.Builder
+
+	// Sort notifiers alphabetically by name for stable output
+	sort.Slice(notifiers, func(i, j int) bool {
+		return notifiers[i].Name < notifiers[j].Name
+	})
+
+	for _, notifier := range notifiers {
+		fileName := notifier.FileName
+		configName := notifier.Name + "Config"
+
+		imports.WriteString(fmt.Sprintf("import %s from './%s'\n", configName, fileName))
+	}
+
+	// Generate the map
+	configMap.WriteString("const configMap = {\n")
+	for _, notifier := range notifiers {
+		configMap.WriteString(fmt.Sprintf("  %s: %sConfig", strings.ToLower(notifier.Name), notifier.Name))
+		configMap.WriteString(",\n")
+	}
+	configMap.WriteString("}\n")
+
+	content := fmt.Sprintf("// This file is auto-generated by notification generator. DO NOT EDIT.\n%s\n%s\nexport default configMap\n", imports.String(), configMap.String())
+
+	// Write to index.ts
+	indexPath := filepath.Join(outputDir, "index.ts")
+	err := os.WriteFile(indexPath, []byte(content), 0644)
+	if err != nil {
+		return fmt.Errorf("error writing index.ts: %w", err)
+	}
+
+	fmt.Printf("Updated index.ts at %s\n", indexPath)
+	return nil
+}

+ 3 - 0
gen.sh

@@ -9,3 +9,6 @@ go run cmd/ngx_dir_index/ngx_dir_index.go ./internal/nginx/nginx_directives.json
 
 
 # generate notification texts
 # generate notification texts
 go run cmd/notification/generate.go
 go run cmd/notification/generate.go
+
+# generate external notifier configs
+go run cmd/external_notifier/generate.go

+ 11 - 5
go.mod

@@ -3,7 +3,7 @@ module github.com/0xJacky/Nginx-UI
 go 1.24.2
 go 1.24.2
 
 
 require (
 require (
-	github.com/0xJacky/pofile v0.2.1
+	github.com/0xJacky/pofile v1.0.0
 	github.com/BurntSushi/toml v1.5.0
 	github.com/BurntSushi/toml v1.5.0
 	github.com/caarlos0/env/v11 v11.3.1
 	github.com/caarlos0/env/v11 v11.3.1
 	github.com/casdoor/casdoor-go-sdk v1.5.0
 	github.com/casdoor/casdoor-go-sdk v1.5.0
@@ -27,6 +27,7 @@ require (
 	github.com/jpillora/overseer v1.1.6
 	github.com/jpillora/overseer v1.1.6
 	github.com/lib/pq v1.10.9
 	github.com/lib/pq v1.10.9
 	github.com/minio/selfupdate v0.6.0
 	github.com/minio/selfupdate v0.6.0
+	github.com/nikoksr/notify v1.3.0
 	github.com/nxadm/tail v1.4.11
 	github.com/nxadm/tail v1.4.11
 	github.com/pkg/errors v0.9.1
 	github.com/pkg/errors v0.9.1
 	github.com/pquerna/otp v1.4.0
 	github.com/pquerna/otp v1.4.0
@@ -58,7 +59,7 @@ require (
 	github.com/AdamSLevy/jsonrpc2/v14 v14.1.0 // indirect
 	github.com/AdamSLevy/jsonrpc2/v14 v14.1.0 // indirect
 	github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect
 	github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect
 	github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 // indirect
 	github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 // indirect
-	github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.2 // indirect
+	github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0 // indirect
 	github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 // indirect
 	github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 // indirect
 	github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0 // indirect
 	github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0 // indirect
 	github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.3.0 // indirect
 	github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.3.0 // indirect
@@ -93,6 +94,7 @@ require (
 	github.com/aws/aws-sdk-go-v2/service/sts v1.33.18 // indirect
 	github.com/aws/aws-sdk-go-v2/service/sts v1.33.18 // indirect
 	github.com/aws/smithy-go v1.22.3 // indirect
 	github.com/aws/smithy-go v1.22.3 // indirect
 	github.com/benbjohnson/clock v1.3.5 // indirect
 	github.com/benbjohnson/clock v1.3.5 // indirect
+	github.com/blinkbean/dingtalk v1.1.3 // indirect
 	github.com/boombuler/barcode v1.0.2 // indirect
 	github.com/boombuler/barcode v1.0.2 // indirect
 	github.com/bsm/redislock v0.9.4 // indirect
 	github.com/bsm/redislock v0.9.4 // indirect
 	github.com/bytedance/sonic v1.13.2 // indirect
 	github.com/bytedance/sonic v1.13.2 // indirect
@@ -123,6 +125,7 @@ require (
 	github.com/go-playground/locales v0.14.1 // indirect
 	github.com/go-playground/locales v0.14.1 // indirect
 	github.com/go-playground/universal-translator v0.18.1 // indirect
 	github.com/go-playground/universal-translator v0.18.1 // indirect
 	github.com/go-sql-driver/mysql v1.9.2 // indirect
 	github.com/go-sql-driver/mysql v1.9.2 // indirect
+	github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible // indirect
 	github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
 	github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
 	github.com/go-webauthn/x v0.1.20 // indirect
 	github.com/go-webauthn/x v0.1.20 // indirect
 	github.com/goccy/go-json v0.10.5 // indirect
 	github.com/goccy/go-json v0.10.5 // indirect
@@ -145,6 +148,7 @@ require (
 	github.com/hashicorp/go-uuid v1.0.3 // indirect
 	github.com/hashicorp/go-uuid v1.0.3 // indirect
 	github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.143 // indirect
 	github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.143 // indirect
 	github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df // indirect
 	github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df // indirect
+	github.com/inconshreveable/mousetrap v1.1.0 // indirect
 	github.com/infobloxopen/infoblox-go-client v1.1.1 // indirect
 	github.com/infobloxopen/infoblox-go-client v1.1.1 // indirect
 	github.com/itchyny/timefmt-go v0.1.6 // indirect
 	github.com/itchyny/timefmt-go v0.1.6 // indirect
 	github.com/jackc/pgio v1.0.0 // indirect
 	github.com/jackc/pgio v1.0.0 // indirect
@@ -193,7 +197,7 @@ require (
 	github.com/nrdcg/porkbun v0.4.0 // indirect
 	github.com/nrdcg/porkbun v0.4.0 // indirect
 	github.com/nzdjb/go-metaname v1.0.0 // indirect
 	github.com/nzdjb/go-metaname v1.0.0 // indirect
 	github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect
 	github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect
-	github.com/oracle/oci-go-sdk/v65 v65.88.1 // indirect
+	github.com/oracle/oci-go-sdk/v65 v65.89.0 // indirect
 	github.com/ovh/go-ovh v1.7.0 // indirect
 	github.com/ovh/go-ovh v1.7.0 // indirect
 	github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
 	github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
 	github.com/pelletier/go-toml/v2 v2.2.4 // indirect
 	github.com/pelletier/go-toml/v2 v2.2.4 // indirect
@@ -221,10 +225,12 @@ require (
 	github.com/sony/sonyflake v1.2.0 // indirect
 	github.com/sony/sonyflake v1.2.0 // indirect
 	github.com/sourcegraph/conc v0.3.0 // indirect
 	github.com/sourcegraph/conc v0.3.0 // indirect
 	github.com/spf13/afero v1.14.0 // indirect
 	github.com/spf13/afero v1.14.0 // indirect
+	github.com/spf13/cobra v1.9.1 // indirect
 	github.com/spf13/pflag v1.0.6 // indirect
 	github.com/spf13/pflag v1.0.6 // indirect
 	github.com/spf13/viper v1.20.1 // indirect
 	github.com/spf13/viper v1.20.1 // indirect
 	github.com/stretchr/objx v0.5.2 // indirect
 	github.com/stretchr/objx v0.5.2 // indirect
 	github.com/subosito/gotenv v1.6.0 // indirect
 	github.com/subosito/gotenv v1.6.0 // indirect
+	github.com/technoweenie/multipartstreamer v1.0.1 // indirect
 	github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1140 // indirect
 	github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1140 // indirect
 	github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1136 // indirect
 	github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1136 // indirect
 	github.com/tjfoc/gmsm v1.4.1 // indirect
 	github.com/tjfoc/gmsm v1.4.1 // indirect
@@ -238,7 +244,7 @@ require (
 	github.com/uozi-tech/cosy-driver-postgres v0.2.1 // indirect
 	github.com/uozi-tech/cosy-driver-postgres v0.2.1 // indirect
 	github.com/vinyldns/go-vinyldns v0.9.16 // indirect
 	github.com/vinyldns/go-vinyldns v0.9.16 // indirect
 	github.com/volcengine/volc-sdk-golang v1.0.202 // indirect
 	github.com/volcengine/volc-sdk-golang v1.0.202 // indirect
-	github.com/vultr/govultr/v3 v3.18.0 // indirect
+	github.com/vultr/govultr/v3 v3.19.1 // indirect
 	github.com/x448/float16 v0.8.4 // indirect
 	github.com/x448/float16 v0.8.4 // indirect
 	github.com/yandex-cloud/go-genproto v0.0.0-20250325081613-cd85d9003939 // indirect
 	github.com/yandex-cloud/go-genproto v0.0.0-20250325081613-cd85d9003939 // indirect
 	github.com/yandex-cloud/go-sdk v0.0.0-20250325134853-dcb34ef70818 // indirect
 	github.com/yandex-cloud/go-sdk v0.0.0-20250325134853-dcb34ef70818 // indirect
@@ -270,7 +276,7 @@ require (
 	google.golang.org/protobuf v1.36.6 // indirect
 	google.golang.org/protobuf v1.36.6 // indirect
 	gopkg.in/inf.v0 v0.9.1 // indirect
 	gopkg.in/inf.v0 v0.9.1 // indirect
 	gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
 	gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
-	gopkg.in/ns1/ns1-go.v2 v2.14.1 // indirect
+	gopkg.in/ns1/ns1-go.v2 v2.14.2 // indirect
 	gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
 	gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect

+ 23 - 0
go.sum

@@ -612,6 +612,8 @@ gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zum
 git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc=
 git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc=
 github.com/0xJacky/pofile v0.2.1 h1:ceNyprJOpo7wPPR0rCOuR1gfjYiS8t9YBc73tSLnlDc=
 github.com/0xJacky/pofile v0.2.1 h1:ceNyprJOpo7wPPR0rCOuR1gfjYiS8t9YBc73tSLnlDc=
 github.com/0xJacky/pofile v0.2.1/go.mod h1:hOZmte1hWostNs9KCwFRhKM7hf0d19zfWosopngij74=
 github.com/0xJacky/pofile v0.2.1/go.mod h1:hOZmte1hWostNs9KCwFRhKM7hf0d19zfWosopngij74=
+github.com/0xJacky/pofile v1.0.0 h1:ZjfpvLlouhnzOsSGhJ/dmqp5DkKg7XGjuulAAXVnhkE=
+github.com/0xJacky/pofile v1.0.0/go.mod h1:qq7YtcX4V35EBfOypsYLuLO7hCBExAH9q7xOxTqv2lQ=
 github.com/AdamSLevy/jsonrpc2/v14 v14.1.0 h1:Dy3M9aegiI7d7PF1LUdjbVigJReo+QOceYsMyFh9qoE=
 github.com/AdamSLevy/jsonrpc2/v14 v14.1.0 h1:Dy3M9aegiI7d7PF1LUdjbVigJReo+QOceYsMyFh9qoE=
 github.com/AdamSLevy/jsonrpc2/v14 v14.1.0/go.mod h1:ZakZtbCXxCz82NJvq7MoREtiQesnDfrtF6RFUGzQfLo=
 github.com/AdamSLevy/jsonrpc2/v14 v14.1.0/go.mod h1:ZakZtbCXxCz82NJvq7MoREtiQesnDfrtF6RFUGzQfLo=
 github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU=
 github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU=
@@ -622,6 +624,8 @@ github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 h1:Gt0j3wceWMwPmiazCa8MzMA0
 github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM=
 github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM=
 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.2 h1:F0gBpfdPLGsw+nsgk6aqqkZS1jiixa5WwFe3fk/T3Ys=
 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.2 h1:F0gBpfdPLGsw+nsgk6aqqkZS1jiixa5WwFe3fk/T3Ys=
 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.2/go.mod h1:SqINnQ9lVVdRlyC8cd1lCI0SdX4n2paeABd2K8ggfnE=
 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.2/go.mod h1:SqINnQ9lVVdRlyC8cd1lCI0SdX4n2paeABd2K8ggfnE=
+github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0 h1:OVoM452qUFBrX+URdH3VpR299ma4kfom0yB0URYky9g=
+github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0/go.mod h1:kUjrAo8bgEwLeZ/CmHqNl3Z/kPm7y6FKfxxK0izYUg4=
 github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY=
 github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY=
 github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8=
 github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8=
 github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY=
 github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY=
@@ -778,6 +782,8 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce
 github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
 github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
 github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
 github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
 github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
 github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
+github.com/blinkbean/dingtalk v1.1.3 h1:MbidFZYom7DTFHD/YIs+eaI7kRy52kmWE/sy0xjo6E4=
+github.com/blinkbean/dingtalk v1.1.3/go.mod h1:9BaLuGSBqY3vT5hstValh48DbsKO7vaHaJnG9pXwbto=
 github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
 github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
 github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
 github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
 github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
 github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
@@ -853,6 +859,7 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc
 github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
 github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
 github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
 github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
 github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
 github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
+github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
 github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
 github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
 github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s=
 github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s=
@@ -1018,6 +1025,8 @@ github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg78
 github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
 github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
 github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
 github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
 github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
 github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
+github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible h1:2cauKuaELYAEARXRkq2LrJ0yDDv1rW7+wrTEdVL3uaU=
+github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible/go.mod h1:qf9acutJ8cwBUhm1bqgz6Bei9/C/c93FPDljKWwsOgM=
 github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
 github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
 github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
 github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
 github.com/go-webauthn/webauthn v0.12.3 h1:hHQl1xkUuabUU9uS+ISNCMLs9z50p9mDUZI/FmkayNE=
 github.com/go-webauthn/webauthn v0.12.3 h1:hHQl1xkUuabUU9uS+ISNCMLs9z50p9mDUZI/FmkayNE=
@@ -1268,6 +1277,7 @@ github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:
 github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df h1:MZf03xP9WdakyXhOWuAD5uPK3wHh96wCsqe3hCMKh8E=
 github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df h1:MZf03xP9WdakyXhOWuAD5uPK3wHh96wCsqe3hCMKh8E=
 github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhKWFeDesPjMj+wCHReeknARU3wqlyN4=
 github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhKWFeDesPjMj+wCHReeknARU3wqlyN4=
 github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
 github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
+github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
 github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
 github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
 github.com/infobloxopen/infoblox-go-client v1.1.1 h1:728A6LbLjptj/7kZjHyIxQnm768PWHfGFm0HH8FnbtU=
 github.com/infobloxopen/infoblox-go-client v1.1.1 h1:728A6LbLjptj/7kZjHyIxQnm768PWHfGFm0HH8FnbtU=
@@ -1375,6 +1385,7 @@ github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1
 github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
 github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
 github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6 h1:IsMZxCuZqKuao2vNdfD82fjjgPLfyHLpR41Z88viRWs=
 github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6 h1:IsMZxCuZqKuao2vNdfD82fjjgPLfyHLpR41Z88viRWs=
 github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6/go.mod h1:3VeWNIJaW+O5xpRQbPp0Ybqu1vJd/pm7s2F473HRrkw=
 github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6/go.mod h1:3VeWNIJaW+O5xpRQbPp0Ybqu1vJd/pm7s2F473HRrkw=
+github.com/keybase/go-keychain v0.0.1 h1:way+bWYa6lDppZoZcgMbYsvC7GxljxrskdNInRtuthU=
 github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
 github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
 github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
 github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
@@ -1529,6 +1540,8 @@ github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV
 github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
 github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
 github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
 github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
 github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
 github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
+github.com/nikoksr/notify v1.3.0 h1:UxzfxzAYGQD9a5JYLBTVx0lFMxeHCke3rPCkfWdPgLs=
+github.com/nikoksr/notify v1.3.0/go.mod h1:Xor2hMmkvrCfkCKvXGbcrESez4brac2zQjhd6U2BbeM=
 github.com/nrdcg/auroradns v1.1.0 h1:KekGh8kmf2MNwqZVVYo/fw/ZONt8QMEmbMFOeljteWo=
 github.com/nrdcg/auroradns v1.1.0 h1:KekGh8kmf2MNwqZVVYo/fw/ZONt8QMEmbMFOeljteWo=
 github.com/nrdcg/auroradns v1.1.0/go.mod h1:O7tViUZbAcnykVnrGkXzIJTHoQCHcgalgAe6X1mzHfk=
 github.com/nrdcg/auroradns v1.1.0/go.mod h1:O7tViUZbAcnykVnrGkXzIJTHoQCHcgalgAe6X1mzHfk=
 github.com/nrdcg/bunny-go v0.0.0-20250327222614-988a091fc7ea h1:OSgRS4kqOs/WuxuFOObP2gwrenL4/qiKXQbQugr/Two=
 github.com/nrdcg/bunny-go v0.0.0-20250327222614-988a091fc7ea h1:OSgRS4kqOs/WuxuFOObP2gwrenL4/qiKXQbQugr/Two=
@@ -1585,6 +1598,8 @@ github.com/oracle/oci-go-sdk/v65 v65.88.0 h1:SbsGKsoRRxJxVTbwUyIPCPwPsHWb8aPgEEp
 github.com/oracle/oci-go-sdk/v65 v65.88.0/go.mod h1:IBEV9l1qBzUpo7zgGaRUhbB05BVfcDGYRFBCPlTcPp0=
 github.com/oracle/oci-go-sdk/v65 v65.88.0/go.mod h1:IBEV9l1qBzUpo7zgGaRUhbB05BVfcDGYRFBCPlTcPp0=
 github.com/oracle/oci-go-sdk/v65 v65.88.1 h1:Y9Y5jlQX8oVDe3UN+O4IcQnLN/aQmi4jR1/2RsXMN3M=
 github.com/oracle/oci-go-sdk/v65 v65.88.1 h1:Y9Y5jlQX8oVDe3UN+O4IcQnLN/aQmi4jR1/2RsXMN3M=
 github.com/oracle/oci-go-sdk/v65 v65.88.1/go.mod h1:u6XRPsw9tPziBh76K7GrrRXPa8P8W3BQeqJ6ZZt9VLA=
 github.com/oracle/oci-go-sdk/v65 v65.88.1/go.mod h1:u6XRPsw9tPziBh76K7GrrRXPa8P8W3BQeqJ6ZZt9VLA=
+github.com/oracle/oci-go-sdk/v65 v65.89.0 h1:Y2NRdvllV++3ebqc8v1bg7w9W1ktiMONKvW9k/bqk0M=
+github.com/oracle/oci-go-sdk/v65 v65.89.0/go.mod h1:u6XRPsw9tPziBh76K7GrrRXPa8P8W3BQeqJ6ZZt9VLA=
 github.com/ovh/go-ovh v1.7.0 h1:V14nF7FwDjQrZt9g7jzcvAAQ3HN6DNShRFRMC3jLoPw=
 github.com/ovh/go-ovh v1.7.0 h1:V14nF7FwDjQrZt9g7jzcvAAQ3HN6DNShRFRMC3jLoPw=
 github.com/ovh/go-ovh v1.7.0/go.mod h1:cTVDnl94z4tl8pP1uZ/8jlVxntjSIf09bNcQ5TJSC7c=
 github.com/ovh/go-ovh v1.7.0/go.mod h1:cTVDnl94z4tl8pP1uZ/8jlVxntjSIf09bNcQ5TJSC7c=
 github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
 github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
@@ -1759,6 +1774,8 @@ github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
 github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
 github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
 github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
 github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
 github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
 github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
+github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
+github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
 github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
 github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
 github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
 github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
 github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
 github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
@@ -1799,6 +1816,8 @@ github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69
 github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
 github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
 github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
 github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
 github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
 github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
+github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM=
+github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog=
 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1134 h1:NDCzSm7r8OZeWQje1FJNHM73Ku4QRrCP1GymfgZYLSM=
 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1134 h1:NDCzSm7r8OZeWQje1FJNHM73Ku4QRrCP1GymfgZYLSM=
 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1134/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1134/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1136/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1136/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
@@ -1855,6 +1874,8 @@ github.com/volcengine/volc-sdk-golang v1.0.202 h1:8H4Rq7jWfrKdW9p3j+ZyvGvVe796Ae
 github.com/volcengine/volc-sdk-golang v1.0.202/go.mod h1:stZX+EPgv1vF4nZwOlEe8iGcriUPRBKX8zA19gXycOQ=
 github.com/volcengine/volc-sdk-golang v1.0.202/go.mod h1:stZX+EPgv1vF4nZwOlEe8iGcriUPRBKX8zA19gXycOQ=
 github.com/vultr/govultr/v3 v3.18.0 h1:nTfxZW7/BRUDdZyEDSWzqrtyQgNolFPXBlwwJuM7EF8=
 github.com/vultr/govultr/v3 v3.18.0 h1:nTfxZW7/BRUDdZyEDSWzqrtyQgNolFPXBlwwJuM7EF8=
 github.com/vultr/govultr/v3 v3.18.0/go.mod h1:q34Wd76upKmf+vxFMgaNMH3A8BbsPBmSYZUGC8oZa5w=
 github.com/vultr/govultr/v3 v3.18.0/go.mod h1:q34Wd76upKmf+vxFMgaNMH3A8BbsPBmSYZUGC8oZa5w=
+github.com/vultr/govultr/v3 v3.19.1 h1:31rOP5Tz40AOc8h6Ws4ryzqAniUBffgRhy9uMG/EFvs=
+github.com/vultr/govultr/v3 v3.19.1/go.mod h1:q34Wd76upKmf+vxFMgaNMH3A8BbsPBmSYZUGC8oZa5w=
 github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
 github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
 github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
 github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
 github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
 github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
@@ -2780,6 +2801,8 @@ gopkg.in/ns1/ns1-go.v2 v2.13.0 h1:I5NNqI9Bi1SGK92TVkOvLTwux5LNrix/99H2datVh48=
 gopkg.in/ns1/ns1-go.v2 v2.13.0/go.mod h1:pfaU0vECVP7DIOr453z03HXS6dFJpXdNRwOyRzwmPSc=
 gopkg.in/ns1/ns1-go.v2 v2.13.0/go.mod h1:pfaU0vECVP7DIOr453z03HXS6dFJpXdNRwOyRzwmPSc=
 gopkg.in/ns1/ns1-go.v2 v2.14.1 h1:wruE2g1uB90kMW+jHW8BtWa1HvNkqDfyf7SacTKWtBY=
 gopkg.in/ns1/ns1-go.v2 v2.14.1 h1:wruE2g1uB90kMW+jHW8BtWa1HvNkqDfyf7SacTKWtBY=
 gopkg.in/ns1/ns1-go.v2 v2.14.1/go.mod h1:pfaU0vECVP7DIOr453z03HXS6dFJpXdNRwOyRzwmPSc=
 gopkg.in/ns1/ns1-go.v2 v2.14.1/go.mod h1:pfaU0vECVP7DIOr453z03HXS6dFJpXdNRwOyRzwmPSc=
+gopkg.in/ns1/ns1-go.v2 v2.14.2 h1:wz/toj9U20wBrmYxW4vTz7sZWED+JJVRjUBBJ7CKrzI=
+gopkg.in/ns1/ns1-go.v2 v2.14.2/go.mod h1:pfaU0vECVP7DIOr453z03HXS6dFJpXdNRwOyRzwmPSc=
 gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
 gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=

+ 33 - 0
internal/notification/bark.go

@@ -0,0 +1,33 @@
+package notification
+
+import (
+	"context"
+
+	"github.com/0xJacky/Nginx-UI/model"
+	"github.com/nikoksr/notify"
+	"github.com/nikoksr/notify/service/bark"
+	"github.com/uozi-tech/cosy/map2struct"
+)
+
+// @external_notifier(Bark)
+type Bark struct {
+	DeviceKey string `json:"device_key" title:"Device Key"`
+	ServerURL string `json:"server_url" title:"Server URL"`
+}
+
+func init() {
+	RegisterExternalNotifier("bark", func(ctx context.Context, n *model.ExternalNotify, msg *ExternalMessage) error {
+		barkConfig := &Bark{}
+		err := map2struct.WeakDecode(n.Config, barkConfig)
+		if err != nil {
+			return err
+		}
+		if barkConfig.DeviceKey == "" && barkConfig.ServerURL == "" {
+			return ErrInvalidNotifierConfig
+		}
+		barkService := bark.NewWithServers(barkConfig.DeviceKey, barkConfig.ServerURL)
+		externalNotify := notify.New()
+		externalNotify.UseServices(barkService)
+		return externalNotify.Send(ctx, msg.GetTitle(n.Language), msg.GetContent(n.Language))
+	})
+}

+ 39 - 0
internal/notification/dingding.go

@@ -0,0 +1,39 @@
+package notification
+
+import (
+	"context"
+
+	"github.com/0xJacky/Nginx-UI/model"
+	"github.com/nikoksr/notify"
+	"github.com/nikoksr/notify/service/dingding"
+	"github.com/uozi-tech/cosy/map2struct"
+)
+
+// @external_notifier(DingTalk)
+type DingTalk struct {
+	AccessToken string `json:"access_token" title:"Access Token"`
+	Secret      string `json:"secret" title:"Secret (Optional)"`
+}
+
+func init() {
+	RegisterExternalNotifier("dingding", func(ctx context.Context, n *model.ExternalNotify, msg *ExternalMessage) error {
+		dingTalkConfig := &DingTalk{}
+		err := map2struct.WeakDecode(n.Config, dingTalkConfig)
+		if err != nil {
+			return err
+		}
+		if dingTalkConfig.AccessToken == "" {
+			return ErrInvalidNotifierConfig
+		}
+
+		// Initialize DingTalk service
+		dingTalkService := dingding.New(&dingding.Config{
+			Token:  dingTalkConfig.AccessToken,
+			Secret: dingTalkConfig.Secret,
+		})
+		// Use the service
+		externalNotify := notify.New()
+		externalNotify.UseServices(dingTalkService)
+		return externalNotify.Send(ctx, msg.GetTitle(n.Language), msg.GetContent(n.Language))
+	})
+}

+ 9 - 0
internal/notification/errors.go

@@ -0,0 +1,9 @@
+package notification
+
+import "github.com/uozi-tech/cosy"
+
+var (
+	e                        = cosy.NewErrorScope("notification")
+	ErrNotifierNotFound      = e.New(404001, "notifier not found")
+	ErrInvalidNotifierConfig = e.New(400001, "invalid notifier config")
+)

+ 100 - 0
internal/notification/external.go

@@ -0,0 +1,100 @@
+package notification
+
+import (
+	"context"
+	"sync"
+
+	"github.com/0xJacky/Nginx-UI/internal/translation"
+	"github.com/0xJacky/Nginx-UI/model"
+	"github.com/0xJacky/Nginx-UI/query"
+	"github.com/uozi-tech/cosy/logger"
+)
+
+var (
+	externalNotifierRegistry      = make(map[string]ExternalNotifierHandlerFunc)
+	externalNotifierRegistryMutex = &sync.RWMutex{}
+)
+
+type ExternalNotifierHandlerFunc func(ctx context.Context, n *model.ExternalNotify, msg *ExternalMessage) error
+
+func externalNotifierHandler(n *model.ExternalNotify, msg *model.Notification) (ExternalNotifierHandlerFunc, error) {
+	externalNotifierRegistryMutex.RLock()
+	defer externalNotifierRegistryMutex.RUnlock()
+	notifier, ok := externalNotifierRegistry[n.Type]
+	if !ok {
+		return nil, ErrNotifierNotFound
+	}
+	return notifier, nil
+}
+
+func RegisterExternalNotifier(name string, handler ExternalNotifierHandlerFunc) {
+	externalNotifierRegistryMutex.Lock()
+	defer externalNotifierRegistryMutex.Unlock()
+	externalNotifierRegistry[name] = handler
+}
+
+type ExternalMessage struct {
+	Notification *model.Notification
+}
+
+func (n *ExternalMessage) Send() {
+	en := query.ExternalNotify
+	externalNotifies, err := en.Find()
+	if err != nil {
+		logger.Error(err)
+		return
+	}
+	ctx := context.Background()
+	for _, externalNotify := range externalNotifies {
+		go func(externalNotify *model.ExternalNotify) {
+			notifier, err := externalNotifierHandler(externalNotify, n.Notification)
+			if err != nil {
+				logger.Error(err)
+				return
+			}
+			notifier(ctx, externalNotify, n)
+		}(externalNotify)
+	}
+}
+
+func (n *ExternalMessage) GetTitle(lang string) string {
+	if n.Notification == nil {
+		return ""
+	}
+
+	dict, ok := translation.Dict[lang]
+	if !ok {
+		dict = translation.Dict["en"]
+	}
+
+	title, err := dict.Translate(n.Notification.Title)
+	if err != nil {
+		logger.Error(err)
+		return n.Notification.Title
+	}
+
+	return title
+}
+
+func (n *ExternalMessage) GetContent(lang string) string {
+	if n.Notification == nil {
+		return ""
+	}
+
+	if n.Notification.Details == nil {
+		return n.Notification.Content
+	}
+
+	dict, ok := translation.Dict[lang]
+	if !ok {
+		dict = translation.Dict["en"]
+	}
+
+	content, err := dict.Translate(n.Notification.Content, n.Notification.Details)
+	if err != nil {
+		logger.Error(err)
+		return n.Notification.Content
+	}
+
+	return content
+}

+ 28 - 0
internal/notification/push.go

@@ -0,0 +1,28 @@
+package notification
+
+import (
+	"github.com/0xJacky/Nginx-UI/model"
+	"github.com/0xJacky/Nginx-UI/query"
+	"github.com/uozi-tech/cosy/logger"
+)
+
+func push(nType model.NotificationType, title string, content string, details any) {
+	n := query.Notification
+
+	data := &model.Notification{
+		Type:    nType,
+		Title:   title,
+		Content: content,
+		Details: details,
+	}
+
+	err := n.Create(data)
+	if err != nil {
+		logger.Error(err)
+		return
+	}
+	broadcast(data)
+
+	extNotify := &ExternalMessage{data}
+	extNotify.Send()
+}

+ 0 - 20
internal/notification/subscribe.go

@@ -4,9 +4,7 @@ import (
 	"sync"
 	"sync"
 
 
 	"github.com/0xJacky/Nginx-UI/model"
 	"github.com/0xJacky/Nginx-UI/model"
-	"github.com/0xJacky/Nginx-UI/query"
 	"github.com/gin-gonic/gin"
 	"github.com/gin-gonic/gin"
-	"github.com/uozi-tech/cosy/logger"
 )
 )
 
 
 var (
 var (
@@ -34,21 +32,3 @@ func broadcast(data *model.Notification) {
 		evtChan <- data
 		evtChan <- data
 	}
 	}
 }
 }
-
-func push(nType model.NotificationType, title string, content string, details any) {
-	n := query.Notification
-
-	data := &model.Notification{
-		Type:    nType,
-		Title:   title,
-		Content: content,
-		Details: details,
-	}
-
-	err := n.Create(data)
-	if err != nil {
-		logger.Error(err)
-		return
-	}
-	broadcast(data)
-}

+ 54 - 0
internal/notification/telegram.go

@@ -0,0 +1,54 @@
+package notification
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"strconv"
+
+	"github.com/0xJacky/Nginx-UI/model"
+	"github.com/nikoksr/notify"
+	"github.com/nikoksr/notify/service/telegram"
+	"github.com/uozi-tech/cosy/map2struct"
+)
+
+// @external_notifier(Telegram)
+type Telegram struct {
+	BotToken string `json:"bot_token" title:"Bot Token"`
+	ChatID   string `json:"chat_id" title:"Chat ID"`
+}
+
+func init() {
+	RegisterExternalNotifier("telegram", func(ctx context.Context, n *model.ExternalNotify, msg *ExternalMessage) error {
+		telegramConfig := &Telegram{}
+		err := map2struct.WeakDecode(n.Config, telegramConfig)
+		if err != nil {
+			return err
+		}
+		if telegramConfig.BotToken == "" || telegramConfig.ChatID == "" {
+			return ErrInvalidNotifierConfig
+		}
+
+		telegramService, err := telegram.New(telegramConfig.BotToken)
+		if err != nil {
+			return err
+		}
+
+		// ChatID must be an integer for telegram service
+		chatIDInt, err := strconv.ParseInt(telegramConfig.ChatID, 10, 64)
+		if err != nil {
+			return fmt.Errorf("invalid Telegram Chat ID '%s': %w", telegramConfig.ChatID, err)
+		}
+
+		// Check if chatIDInt is 0, which might indicate an empty or invalid input was parsed
+		if chatIDInt == 0 {
+			return errors.New("invalid Telegram Chat ID: cannot be zero")
+		}
+
+		telegramService.AddReceivers(chatIDInt)
+
+		externalNotify := notify.New()
+		externalNotify.UseServices(telegramService)
+		return externalNotify.Send(ctx, msg.GetTitle(n.Language), msg.GetContent(n.Language))
+	})
+}

+ 1 - 1
internal/translation/translation.go

@@ -4,7 +4,7 @@ import (
 	"encoding/json"
 	"encoding/json"
 	"fmt"
 	"fmt"
 	"github.com/0xJacky/Nginx-UI/app"
 	"github.com/0xJacky/Nginx-UI/app"
-	"github.com/0xJacky/pofile/pofile"
+	"github.com/0xJacky/pofile"
 	"github.com/samber/lo"
 	"github.com/samber/lo"
 	"io"
 	"io"
 	"log"
 	"log"

+ 8 - 0
model/external_notify.go

@@ -0,0 +1,8 @@
+package model
+
+type ExternalNotify struct {
+	Model
+	Type     string            `json:"type" cosy:"add:required;update:omitempty" gorm:"index"`
+	Language string            `json:"language" cosy:"add:required;update:omitempty" gorm:"index"`
+	Config   map[string]string `json:"config" cosy:"add:required;update:omitempty" gorm:"serializer:json[aes]"`
+}

+ 1 - 0
model/model.go

@@ -33,6 +33,7 @@ func GenerateAllModel() []any {
 		Config{},
 		Config{},
 		Passkey{},
 		Passkey{},
 		EnvGroup{},
 		EnvGroup{},
+		ExternalNotify{},
 	}
 	}
 }
 }
 
 

+ 370 - 0
query/external_notifies.gen.go

@@ -0,0 +1,370 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+	"context"
+	"strings"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"github.com/0xJacky/Nginx-UI/model"
+)
+
+func newExternalNotify(db *gorm.DB, opts ...gen.DOOption) externalNotify {
+	_externalNotify := externalNotify{}
+
+	_externalNotify.externalNotifyDo.UseDB(db, opts...)
+	_externalNotify.externalNotifyDo.UseModel(&model.ExternalNotify{})
+
+	tableName := _externalNotify.externalNotifyDo.TableName()
+	_externalNotify.ALL = field.NewAsterisk(tableName)
+	_externalNotify.ID = field.NewUint64(tableName, "id")
+	_externalNotify.CreatedAt = field.NewTime(tableName, "created_at")
+	_externalNotify.UpdatedAt = field.NewTime(tableName, "updated_at")
+	_externalNotify.DeletedAt = field.NewField(tableName, "deleted_at")
+	_externalNotify.Type = field.NewString(tableName, "type")
+	_externalNotify.Config = field.NewField(tableName, "config")
+
+	_externalNotify.fillFieldMap()
+
+	return _externalNotify
+}
+
+type externalNotify struct {
+	externalNotifyDo
+
+	ALL       field.Asterisk
+	ID        field.Uint64
+	CreatedAt field.Time
+	UpdatedAt field.Time
+	DeletedAt field.Field
+	Type      field.String
+	Config    field.Field
+
+	fieldMap map[string]field.Expr
+}
+
+func (e externalNotify) Table(newTableName string) *externalNotify {
+	e.externalNotifyDo.UseTable(newTableName)
+	return e.updateTableName(newTableName)
+}
+
+func (e externalNotify) As(alias string) *externalNotify {
+	e.externalNotifyDo.DO = *(e.externalNotifyDo.As(alias).(*gen.DO))
+	return e.updateTableName(alias)
+}
+
+func (e *externalNotify) updateTableName(table string) *externalNotify {
+	e.ALL = field.NewAsterisk(table)
+	e.ID = field.NewUint64(table, "id")
+	e.CreatedAt = field.NewTime(table, "created_at")
+	e.UpdatedAt = field.NewTime(table, "updated_at")
+	e.DeletedAt = field.NewField(table, "deleted_at")
+	e.Type = field.NewString(table, "type")
+	e.Config = field.NewField(table, "config")
+
+	e.fillFieldMap()
+
+	return e
+}
+
+func (e *externalNotify) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := e.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (e *externalNotify) fillFieldMap() {
+	e.fieldMap = make(map[string]field.Expr, 6)
+	e.fieldMap["id"] = e.ID
+	e.fieldMap["created_at"] = e.CreatedAt
+	e.fieldMap["updated_at"] = e.UpdatedAt
+	e.fieldMap["deleted_at"] = e.DeletedAt
+	e.fieldMap["type"] = e.Type
+	e.fieldMap["config"] = e.Config
+}
+
+func (e externalNotify) clone(db *gorm.DB) externalNotify {
+	e.externalNotifyDo.ReplaceConnPool(db.Statement.ConnPool)
+	return e
+}
+
+func (e externalNotify) replaceDB(db *gorm.DB) externalNotify {
+	e.externalNotifyDo.ReplaceDB(db)
+	return e
+}
+
+type externalNotifyDo struct{ gen.DO }
+
+// FirstByID Where("id=@id")
+func (e externalNotifyDo) FirstByID(id uint64) (result *model.ExternalNotify, err error) {
+	var params []interface{}
+
+	var generateSQL strings.Builder
+	params = append(params, id)
+	generateSQL.WriteString("id=? ")
+
+	var executeSQL *gorm.DB
+	executeSQL = e.UnderlyingDB().Where(generateSQL.String(), params...).Take(&result) // ignore_security_alert
+	err = executeSQL.Error
+
+	return
+}
+
+// DeleteByID update @@table set deleted_at=strftime('%Y-%m-%d %H:%M:%S','now') where id=@id
+func (e externalNotifyDo) DeleteByID(id uint64) (err error) {
+	var params []interface{}
+
+	var generateSQL strings.Builder
+	params = append(params, id)
+	generateSQL.WriteString("update external_notifies set deleted_at=strftime('%Y-%m-%d %H:%M:%S','now') where id=? ")
+
+	var executeSQL *gorm.DB
+	executeSQL = e.UnderlyingDB().Exec(generateSQL.String(), params...) // ignore_security_alert
+	err = executeSQL.Error
+
+	return
+}
+
+func (e externalNotifyDo) Debug() *externalNotifyDo {
+	return e.withDO(e.DO.Debug())
+}
+
+func (e externalNotifyDo) WithContext(ctx context.Context) *externalNotifyDo {
+	return e.withDO(e.DO.WithContext(ctx))
+}
+
+func (e externalNotifyDo) ReadDB() *externalNotifyDo {
+	return e.Clauses(dbresolver.Read)
+}
+
+func (e externalNotifyDo) WriteDB() *externalNotifyDo {
+	return e.Clauses(dbresolver.Write)
+}
+
+func (e externalNotifyDo) Session(config *gorm.Session) *externalNotifyDo {
+	return e.withDO(e.DO.Session(config))
+}
+
+func (e externalNotifyDo) Clauses(conds ...clause.Expression) *externalNotifyDo {
+	return e.withDO(e.DO.Clauses(conds...))
+}
+
+func (e externalNotifyDo) Returning(value interface{}, columns ...string) *externalNotifyDo {
+	return e.withDO(e.DO.Returning(value, columns...))
+}
+
+func (e externalNotifyDo) Not(conds ...gen.Condition) *externalNotifyDo {
+	return e.withDO(e.DO.Not(conds...))
+}
+
+func (e externalNotifyDo) Or(conds ...gen.Condition) *externalNotifyDo {
+	return e.withDO(e.DO.Or(conds...))
+}
+
+func (e externalNotifyDo) Select(conds ...field.Expr) *externalNotifyDo {
+	return e.withDO(e.DO.Select(conds...))
+}
+
+func (e externalNotifyDo) Where(conds ...gen.Condition) *externalNotifyDo {
+	return e.withDO(e.DO.Where(conds...))
+}
+
+func (e externalNotifyDo) Order(conds ...field.Expr) *externalNotifyDo {
+	return e.withDO(e.DO.Order(conds...))
+}
+
+func (e externalNotifyDo) Distinct(cols ...field.Expr) *externalNotifyDo {
+	return e.withDO(e.DO.Distinct(cols...))
+}
+
+func (e externalNotifyDo) Omit(cols ...field.Expr) *externalNotifyDo {
+	return e.withDO(e.DO.Omit(cols...))
+}
+
+func (e externalNotifyDo) Join(table schema.Tabler, on ...field.Expr) *externalNotifyDo {
+	return e.withDO(e.DO.Join(table, on...))
+}
+
+func (e externalNotifyDo) LeftJoin(table schema.Tabler, on ...field.Expr) *externalNotifyDo {
+	return e.withDO(e.DO.LeftJoin(table, on...))
+}
+
+func (e externalNotifyDo) RightJoin(table schema.Tabler, on ...field.Expr) *externalNotifyDo {
+	return e.withDO(e.DO.RightJoin(table, on...))
+}
+
+func (e externalNotifyDo) Group(cols ...field.Expr) *externalNotifyDo {
+	return e.withDO(e.DO.Group(cols...))
+}
+
+func (e externalNotifyDo) Having(conds ...gen.Condition) *externalNotifyDo {
+	return e.withDO(e.DO.Having(conds...))
+}
+
+func (e externalNotifyDo) Limit(limit int) *externalNotifyDo {
+	return e.withDO(e.DO.Limit(limit))
+}
+
+func (e externalNotifyDo) Offset(offset int) *externalNotifyDo {
+	return e.withDO(e.DO.Offset(offset))
+}
+
+func (e externalNotifyDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *externalNotifyDo {
+	return e.withDO(e.DO.Scopes(funcs...))
+}
+
+func (e externalNotifyDo) Unscoped() *externalNotifyDo {
+	return e.withDO(e.DO.Unscoped())
+}
+
+func (e externalNotifyDo) Create(values ...*model.ExternalNotify) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return e.DO.Create(values)
+}
+
+func (e externalNotifyDo) CreateInBatches(values []*model.ExternalNotify, batchSize int) error {
+	return e.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (e externalNotifyDo) Save(values ...*model.ExternalNotify) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return e.DO.Save(values)
+}
+
+func (e externalNotifyDo) First() (*model.ExternalNotify, error) {
+	if result, err := e.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.ExternalNotify), nil
+	}
+}
+
+func (e externalNotifyDo) Take() (*model.ExternalNotify, error) {
+	if result, err := e.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.ExternalNotify), nil
+	}
+}
+
+func (e externalNotifyDo) Last() (*model.ExternalNotify, error) {
+	if result, err := e.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.ExternalNotify), nil
+	}
+}
+
+func (e externalNotifyDo) Find() ([]*model.ExternalNotify, error) {
+	result, err := e.DO.Find()
+	return result.([]*model.ExternalNotify), err
+}
+
+func (e externalNotifyDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.ExternalNotify, err error) {
+	buf := make([]*model.ExternalNotify, 0, batchSize)
+	err = e.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (e externalNotifyDo) FindInBatches(result *[]*model.ExternalNotify, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return e.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (e externalNotifyDo) Attrs(attrs ...field.AssignExpr) *externalNotifyDo {
+	return e.withDO(e.DO.Attrs(attrs...))
+}
+
+func (e externalNotifyDo) Assign(attrs ...field.AssignExpr) *externalNotifyDo {
+	return e.withDO(e.DO.Assign(attrs...))
+}
+
+func (e externalNotifyDo) Joins(fields ...field.RelationField) *externalNotifyDo {
+	for _, _f := range fields {
+		e = *e.withDO(e.DO.Joins(_f))
+	}
+	return &e
+}
+
+func (e externalNotifyDo) Preload(fields ...field.RelationField) *externalNotifyDo {
+	for _, _f := range fields {
+		e = *e.withDO(e.DO.Preload(_f))
+	}
+	return &e
+}
+
+func (e externalNotifyDo) FirstOrInit() (*model.ExternalNotify, error) {
+	if result, err := e.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.ExternalNotify), nil
+	}
+}
+
+func (e externalNotifyDo) FirstOrCreate() (*model.ExternalNotify, error) {
+	if result, err := e.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.ExternalNotify), nil
+	}
+}
+
+func (e externalNotifyDo) FindByPage(offset int, limit int) (result []*model.ExternalNotify, count int64, err error) {
+	result, err = e.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = e.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (e externalNotifyDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = e.Count()
+	if err != nil {
+		return
+	}
+
+	err = e.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (e externalNotifyDo) Scan(result interface{}) (err error) {
+	return e.DO.Scan(result)
+}
+
+func (e externalNotifyDo) Delete(models ...*model.ExternalNotify) (result gen.ResultInfo, err error) {
+	return e.DO.Delete(models)
+}
+
+func (e *externalNotifyDo) withDO(do gen.Dao) *externalNotifyDo {
+	e.DO = *do.(*gen.DO)
+	return e
+}

+ 117 - 109
query/gen.go

@@ -16,22 +16,23 @@ import (
 )
 )
 
 
 var (
 var (
-	Q             = new(Query)
-	AcmeUser      *acmeUser
-	AuthToken     *authToken
-	BanIP         *banIP
-	Cert          *cert
-	ChatGPTLog    *chatGPTLog
-	Config        *config
-	ConfigBackup  *configBackup
-	DnsCredential *dnsCredential
-	EnvGroup      *envGroup
-	Environment   *environment
-	Notification  *notification
-	Passkey       *passkey
-	Site          *site
-	Stream        *stream
-	User          *user
+	Q              = new(Query)
+	AcmeUser       *acmeUser
+	AuthToken      *authToken
+	BanIP          *banIP
+	Cert           *cert
+	ChatGPTLog     *chatGPTLog
+	Config         *config
+	ConfigBackup   *configBackup
+	DnsCredential  *dnsCredential
+	EnvGroup       *envGroup
+	Environment    *environment
+	ExternalNotify *externalNotify
+	Notification   *notification
+	Passkey        *passkey
+	Site           *site
+	Stream         *stream
+	User           *user
 )
 )
 
 
 func SetDefault(db *gorm.DB, opts ...gen.DOOption) {
 func SetDefault(db *gorm.DB, opts ...gen.DOOption) {
@@ -46,6 +47,7 @@ func SetDefault(db *gorm.DB, opts ...gen.DOOption) {
 	DnsCredential = &Q.DnsCredential
 	DnsCredential = &Q.DnsCredential
 	EnvGroup = &Q.EnvGroup
 	EnvGroup = &Q.EnvGroup
 	Environment = &Q.Environment
 	Environment = &Q.Environment
+	ExternalNotify = &Q.ExternalNotify
 	Notification = &Q.Notification
 	Notification = &Q.Notification
 	Passkey = &Q.Passkey
 	Passkey = &Q.Passkey
 	Site = &Q.Site
 	Site = &Q.Site
@@ -55,65 +57,68 @@ func SetDefault(db *gorm.DB, opts ...gen.DOOption) {
 
 
 func Use(db *gorm.DB, opts ...gen.DOOption) *Query {
 func Use(db *gorm.DB, opts ...gen.DOOption) *Query {
 	return &Query{
 	return &Query{
-		db:            db,
-		AcmeUser:      newAcmeUser(db, opts...),
-		AuthToken:     newAuthToken(db, opts...),
-		BanIP:         newBanIP(db, opts...),
-		Cert:          newCert(db, opts...),
-		ChatGPTLog:    newChatGPTLog(db, opts...),
-		Config:        newConfig(db, opts...),
-		ConfigBackup:  newConfigBackup(db, opts...),
-		DnsCredential: newDnsCredential(db, opts...),
-		EnvGroup:      newEnvGroup(db, opts...),
-		Environment:   newEnvironment(db, opts...),
-		Notification:  newNotification(db, opts...),
-		Passkey:       newPasskey(db, opts...),
-		Site:          newSite(db, opts...),
-		Stream:        newStream(db, opts...),
-		User:          newUser(db, opts...),
+		db:             db,
+		AcmeUser:       newAcmeUser(db, opts...),
+		AuthToken:      newAuthToken(db, opts...),
+		BanIP:          newBanIP(db, opts...),
+		Cert:           newCert(db, opts...),
+		ChatGPTLog:     newChatGPTLog(db, opts...),
+		Config:         newConfig(db, opts...),
+		ConfigBackup:   newConfigBackup(db, opts...),
+		DnsCredential:  newDnsCredential(db, opts...),
+		EnvGroup:       newEnvGroup(db, opts...),
+		Environment:    newEnvironment(db, opts...),
+		ExternalNotify: newExternalNotify(db, opts...),
+		Notification:   newNotification(db, opts...),
+		Passkey:        newPasskey(db, opts...),
+		Site:           newSite(db, opts...),
+		Stream:         newStream(db, opts...),
+		User:           newUser(db, opts...),
 	}
 	}
 }
 }
 
 
 type Query struct {
 type Query struct {
 	db *gorm.DB
 	db *gorm.DB
 
 
-	AcmeUser      acmeUser
-	AuthToken     authToken
-	BanIP         banIP
-	Cert          cert
-	ChatGPTLog    chatGPTLog
-	Config        config
-	ConfigBackup  configBackup
-	DnsCredential dnsCredential
-	EnvGroup      envGroup
-	Environment   environment
-	Notification  notification
-	Passkey       passkey
-	Site          site
-	Stream        stream
-	User          user
+	AcmeUser       acmeUser
+	AuthToken      authToken
+	BanIP          banIP
+	Cert           cert
+	ChatGPTLog     chatGPTLog
+	Config         config
+	ConfigBackup   configBackup
+	DnsCredential  dnsCredential
+	EnvGroup       envGroup
+	Environment    environment
+	ExternalNotify externalNotify
+	Notification   notification
+	Passkey        passkey
+	Site           site
+	Stream         stream
+	User           user
 }
 }
 
 
 func (q *Query) Available() bool { return q.db != nil }
 func (q *Query) Available() bool { return q.db != nil }
 
 
 func (q *Query) clone(db *gorm.DB) *Query {
 func (q *Query) clone(db *gorm.DB) *Query {
 	return &Query{
 	return &Query{
-		db:            db,
-		AcmeUser:      q.AcmeUser.clone(db),
-		AuthToken:     q.AuthToken.clone(db),
-		BanIP:         q.BanIP.clone(db),
-		Cert:          q.Cert.clone(db),
-		ChatGPTLog:    q.ChatGPTLog.clone(db),
-		Config:        q.Config.clone(db),
-		ConfigBackup:  q.ConfigBackup.clone(db),
-		DnsCredential: q.DnsCredential.clone(db),
-		EnvGroup:      q.EnvGroup.clone(db),
-		Environment:   q.Environment.clone(db),
-		Notification:  q.Notification.clone(db),
-		Passkey:       q.Passkey.clone(db),
-		Site:          q.Site.clone(db),
-		Stream:        q.Stream.clone(db),
-		User:          q.User.clone(db),
+		db:             db,
+		AcmeUser:       q.AcmeUser.clone(db),
+		AuthToken:      q.AuthToken.clone(db),
+		BanIP:          q.BanIP.clone(db),
+		Cert:           q.Cert.clone(db),
+		ChatGPTLog:     q.ChatGPTLog.clone(db),
+		Config:         q.Config.clone(db),
+		ConfigBackup:   q.ConfigBackup.clone(db),
+		DnsCredential:  q.DnsCredential.clone(db),
+		EnvGroup:       q.EnvGroup.clone(db),
+		Environment:    q.Environment.clone(db),
+		ExternalNotify: q.ExternalNotify.clone(db),
+		Notification:   q.Notification.clone(db),
+		Passkey:        q.Passkey.clone(db),
+		Site:           q.Site.clone(db),
+		Stream:         q.Stream.clone(db),
+		User:           q.User.clone(db),
 	}
 	}
 }
 }
 
 
@@ -127,60 +132,63 @@ func (q *Query) WriteDB() *Query {
 
 
 func (q *Query) ReplaceDB(db *gorm.DB) *Query {
 func (q *Query) ReplaceDB(db *gorm.DB) *Query {
 	return &Query{
 	return &Query{
-		db:            db,
-		AcmeUser:      q.AcmeUser.replaceDB(db),
-		AuthToken:     q.AuthToken.replaceDB(db),
-		BanIP:         q.BanIP.replaceDB(db),
-		Cert:          q.Cert.replaceDB(db),
-		ChatGPTLog:    q.ChatGPTLog.replaceDB(db),
-		Config:        q.Config.replaceDB(db),
-		ConfigBackup:  q.ConfigBackup.replaceDB(db),
-		DnsCredential: q.DnsCredential.replaceDB(db),
-		EnvGroup:      q.EnvGroup.replaceDB(db),
-		Environment:   q.Environment.replaceDB(db),
-		Notification:  q.Notification.replaceDB(db),
-		Passkey:       q.Passkey.replaceDB(db),
-		Site:          q.Site.replaceDB(db),
-		Stream:        q.Stream.replaceDB(db),
-		User:          q.User.replaceDB(db),
+		db:             db,
+		AcmeUser:       q.AcmeUser.replaceDB(db),
+		AuthToken:      q.AuthToken.replaceDB(db),
+		BanIP:          q.BanIP.replaceDB(db),
+		Cert:           q.Cert.replaceDB(db),
+		ChatGPTLog:     q.ChatGPTLog.replaceDB(db),
+		Config:         q.Config.replaceDB(db),
+		ConfigBackup:   q.ConfigBackup.replaceDB(db),
+		DnsCredential:  q.DnsCredential.replaceDB(db),
+		EnvGroup:       q.EnvGroup.replaceDB(db),
+		Environment:    q.Environment.replaceDB(db),
+		ExternalNotify: q.ExternalNotify.replaceDB(db),
+		Notification:   q.Notification.replaceDB(db),
+		Passkey:        q.Passkey.replaceDB(db),
+		Site:           q.Site.replaceDB(db),
+		Stream:         q.Stream.replaceDB(db),
+		User:           q.User.replaceDB(db),
 	}
 	}
 }
 }
 
 
 type queryCtx struct {
 type queryCtx struct {
-	AcmeUser      *acmeUserDo
-	AuthToken     *authTokenDo
-	BanIP         *banIPDo
-	Cert          *certDo
-	ChatGPTLog    *chatGPTLogDo
-	Config        *configDo
-	ConfigBackup  *configBackupDo
-	DnsCredential *dnsCredentialDo
-	EnvGroup      *envGroupDo
-	Environment   *environmentDo
-	Notification  *notificationDo
-	Passkey       *passkeyDo
-	Site          *siteDo
-	Stream        *streamDo
-	User          *userDo
+	AcmeUser       *acmeUserDo
+	AuthToken      *authTokenDo
+	BanIP          *banIPDo
+	Cert           *certDo
+	ChatGPTLog     *chatGPTLogDo
+	Config         *configDo
+	ConfigBackup   *configBackupDo
+	DnsCredential  *dnsCredentialDo
+	EnvGroup       *envGroupDo
+	Environment    *environmentDo
+	ExternalNotify *externalNotifyDo
+	Notification   *notificationDo
+	Passkey        *passkeyDo
+	Site           *siteDo
+	Stream         *streamDo
+	User           *userDo
 }
 }
 
 
 func (q *Query) WithContext(ctx context.Context) *queryCtx {
 func (q *Query) WithContext(ctx context.Context) *queryCtx {
 	return &queryCtx{
 	return &queryCtx{
-		AcmeUser:      q.AcmeUser.WithContext(ctx),
-		AuthToken:     q.AuthToken.WithContext(ctx),
-		BanIP:         q.BanIP.WithContext(ctx),
-		Cert:          q.Cert.WithContext(ctx),
-		ChatGPTLog:    q.ChatGPTLog.WithContext(ctx),
-		Config:        q.Config.WithContext(ctx),
-		ConfigBackup:  q.ConfigBackup.WithContext(ctx),
-		DnsCredential: q.DnsCredential.WithContext(ctx),
-		EnvGroup:      q.EnvGroup.WithContext(ctx),
-		Environment:   q.Environment.WithContext(ctx),
-		Notification:  q.Notification.WithContext(ctx),
-		Passkey:       q.Passkey.WithContext(ctx),
-		Site:          q.Site.WithContext(ctx),
-		Stream:        q.Stream.WithContext(ctx),
-		User:          q.User.WithContext(ctx),
+		AcmeUser:       q.AcmeUser.WithContext(ctx),
+		AuthToken:      q.AuthToken.WithContext(ctx),
+		BanIP:          q.BanIP.WithContext(ctx),
+		Cert:           q.Cert.WithContext(ctx),
+		ChatGPTLog:     q.ChatGPTLog.WithContext(ctx),
+		Config:         q.Config.WithContext(ctx),
+		ConfigBackup:   q.ConfigBackup.WithContext(ctx),
+		DnsCredential:  q.DnsCredential.WithContext(ctx),
+		EnvGroup:       q.EnvGroup.WithContext(ctx),
+		Environment:    q.Environment.WithContext(ctx),
+		ExternalNotify: q.ExternalNotify.WithContext(ctx),
+		Notification:   q.Notification.WithContext(ctx),
+		Passkey:        q.Passkey.WithContext(ctx),
+		Site:           q.Site.WithContext(ctx),
+		Stream:         q.Stream.WithContext(ctx),
+		User:           q.User.WithContext(ctx),
 	}
 	}
 }
 }
 
 

+ 2 - 0
router/routers.go

@@ -10,6 +10,7 @@ import (
 	"github.com/0xJacky/Nginx-UI/api/cluster"
 	"github.com/0xJacky/Nginx-UI/api/cluster"
 	"github.com/0xJacky/Nginx-UI/api/config"
 	"github.com/0xJacky/Nginx-UI/api/config"
 	"github.com/0xJacky/Nginx-UI/api/crypto"
 	"github.com/0xJacky/Nginx-UI/api/crypto"
+	"github.com/0xJacky/Nginx-UI/api/external_notify"
 	"github.com/0xJacky/Nginx-UI/api/index"
 	"github.com/0xJacky/Nginx-UI/api/index"
 	"github.com/0xJacky/Nginx-UI/api/nginx"
 	"github.com/0xJacky/Nginx-UI/api/nginx"
 	nginxLog "github.com/0xJacky/Nginx-UI/api/nginx_log"
 	nginxLog "github.com/0xJacky/Nginx-UI/api/nginx_log"
@@ -74,6 +75,7 @@ func InitRouter() {
 			openai.InitRouter(g)
 			openai.InitRouter(g)
 			cluster.InitRouter(g)
 			cluster.InitRouter(g)
 			notification.InitRouter(g)
 			notification.InitRouter(g)
+			external_notify.InitRouter(g)
 		}
 		}
 
 
 		// Authorization required and websocket request
 		// Authorization required and websocket request