瀏覽代碼

feat(env_group): add post-sync action to environment and stream configurations #725

Jacky 3 周之前
父節點
當前提交
94fcbf6362

+ 6 - 4
api/cluster/group.go

@@ -54,8 +54,9 @@ func RestartNginx(c *gin.Context) {
 func AddGroup(c *gin.Context) {
 	cosy.Core[model.EnvGroup](c).
 		SetValidRules(gin.H{
-			"name":          "required",
-			"sync_node_ids": "omitempty",
+			"name":             "required",
+			"sync_node_ids":    "omitempty",
+			"post_sync_action": "omitempty,oneof=" + model.PostSyncActionNone + " " + model.PostSyncActionReloadNginx,
 		}).
 		Create()
 }
@@ -63,8 +64,9 @@ func AddGroup(c *gin.Context) {
 func ModifyGroup(c *gin.Context) {
 	cosy.Core[model.EnvGroup](c).
 		SetValidRules(gin.H{
-			"name":          "required",
-			"sync_node_ids": "omitempty",
+			"name":             "required",
+			"sync_node_ids":    "omitempty",
+			"post_sync_action": "omitempty,oneof=" + model.PostSyncActionNone + " " + model.PostSyncActionReloadNginx,
 		}).
 		Modify()
 }

+ 2 - 1
api/sites/site.go

@@ -118,13 +118,14 @@ func SaveSite(c *gin.Context) {
 		EnvGroupID  uint64   `json:"env_group_id"`
 		SyncNodeIDs []uint64 `json:"sync_node_ids"`
 		Overwrite   bool     `json:"overwrite"`
+		PostAction  string   `json:"post_action"`
 	}
 
 	if !cosy.BindAndValid(c, &json) {
 		return
 	}
 
-	err := site.Save(name, json.Content, json.Overwrite, json.EnvGroupID, json.SyncNodeIDs)
+	err := site.Save(name, json.Content, json.Overwrite, json.EnvGroupID, json.SyncNodeIDs, json.PostAction)
 	if err != nil {
 		cosy.ErrHandler(c, err)
 		return

+ 9 - 8
api/streams/streams.go

@@ -60,7 +60,7 @@ func GetStreams(c *gin.Context) {
 
 	var configs []config.Config
 
-	// Get all streams map for environment group lookup
+	// Get all streams map for Node Group lookup
 	s := query.Stream
 	var streams []*model.Stream
 	if queryEnvGroupId != 0 {
@@ -73,21 +73,21 @@ func GetStreams(c *gin.Context) {
 		return
 	}
 
-	// Retrieve environment groups data
+	// Retrieve Node Groups data
 	eg := query.EnvGroup
 	envGroups, err := eg.Find()
 	if err != nil {
 		cosy.ErrHandler(c, err)
 		return
 	}
-	// Create a map of environment groups for quick lookup by ID
+	// Create a map of Node Groups for quick lookup by ID
 	envGroupMap := lo.SliceToMap(envGroups, func(item *model.EnvGroup) (uint64, *model.EnvGroup) {
 		return item.ID, item
 	})
 
 	// Convert streams slice to map for efficient lookups
 	streamsMap := lo.SliceToMap(streams, func(item *model.Stream) (string, *model.Stream) {
-		// Associate each stream with its corresponding environment group
+		// Associate each stream with its corresponding Node Group
 		if item.EnvGroupID > 0 {
 			item.EnvGroup = envGroupMap[item.EnvGroupID]
 		}
@@ -121,13 +121,13 @@ func GetStreams(c *gin.Context) {
 			envGroup   *model.EnvGroup
 		)
 
-		// Lookup stream in the streams map to get environment group info
+		// Lookup stream in the streams map to get Node Group info
 		if stream, ok := streamsMap[file.Name()]; ok {
 			envGroupId = stream.EnvGroupID
 			envGroup = stream.EnvGroup
 		}
 
-		// Apply environment group filter if specified
+		// Apply Node Group filter if specified
 		if queryEnvGroupId != 0 && envGroupId != queryEnvGroupId {
 			continue
 		}
@@ -245,6 +245,7 @@ func SaveStream(c *gin.Context) {
 		EnvGroupID  uint64   `json:"env_group_id"`
 		SyncNodeIDs []uint64 `json:"sync_node_ids"`
 		Overwrite   bool     `json:"overwrite"`
+		PostAction  string   `json:"post_action"`
 	}
 
 	// Validate input JSON
@@ -261,7 +262,7 @@ func SaveStream(c *gin.Context) {
 		return
 	}
 
-	// Update environment group ID if provided
+	// Update Node Group ID if provided
 	if json.EnvGroupID > 0 {
 		streamModel.EnvGroupID = json.EnvGroupID
 	}
@@ -279,7 +280,7 @@ func SaveStream(c *gin.Context) {
 	}
 
 	// Save the stream configuration file
-	err = stream.Save(name, json.Content, json.Overwrite, json.SyncNodeIDs)
+	err = stream.Save(name, json.Content, json.Overwrite, json.SyncNodeIDs, json.PostAction)
 	if err != nil {
 		cosy.ErrHandler(c, err)
 		return

+ 8 - 3
app/src/api/env_group.ts

@@ -1,11 +1,16 @@
 import type { ModelBase } from '@/api/curd'
 import Curd from '@/api/curd'
 
+// Post-sync action types
+export const PostSyncAction = {
+  None: 'none',
+  ReloadNginx: 'reload_nginx',
+}
+
 export interface EnvGroup extends ModelBase {
   name: string
   sync_node_ids: number[]
+  post_sync_action?: string
 }
 
-const env_group = new Curd<EnvGroup>('env_groups')
-
-export default env_group
+export default new Curd<EnvGroup>('/env_groups')

+ 1 - 1
app/src/components/EnvGroupTabs/EnvGroupTabs.vue

@@ -68,7 +68,7 @@ function disconnectSSE() {
   }
 }
 
-// Get the current environment group data
+// Get the current Node Group data
 const currentEnvGroup = computed(() => {
   if (!modelValue.value || modelValue.value === 0)
     return null

+ 38 - 23
app/src/language/ar/app.po

@@ -43,7 +43,7 @@ msgstr "مستخدم ACME"
 #: src/views/certificate/CertificateList/certColumns.tsx:97
 #: src/views/certificate/DNSCredential.vue:33
 #: src/views/config/configColumns.tsx:42
-#: src/views/environments/group/columns.ts:28
+#: src/views/environments/group/columns.ts:42
 #: src/views/environments/list/envColumns.tsx:97
 #: src/views/nginx_log/NginxLogList.vue:53
 #: src/views/notification/notificationColumns.tsx:66
@@ -642,7 +642,7 @@ msgid ""
 "Backup files will be automatically downloaded to your computer."
 msgstr ""
 
-#: src/views/environments/group/columns.ts:16
+#: src/views/environments/group/columns.ts:30
 #: src/views/notification/notificationColumns.tsx:59
 #: src/views/preference/components/Passkey.vue:95
 #: src/views/user/userColumns.tsx:48
@@ -1115,19 +1115,6 @@ msgstr "تم التفعيل بنجاح"
 msgid "Encrypt website with Let's Encrypt"
 msgstr "تشفير الموقع باستخدام Let's Encrypt"
 
-#: src/views/site/site_edit/RightSettings.vue:91
-#: src/views/site/site_list/columns.tsx:25
-#: src/views/stream/components/RightSettings.vue:90
-#: src/views/stream/StreamList.vue:28
-#, fuzzy
-msgid "Environment Group"
-msgstr "بيئة"
-
-#: src/views/environments/group/EnvGroup.vue:10
-#, fuzzy
-msgid "Environment Groups"
-msgstr "البيئات"
-
 #: src/language/constants.ts:22
 msgid "Environment variables cleaned"
 msgstr "تم تنظيف متغيرات البيئة"
@@ -1536,10 +1523,6 @@ msgstr "جارٍ الحصول على الشهادة، يرجى الانتظار.
 msgid "Github Proxy"
 msgstr "وكيل Github"
 
-#: src/routes/modules/environments.ts:33
-msgid "Groups"
-msgstr ""
-
 #: src/constants/errors/backup.ts:59
 msgid "Hash verification failed: file integrity compromised"
 msgstr ""
@@ -1964,7 +1947,7 @@ msgstr "توجيه متعدد الأسطر"
 #: src/views/certificate/DNSCredential.vue:11
 #: src/views/config/components/Mkdir.vue:64
 #: src/views/config/configColumns.tsx:7 src/views/config/ConfigEditor.vue:256
-#: src/views/environments/group/columns.ts:7
+#: src/views/environments/group/columns.ts:8
 #: src/views/environments/list/envColumns.tsx:9
 #: src/views/nginx_log/NginxLogList.vue:37
 #: src/views/preference/components/AddPasskey.vue:75
@@ -2162,11 +2145,31 @@ msgstr "خطأ في تحليل تكوين Nginx"
 msgid "No"
 msgstr "لا"
 
+#: src/views/environments/group/columns.ts:21
+#: src/views/environments/group/EnvGroup.vue:34
+#, fuzzy
+msgid "No Action"
+msgstr "إجراء"
+
 #: src/views/preference/Preference.vue:168
 #, fuzzy
 msgid "Node"
 msgstr "اسم العقدة"
 
+#: src/views/site/site_edit/RightSettings.vue:91
+#: src/views/site/site_list/columns.tsx:25
+#: src/views/stream/components/RightSettings.vue:90
+#: src/views/stream/StreamList.vue:28
+#, fuzzy
+msgid "Node Group"
+msgstr "بيئة"
+
+#: src/routes/modules/environments.ts:33
+#: src/views/environments/group/EnvGroup.vue:10
+#, fuzzy
+msgid "Node Groups"
+msgstr "البيئات"
+
 #: src/views/preference/NodeSettings.vue:15
 msgid "Node name"
 msgstr "اسم العقدة"
@@ -2507,6 +2510,12 @@ msgstr "يرجى اختيار عقدة واحدة على الأقل للترقي
 msgid "Port"
 msgstr "منفذ HTTP"
 
+#: src/views/environments/group/columns.ts:17
+#: src/views/environments/group/EnvGroup.vue:26
+#, fuzzy
+msgid "Post-sync Action"
+msgstr "إجراء"
+
 #: src/views/environments/list/BatchUpgrader.vue:167
 #: src/views/environments/list/BatchUpgrader.vue:220
 #: src/views/system/Upgrade.vue:194 src/views/system/Upgrade.vue:245
@@ -2639,6 +2648,8 @@ msgid "Reload"
 msgstr "إعادة تحميل"
 
 #: src/components/EnvGroupTabs/EnvGroupTabs.vue:156
+#: src/views/environments/group/columns.ts:23
+#: src/views/environments/group/EnvGroup.vue:37
 #: src/views/environments/list/Environment.vue:120
 #: src/views/environments/list/Environment.vue:128
 #, fuzzy
@@ -2980,6 +2991,10 @@ msgstr ""
 msgid "Security Token Information"
 msgstr "رمز 2FA أو الاسترداد غير صالح"
 
+#: src/views/environments/group/EnvGroup.vue:29
+msgid "Select an action after sync"
+msgstr ""
+
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:189
 msgid "Selector"
 msgstr "المحدد"
@@ -3613,7 +3628,7 @@ msgstr "تم التحديث بنجاح"
 #: src/views/certificate/ACMEUser.vue:88
 #: src/views/certificate/DNSCredential.vue:27
 #: src/views/config/configColumns.tsx:34 src/views/config/ConfigEditor.vue:276
-#: src/views/environments/group/columns.ts:22
+#: src/views/environments/group/columns.ts:36
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/site/site_edit/RightSettings.vue:100
 #: src/views/site/site_list/columns.tsx:69
@@ -3782,7 +3797,7 @@ msgstr ""
 #, fuzzy
 msgid ""
 "When you enable/disable, delete, or save this site, the nodes set in the "
-"environment group and the nodes selected below will be synchronized."
+"Node Group and the nodes selected below will be synchronized."
 msgstr ""
 "عند تفعيل/تعطيل، حذف، أو حفظ هذا الموقع، سيتم مزامنة العقد المحددة في فئة "
 "الموقع والعقد المحددة أدناه."
@@ -3791,7 +3806,7 @@ msgstr ""
 #, fuzzy
 msgid ""
 "When you enable/disable, delete, or save this stream, the nodes set in the "
-"environment group and the nodes selected below will be synchronized."
+"Node Group and the nodes selected below will be synchronized."
 msgstr ""
 "عند تفعيل/تعطيل، حذف، أو حفظ هذا الموقع، سيتم مزامنة العقد المحددة في فئة "
 "الموقع والعقد المحددة أدناه."

+ 38 - 23
app/src/language/de_DE/app.po

@@ -40,7 +40,7 @@ msgstr "Benutzername"
 #: src/views/certificate/CertificateList/certColumns.tsx:97
 #: src/views/certificate/DNSCredential.vue:33
 #: src/views/config/configColumns.tsx:42
-#: src/views/environments/group/columns.ts:28
+#: src/views/environments/group/columns.ts:42
 #: src/views/environments/list/envColumns.tsx:97
 #: src/views/nginx_log/NginxLogList.vue:53
 #: src/views/notification/notificationColumns.tsx:66
@@ -665,7 +665,7 @@ msgid ""
 "Backup files will be automatically downloaded to your computer."
 msgstr ""
 
-#: src/views/environments/group/columns.ts:16
+#: src/views/environments/group/columns.ts:30
 #: src/views/notification/notificationColumns.tsx:59
 #: src/views/preference/components/Passkey.vue:95
 #: src/views/user/userColumns.tsx:48
@@ -1162,19 +1162,6 @@ msgstr "Erfolgreich aktiviert"
 msgid "Encrypt website with Let's Encrypt"
 msgstr "Webseite mit Let's Encrypt verschlüsseln"
 
-#: src/views/site/site_edit/RightSettings.vue:91
-#: src/views/site/site_list/columns.tsx:25
-#: src/views/stream/components/RightSettings.vue:90
-#: src/views/stream/StreamList.vue:28
-#, fuzzy
-msgid "Environment Group"
-msgstr "Umgebung"
-
-#: src/views/environments/group/EnvGroup.vue:10
-#, fuzzy
-msgid "Environment Groups"
-msgstr "Kommentare"
-
 #: src/language/constants.ts:22
 msgid "Environment variables cleaned"
 msgstr "Umgebungsvariablen gesäubert"
@@ -1588,10 +1575,6 @@ msgstr "Hole das Zertifikat, bitte warten..."
 msgid "Github Proxy"
 msgstr ""
 
-#: src/routes/modules/environments.ts:33
-msgid "Groups"
-msgstr ""
-
 #: src/constants/errors/backup.ts:59
 msgid "Hash verification failed: file integrity compromised"
 msgstr ""
@@ -2039,7 +2022,7 @@ msgstr "Einzelne Anweisung"
 #: src/views/certificate/DNSCredential.vue:11
 #: src/views/config/components/Mkdir.vue:64
 #: src/views/config/configColumns.tsx:7 src/views/config/ConfigEditor.vue:256
-#: src/views/environments/group/columns.ts:7
+#: src/views/environments/group/columns.ts:8
 #: src/views/environments/list/envColumns.tsx:9
 #: src/views/nginx_log/NginxLogList.vue:37
 #: src/views/preference/components/AddPasskey.vue:75
@@ -2243,11 +2226,31 @@ msgstr "Name der Konfiguration"
 msgid "No"
 msgstr "Nein"
 
+#: src/views/environments/group/columns.ts:21
+#: src/views/environments/group/EnvGroup.vue:34
+#, fuzzy
+msgid "No Action"
+msgstr "Aktion"
+
 #: src/views/preference/Preference.vue:168
 #, fuzzy
 msgid "Node"
 msgstr "Benuztername"
 
+#: src/views/site/site_edit/RightSettings.vue:91
+#: src/views/site/site_list/columns.tsx:25
+#: src/views/stream/components/RightSettings.vue:90
+#: src/views/stream/StreamList.vue:28
+#, fuzzy
+msgid "Node Group"
+msgstr "Umgebung"
+
+#: src/routes/modules/environments.ts:33
+#: src/views/environments/group/EnvGroup.vue:10
+#, fuzzy
+msgid "Node Groups"
+msgstr "Kommentare"
+
 #: src/views/preference/NodeSettings.vue:15
 #, fuzzy
 msgid "Node name"
@@ -2606,6 +2609,12 @@ msgstr "Bitte wähle mindestens einen Knoten zum Upgrade aus"
 msgid "Port"
 msgstr ""
 
+#: src/views/environments/group/columns.ts:17
+#: src/views/environments/group/EnvGroup.vue:26
+#, fuzzy
+msgid "Post-sync Action"
+msgstr "Aktionen"
+
 #: src/views/environments/list/BatchUpgrader.vue:167
 #: src/views/environments/list/BatchUpgrader.vue:220
 #: src/views/system/Upgrade.vue:194 src/views/system/Upgrade.vue:245
@@ -2746,6 +2755,8 @@ msgid "Reload"
 msgstr "Neu laden"
 
 #: src/components/EnvGroupTabs/EnvGroupTabs.vue:156
+#: src/views/environments/group/columns.ts:23
+#: src/views/environments/group/EnvGroup.vue:37
 #: src/views/environments/list/Environment.vue:120
 #: src/views/environments/list/Environment.vue:128
 #, fuzzy
@@ -3106,6 +3117,10 @@ msgstr ""
 msgid "Security Token Information"
 msgstr "Ungültiger 2FA- oder Wiederherstellungscode"
 
+#: src/views/environments/group/EnvGroup.vue:29
+msgid "Select an action after sync"
+msgstr ""
+
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:189
 msgid "Selector"
 msgstr "Auswähler"
@@ -3752,7 +3767,7 @@ msgstr "Speichern erfolgreich"
 #: src/views/certificate/ACMEUser.vue:88
 #: src/views/certificate/DNSCredential.vue:27
 #: src/views/config/configColumns.tsx:34 src/views/config/ConfigEditor.vue:276
-#: src/views/environments/group/columns.ts:22
+#: src/views/environments/group/columns.ts:36
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/site/site_edit/RightSettings.vue:100
 #: src/views/site/site_list/columns.tsx:69
@@ -3930,7 +3945,7 @@ msgstr ""
 #, fuzzy
 msgid ""
 "When you enable/disable, delete, or save this site, the nodes set in the "
-"environment group and the nodes selected below will be synchronized."
+"Node Group and the nodes selected below will be synchronized."
 msgstr ""
 "Wenn du diese Seite aktivierst/deaktivierst, löschst oder speicherst, werden "
 "die Knoten, die in der Seitenkategorie festgelegt sind, und die unten "
@@ -3939,7 +3954,7 @@ msgstr ""
 #, fuzzy
 msgid ""
 "When you enable/disable, delete, or save this stream, the nodes set in the "
-"environment group and the nodes selected below will be synchronized."
+"Node Group and the nodes selected below will be synchronized."
 msgstr ""
 "Wenn du diese Seite aktivierst/deaktivierst, löschst oder speicherst, werden "
 "die Knoten, die in der Seitenkategorie festgelegt sind, und die unten "

+ 38 - 23
app/src/language/en/app.po

@@ -41,7 +41,7 @@ msgstr "Username"
 #: src/views/certificate/CertificateList/certColumns.tsx:97
 #: src/views/certificate/DNSCredential.vue:33
 #: src/views/config/configColumns.tsx:42
-#: src/views/environments/group/columns.ts:28
+#: src/views/environments/group/columns.ts:42
 #: src/views/environments/list/envColumns.tsx:97
 #: src/views/nginx_log/NginxLogList.vue:53
 #: src/views/notification/notificationColumns.tsx:66
@@ -657,7 +657,7 @@ msgid ""
 "Backup files will be automatically downloaded to your computer."
 msgstr ""
 
-#: src/views/environments/group/columns.ts:16
+#: src/views/environments/group/columns.ts:30
 #: src/views/notification/notificationColumns.tsx:59
 #: src/views/preference/components/Passkey.vue:95
 #: src/views/user/userColumns.tsx:48
@@ -1148,19 +1148,6 @@ msgstr "Enabled successfully"
 msgid "Encrypt website with Let's Encrypt"
 msgstr "Encrypt website with Let's Encrypt"
 
-#: src/views/site/site_edit/RightSettings.vue:91
-#: src/views/site/site_list/columns.tsx:25
-#: src/views/stream/components/RightSettings.vue:90
-#: src/views/stream/StreamList.vue:28
-#, fuzzy
-msgid "Environment Group"
-msgstr "Comments"
-
-#: src/views/environments/group/EnvGroup.vue:10
-#, fuzzy
-msgid "Environment Groups"
-msgstr "Comments"
-
 #: src/language/constants.ts:22
 msgid "Environment variables cleaned"
 msgstr ""
@@ -1575,10 +1562,6 @@ msgstr "Getting the certificate, please wait..."
 msgid "Github Proxy"
 msgstr ""
 
-#: src/routes/modules/environments.ts:33
-msgid "Groups"
-msgstr ""
-
 #: src/constants/errors/backup.ts:59
 msgid "Hash verification failed: file integrity compromised"
 msgstr ""
@@ -2016,7 +1999,7 @@ msgstr "Single Directive"
 #: src/views/certificate/DNSCredential.vue:11
 #: src/views/config/components/Mkdir.vue:64
 #: src/views/config/configColumns.tsx:7 src/views/config/ConfigEditor.vue:256
-#: src/views/environments/group/columns.ts:7
+#: src/views/environments/group/columns.ts:8
 #: src/views/environments/list/envColumns.tsx:9
 #: src/views/nginx_log/NginxLogList.vue:37
 #: src/views/preference/components/AddPasskey.vue:75
@@ -2219,11 +2202,31 @@ msgstr "Configuration Name"
 msgid "No"
 msgstr "No"
 
+#: src/views/environments/group/columns.ts:21
+#: src/views/environments/group/EnvGroup.vue:34
+#, fuzzy
+msgid "No Action"
+msgstr "Action"
+
 #: src/views/preference/Preference.vue:168
 #, fuzzy
 msgid "Node"
 msgstr "Username"
 
+#: src/views/site/site_edit/RightSettings.vue:91
+#: src/views/site/site_list/columns.tsx:25
+#: src/views/stream/components/RightSettings.vue:90
+#: src/views/stream/StreamList.vue:28
+#, fuzzy
+msgid "Node Group"
+msgstr "Comments"
+
+#: src/routes/modules/environments.ts:33
+#: src/views/environments/group/EnvGroup.vue:10
+#, fuzzy
+msgid "Node Groups"
+msgstr "Comments"
+
 #: src/views/preference/NodeSettings.vue:15
 #, fuzzy
 msgid "Node name"
@@ -2559,6 +2562,12 @@ msgstr ""
 msgid "Port"
 msgstr ""
 
+#: src/views/environments/group/columns.ts:17
+#: src/views/environments/group/EnvGroup.vue:26
+#, fuzzy
+msgid "Post-sync Action"
+msgstr "Action"
+
 #: src/views/environments/list/BatchUpgrader.vue:167
 #: src/views/environments/list/BatchUpgrader.vue:220
 #: src/views/system/Upgrade.vue:194 src/views/system/Upgrade.vue:245
@@ -2699,6 +2708,8 @@ msgid "Reload"
 msgstr ""
 
 #: src/components/EnvGroupTabs/EnvGroupTabs.vue:156
+#: src/views/environments/group/columns.ts:23
+#: src/views/environments/group/EnvGroup.vue:37
 #: src/views/environments/list/Environment.vue:120
 #: src/views/environments/list/Environment.vue:128
 msgid "Reload Nginx"
@@ -3056,6 +3067,10 @@ msgstr ""
 msgid "Security Token Information"
 msgstr "Invalid E-mail!"
 
+#: src/views/environments/group/EnvGroup.vue:29
+msgid "Select an action after sync"
+msgstr ""
+
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:189
 #, fuzzy
 msgid "Selector"
@@ -3681,7 +3696,7 @@ msgstr "Saved successfully"
 #: src/views/certificate/ACMEUser.vue:88
 #: src/views/certificate/DNSCredential.vue:27
 #: src/views/config/configColumns.tsx:34 src/views/config/ConfigEditor.vue:276
-#: src/views/environments/group/columns.ts:22
+#: src/views/environments/group/columns.ts:36
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/site/site_edit/RightSettings.vue:100
 #: src/views/site/site_list/columns.tsx:69
@@ -3852,13 +3867,13 @@ msgstr ""
 #: src/views/site/site_edit/RightSettings.vue:116
 msgid ""
 "When you enable/disable, delete, or save this site, the nodes set in the "
-"environment group and the nodes selected below will be synchronized."
+"Node Group and the nodes selected below will be synchronized."
 msgstr ""
 
 #: src/views/stream/components/RightSettings.vue:114
 msgid ""
 "When you enable/disable, delete, or save this stream, the nodes set in the "
-"environment group and the nodes selected below will be synchronized."
+"Node Group and the nodes selected below will be synchronized."
 msgstr ""
 
 #: src/views/preference/components/RecoveryCodes.vue:140

+ 38 - 23
app/src/language/es/app.po

@@ -46,7 +46,7 @@ msgstr "Usuario ACME"
 #: src/views/certificate/CertificateList/certColumns.tsx:97
 #: src/views/certificate/DNSCredential.vue:33
 #: src/views/config/configColumns.tsx:42
-#: src/views/environments/group/columns.ts:28
+#: src/views/environments/group/columns.ts:42
 #: src/views/environments/list/envColumns.tsx:97
 #: src/views/nginx_log/NginxLogList.vue:53
 #: src/views/notification/notificationColumns.tsx:66
@@ -641,7 +641,7 @@ msgid ""
 "Backup files will be automatically downloaded to your computer."
 msgstr ""
 
-#: src/views/environments/group/columns.ts:16
+#: src/views/environments/group/columns.ts:30
 #: src/views/notification/notificationColumns.tsx:59
 #: src/views/preference/components/Passkey.vue:95
 #: src/views/user/userColumns.tsx:48
@@ -1118,19 +1118,6 @@ msgstr "Habilitado con éxito"
 msgid "Encrypt website with Let's Encrypt"
 msgstr "Encriptar sitio web con Let's Encrypt"
 
-#: src/views/site/site_edit/RightSettings.vue:91
-#: src/views/site/site_list/columns.tsx:25
-#: src/views/stream/components/RightSettings.vue:90
-#: src/views/stream/StreamList.vue:28
-#, fuzzy
-msgid "Environment Group"
-msgstr "Entorno"
-
-#: src/views/environments/group/EnvGroup.vue:10
-#, fuzzy
-msgid "Environment Groups"
-msgstr "Entornos"
-
 #: src/language/constants.ts:22
 msgid "Environment variables cleaned"
 msgstr "Variables de entorno limpiadas"
@@ -1537,10 +1524,6 @@ msgstr "Obteniendo el certificado, por favor espere..."
 msgid "Github Proxy"
 msgstr "Proxy Github"
 
-#: src/routes/modules/environments.ts:33
-msgid "Groups"
-msgstr ""
-
 #: src/constants/errors/backup.ts:59
 msgid "Hash verification failed: file integrity compromised"
 msgstr ""
@@ -1967,7 +1950,7 @@ msgstr "Directiva multilínea"
 #: src/views/certificate/DNSCredential.vue:11
 #: src/views/config/components/Mkdir.vue:64
 #: src/views/config/configColumns.tsx:7 src/views/config/ConfigEditor.vue:256
-#: src/views/environments/group/columns.ts:7
+#: src/views/environments/group/columns.ts:8
 #: src/views/environments/list/envColumns.tsx:9
 #: src/views/nginx_log/NginxLogList.vue:37
 #: src/views/preference/components/AddPasskey.vue:75
@@ -2168,11 +2151,31 @@ msgstr "Error de análisis de configuración de Nginx"
 msgid "No"
 msgstr "No"
 
+#: src/views/environments/group/columns.ts:21
+#: src/views/environments/group/EnvGroup.vue:34
+#, fuzzy
+msgid "No Action"
+msgstr "Acción"
+
 #: src/views/preference/Preference.vue:168
 #, fuzzy
 msgid "Node"
 msgstr "Nuevo nombre"
 
+#: src/views/site/site_edit/RightSettings.vue:91
+#: src/views/site/site_list/columns.tsx:25
+#: src/views/stream/components/RightSettings.vue:90
+#: src/views/stream/StreamList.vue:28
+#, fuzzy
+msgid "Node Group"
+msgstr "Entorno"
+
+#: src/routes/modules/environments.ts:33
+#: src/views/environments/group/EnvGroup.vue:10
+#, fuzzy
+msgid "Node Groups"
+msgstr "Entornos"
+
 #: src/views/preference/NodeSettings.vue:15
 #, fuzzy
 msgid "Node name"
@@ -2527,6 +2530,12 @@ msgstr "Seleccione al menos un nodo para actualizar"
 msgid "Port"
 msgstr "Puerto HTTP"
 
+#: src/views/environments/group/columns.ts:17
+#: src/views/environments/group/EnvGroup.vue:26
+#, fuzzy
+msgid "Post-sync Action"
+msgstr "Acción"
+
 #: src/views/environments/list/BatchUpgrader.vue:167
 #: src/views/environments/list/BatchUpgrader.vue:220
 #: src/views/system/Upgrade.vue:194 src/views/system/Upgrade.vue:245
@@ -2664,6 +2673,8 @@ msgid "Reload"
 msgstr "Recargar"
 
 #: src/components/EnvGroupTabs/EnvGroupTabs.vue:156
+#: src/views/environments/group/columns.ts:23
+#: src/views/environments/group/EnvGroup.vue:37
 #: src/views/environments/list/Environment.vue:120
 #: src/views/environments/list/Environment.vue:128
 #, fuzzy
@@ -3012,6 +3023,10 @@ msgstr ""
 msgid "Security Token Information"
 msgstr "Código 2FA o de recuperación inválido"
 
+#: src/views/environments/group/EnvGroup.vue:29
+msgid "Select an action after sync"
+msgstr ""
+
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:189
 msgid "Selector"
 msgstr "Seleccionador"
@@ -3655,7 +3670,7 @@ msgstr "Actualización exitosa"
 #: src/views/certificate/ACMEUser.vue:88
 #: src/views/certificate/DNSCredential.vue:27
 #: src/views/config/configColumns.tsx:34 src/views/config/ConfigEditor.vue:276
-#: src/views/environments/group/columns.ts:22
+#: src/views/environments/group/columns.ts:36
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/site/site_edit/RightSettings.vue:100
 #: src/views/site/site_list/columns.tsx:69
@@ -3826,7 +3841,7 @@ msgstr ""
 #, fuzzy
 msgid ""
 "When you enable/disable, delete, or save this site, the nodes set in the "
-"environment group and the nodes selected below will be synchronized."
+"Node Group and the nodes selected below will be synchronized."
 msgstr ""
 "Cuando habilite/deshabilite, elimine o guarde este sitio, los nodos "
 "configurados en la categoría del sitio y los nodos seleccionados a "
@@ -3836,7 +3851,7 @@ msgstr ""
 #, fuzzy
 msgid ""
 "When you enable/disable, delete, or save this stream, the nodes set in the "
-"environment group and the nodes selected below will be synchronized."
+"Node Group and the nodes selected below will be synchronized."
 msgstr ""
 "Cuando habilite/deshabilite, elimine o guarde este sitio, los nodos "
 "configurados en la categoría del sitio y los nodos seleccionados a "

+ 38 - 23
app/src/language/fr_FR/app.po

@@ -45,7 +45,7 @@ msgstr "Nom d'utilisateur"
 #: src/views/certificate/CertificateList/certColumns.tsx:97
 #: src/views/certificate/DNSCredential.vue:33
 #: src/views/config/configColumns.tsx:42
-#: src/views/environments/group/columns.ts:28
+#: src/views/environments/group/columns.ts:42
 #: src/views/environments/list/envColumns.tsx:97
 #: src/views/nginx_log/NginxLogList.vue:53
 #: src/views/notification/notificationColumns.tsx:66
@@ -669,7 +669,7 @@ msgid ""
 "Backup files will be automatically downloaded to your computer."
 msgstr ""
 
-#: src/views/environments/group/columns.ts:16
+#: src/views/environments/group/columns.ts:30
 #: src/views/notification/notificationColumns.tsx:59
 #: src/views/preference/components/Passkey.vue:95
 #: src/views/user/userColumns.tsx:48
@@ -1166,19 +1166,6 @@ msgstr "Activé avec succès"
 msgid "Encrypt website with Let's Encrypt"
 msgstr "Crypter le site Web avec Let's Encrypt"
 
-#: src/views/site/site_edit/RightSettings.vue:91
-#: src/views/site/site_list/columns.tsx:25
-#: src/views/stream/components/RightSettings.vue:90
-#: src/views/stream/StreamList.vue:28
-#, fuzzy
-msgid "Environment Group"
-msgstr "Commentaires"
-
-#: src/views/environments/group/EnvGroup.vue:10
-#, fuzzy
-msgid "Environment Groups"
-msgstr "Commentaires"
-
 #: src/language/constants.ts:22
 #, fuzzy
 msgid "Environment variables cleaned"
@@ -1598,10 +1585,6 @@ msgstr "Obtention du certificat, veuillez patienter..."
 msgid "Github Proxy"
 msgstr "Proxy Github"
 
-#: src/routes/modules/environments.ts:33
-msgid "Groups"
-msgstr ""
-
 #: src/constants/errors/backup.ts:59
 msgid "Hash verification failed: file integrity compromised"
 msgstr ""
@@ -2047,7 +2030,7 @@ msgstr "Directive multiligne"
 #: src/views/certificate/DNSCredential.vue:11
 #: src/views/config/components/Mkdir.vue:64
 #: src/views/config/configColumns.tsx:7 src/views/config/ConfigEditor.vue:256
-#: src/views/environments/group/columns.ts:7
+#: src/views/environments/group/columns.ts:8
 #: src/views/environments/list/envColumns.tsx:9
 #: src/views/nginx_log/NginxLogList.vue:37
 #: src/views/preference/components/AddPasskey.vue:75
@@ -2252,11 +2235,31 @@ msgstr "Erreur d'analyse de configuration Nginx"
 msgid "No"
 msgstr "Non"
 
+#: src/views/environments/group/columns.ts:21
+#: src/views/environments/group/EnvGroup.vue:34
+#, fuzzy
+msgid "No Action"
+msgstr "Action"
+
 #: src/views/preference/Preference.vue:168
 #, fuzzy
 msgid "Node"
 msgstr "Nom d'utilisateur"
 
+#: src/views/site/site_edit/RightSettings.vue:91
+#: src/views/site/site_list/columns.tsx:25
+#: src/views/stream/components/RightSettings.vue:90
+#: src/views/stream/StreamList.vue:28
+#, fuzzy
+msgid "Node Group"
+msgstr "Commentaires"
+
+#: src/routes/modules/environments.ts:33
+#: src/views/environments/group/EnvGroup.vue:10
+#, fuzzy
+msgid "Node Groups"
+msgstr "Commentaires"
+
 #: src/views/preference/NodeSettings.vue:15
 #, fuzzy
 msgid "Node name"
@@ -2596,6 +2599,12 @@ msgstr ""
 msgid "Port"
 msgstr "Port HTTP"
 
+#: src/views/environments/group/columns.ts:17
+#: src/views/environments/group/EnvGroup.vue:26
+#, fuzzy
+msgid "Post-sync Action"
+msgstr "Action"
+
 #: src/views/environments/list/BatchUpgrader.vue:167
 #: src/views/environments/list/BatchUpgrader.vue:220
 #: src/views/system/Upgrade.vue:194 src/views/system/Upgrade.vue:245
@@ -2738,6 +2747,8 @@ msgid "Reload"
 msgstr "Recharger"
 
 #: src/components/EnvGroupTabs/EnvGroupTabs.vue:156
+#: src/views/environments/group/columns.ts:23
+#: src/views/environments/group/EnvGroup.vue:37
 #: src/views/environments/list/Environment.vue:120
 #: src/views/environments/list/Environment.vue:128
 #, fuzzy
@@ -3096,6 +3107,10 @@ msgstr ""
 msgid "Security Token Information"
 msgstr "Format de la requête invalide"
 
+#: src/views/environments/group/EnvGroup.vue:29
+msgid "Select an action after sync"
+msgstr ""
+
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:189
 msgid "Selector"
 msgstr "Sélecteur"
@@ -3729,7 +3744,7 @@ msgstr "Mis à jour avec succés"
 #: src/views/certificate/ACMEUser.vue:88
 #: src/views/certificate/DNSCredential.vue:27
 #: src/views/config/configColumns.tsx:34 src/views/config/ConfigEditor.vue:276
-#: src/views/environments/group/columns.ts:22
+#: src/views/environments/group/columns.ts:36
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/site/site_edit/RightSettings.vue:100
 #: src/views/site/site_list/columns.tsx:69
@@ -3898,13 +3913,13 @@ msgstr ""
 #: src/views/site/site_edit/RightSettings.vue:116
 msgid ""
 "When you enable/disable, delete, or save this site, the nodes set in the "
-"environment group and the nodes selected below will be synchronized."
+"Node Group and the nodes selected below will be synchronized."
 msgstr ""
 
 #: src/views/stream/components/RightSettings.vue:114
 msgid ""
 "When you enable/disable, delete, or save this stream, the nodes set in the "
-"environment group and the nodes selected below will be synchronized."
+"Node Group and the nodes selected below will be synchronized."
 msgstr ""
 
 #: src/views/preference/components/RecoveryCodes.vue:140

+ 38 - 23
app/src/language/ko_KR/app.po

@@ -44,7 +44,7 @@ msgstr "ACME 사용자"
 #: src/views/certificate/CertificateList/certColumns.tsx:97
 #: src/views/certificate/DNSCredential.vue:33
 #: src/views/config/configColumns.tsx:42
-#: src/views/environments/group/columns.ts:28
+#: src/views/environments/group/columns.ts:42
 #: src/views/environments/list/envColumns.tsx:97
 #: src/views/nginx_log/NginxLogList.vue:53
 #: src/views/notification/notificationColumns.tsx:66
@@ -638,7 +638,7 @@ msgid ""
 "Backup files will be automatically downloaded to your computer."
 msgstr ""
 
-#: src/views/environments/group/columns.ts:16
+#: src/views/environments/group/columns.ts:30
 #: src/views/notification/notificationColumns.tsx:59
 #: src/views/preference/components/Passkey.vue:95
 #: src/views/user/userColumns.tsx:48
@@ -1116,19 +1116,6 @@ msgstr "성공적으로 활성화됨"
 msgid "Encrypt website with Let's Encrypt"
 msgstr "Let's Encrypt로 웹사이트 암호화"
 
-#: src/views/site/site_edit/RightSettings.vue:91
-#: src/views/site/site_list/columns.tsx:25
-#: src/views/stream/components/RightSettings.vue:90
-#: src/views/stream/StreamList.vue:28
-#, fuzzy
-msgid "Environment Group"
-msgstr "환경"
-
-#: src/views/environments/group/EnvGroup.vue:10
-#, fuzzy
-msgid "Environment Groups"
-msgstr "환경"
-
 #: src/language/constants.ts:22
 #, fuzzy
 msgid "Environment variables cleaned"
@@ -1537,10 +1524,6 @@ msgstr "인증서를 가져오는 중입니다. 잠시 기다려 주세요..."
 msgid "Github Proxy"
 msgstr "Github 프록시"
 
-#: src/routes/modules/environments.ts:33
-msgid "Groups"
-msgstr ""
-
 #: src/constants/errors/backup.ts:59
 msgid "Hash verification failed: file integrity compromised"
 msgstr ""
@@ -1978,7 +1961,7 @@ msgstr "단일 지시문"
 #: src/views/certificate/DNSCredential.vue:11
 #: src/views/config/components/Mkdir.vue:64
 #: src/views/config/configColumns.tsx:7 src/views/config/ConfigEditor.vue:256
-#: src/views/environments/group/columns.ts:7
+#: src/views/environments/group/columns.ts:8
 #: src/views/environments/list/envColumns.tsx:9
 #: src/views/nginx_log/NginxLogList.vue:37
 #: src/views/preference/components/AddPasskey.vue:75
@@ -2183,11 +2166,31 @@ msgstr "Nginx 구성 오류름"
 msgid "No"
 msgstr "아니요"
 
+#: src/views/environments/group/columns.ts:21
+#: src/views/environments/group/EnvGroup.vue:34
+#, fuzzy
+msgid "No Action"
+msgstr "작업"
+
 #: src/views/preference/Preference.vue:168
 #, fuzzy
 msgid "Node"
 msgstr "이름 변경"
 
+#: src/views/site/site_edit/RightSettings.vue:91
+#: src/views/site/site_list/columns.tsx:25
+#: src/views/stream/components/RightSettings.vue:90
+#: src/views/stream/StreamList.vue:28
+#, fuzzy
+msgid "Node Group"
+msgstr "환경"
+
+#: src/routes/modules/environments.ts:33
+#: src/views/environments/group/EnvGroup.vue:10
+#, fuzzy
+msgid "Node Groups"
+msgstr "환경"
+
 #: src/views/preference/NodeSettings.vue:15
 #, fuzzy
 msgid "Node name"
@@ -2527,6 +2530,12 @@ msgstr "적어도 하나의 노드를 선택해주세요!"
 msgid "Port"
 msgstr "HTTP 포트"
 
+#: src/views/environments/group/columns.ts:17
+#: src/views/environments/group/EnvGroup.vue:26
+#, fuzzy
+msgid "Post-sync Action"
+msgstr "작업"
+
 #: src/views/environments/list/BatchUpgrader.vue:167
 #: src/views/environments/list/BatchUpgrader.vue:220
 #: src/views/system/Upgrade.vue:194 src/views/system/Upgrade.vue:245
@@ -2668,6 +2677,8 @@ msgid "Reload"
 msgstr "리로드"
 
 #: src/components/EnvGroupTabs/EnvGroupTabs.vue:156
+#: src/views/environments/group/columns.ts:23
+#: src/views/environments/group/EnvGroup.vue:37
 #: src/views/environments/list/Environment.vue:120
 #: src/views/environments/list/Environment.vue:128
 #, fuzzy
@@ -3027,6 +3038,10 @@ msgstr ""
 msgid "Security Token Information"
 msgstr ""
 
+#: src/views/environments/group/EnvGroup.vue:29
+msgid "Select an action after sync"
+msgstr ""
+
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:189
 msgid "Selector"
 msgstr "선택"
@@ -3651,7 +3666,7 @@ msgstr "성공적으로 저장되었습니다"
 #: src/views/certificate/ACMEUser.vue:88
 #: src/views/certificate/DNSCredential.vue:27
 #: src/views/config/configColumns.tsx:34 src/views/config/ConfigEditor.vue:276
-#: src/views/environments/group/columns.ts:22
+#: src/views/environments/group/columns.ts:36
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/site/site_edit/RightSettings.vue:100
 #: src/views/site/site_list/columns.tsx:69
@@ -3825,13 +3840,13 @@ msgstr ""
 #: src/views/site/site_edit/RightSettings.vue:116
 msgid ""
 "When you enable/disable, delete, or save this site, the nodes set in the "
-"environment group and the nodes selected below will be synchronized."
+"Node Group and the nodes selected below will be synchronized."
 msgstr ""
 
 #: src/views/stream/components/RightSettings.vue:114
 msgid ""
 "When you enable/disable, delete, or save this stream, the nodes set in the "
-"environment group and the nodes selected below will be synchronized."
+"Node Group and the nodes selected below will be synchronized."
 msgstr ""
 
 #: src/views/preference/components/RecoveryCodes.vue:140

+ 34 - 21
app/src/language/messages.pot

@@ -33,7 +33,7 @@ msgstr ""
 #: src/views/certificate/CertificateList/certColumns.tsx:97
 #: src/views/certificate/DNSCredential.vue:33
 #: src/views/config/configColumns.tsx:42
-#: src/views/environments/group/columns.ts:28
+#: src/views/environments/group/columns.ts:42
 #: src/views/environments/list/envColumns.tsx:97
 #: src/views/nginx_log/NginxLogList.vue:53
 #: src/views/notification/notificationColumns.tsx:66
@@ -602,7 +602,7 @@ msgstr ""
 msgid "Create system backups including Nginx configuration and Nginx UI settings. Backup files will be automatically downloaded to your computer."
 msgstr ""
 
-#: src/views/environments/group/columns.ts:16
+#: src/views/environments/group/columns.ts:30
 #: src/views/notification/notificationColumns.tsx:59
 #: src/views/preference/components/Passkey.vue:95
 #: src/views/user/userColumns.tsx:48
@@ -1056,17 +1056,6 @@ msgstr ""
 msgid "Encrypt website with Let's Encrypt"
 msgstr ""
 
-#: src/views/site/site_edit/RightSettings.vue:91
-#: src/views/site/site_list/columns.tsx:25
-#: src/views/stream/components/RightSettings.vue:90
-#: src/views/stream/StreamList.vue:28
-msgid "Environment Group"
-msgstr ""
-
-#: src/views/environments/group/EnvGroup.vue:10
-msgid "Environment Groups"
-msgstr ""
-
 #: src/language/constants.ts:22
 msgid "Environment variables cleaned"
 msgstr ""
@@ -1436,10 +1425,6 @@ msgstr ""
 msgid "Github Proxy"
 msgstr ""
 
-#: src/routes/modules/environments.ts:33
-msgid "Groups"
-msgstr ""
-
 #: src/constants/errors/backup.ts:59
 msgid "Hash verification failed: file integrity compromised"
 msgstr ""
@@ -1834,7 +1819,7 @@ msgstr ""
 #: src/views/config/components/Mkdir.vue:64
 #: src/views/config/configColumns.tsx:7
 #: src/views/config/ConfigEditor.vue:256
-#: src/views/environments/group/columns.ts:7
+#: src/views/environments/group/columns.ts:8
 #: src/views/environments/list/envColumns.tsx:9
 #: src/views/nginx_log/NginxLogList.vue:37
 #: src/views/preference/components/AddPasskey.vue:75
@@ -2024,10 +2009,27 @@ msgstr ""
 msgid "No"
 msgstr ""
 
+#: src/views/environments/group/columns.ts:21
+#: src/views/environments/group/EnvGroup.vue:34
+msgid "No Action"
+msgstr ""
+
 #: src/views/preference/Preference.vue:168
 msgid "Node"
 msgstr ""
 
+#: src/views/site/site_edit/RightSettings.vue:91
+#: src/views/site/site_list/columns.tsx:25
+#: src/views/stream/components/RightSettings.vue:90
+#: src/views/stream/StreamList.vue:28
+msgid "Node Group"
+msgstr ""
+
+#: src/routes/modules/environments.ts:33
+#: src/views/environments/group/EnvGroup.vue:10
+msgid "Node Groups"
+msgstr ""
+
 #: src/views/preference/NodeSettings.vue:15
 msgid "Node name"
 msgstr ""
@@ -2336,6 +2338,11 @@ msgstr ""
 msgid "Port"
 msgstr ""
 
+#: src/views/environments/group/columns.ts:17
+#: src/views/environments/group/EnvGroup.vue:26
+msgid "Post-sync Action"
+msgstr ""
+
 #: src/views/environments/list/BatchUpgrader.vue:167
 #: src/views/environments/list/BatchUpgrader.vue:220
 #: src/views/system/Upgrade.vue:194
@@ -2465,6 +2472,8 @@ msgid "Reload"
 msgstr ""
 
 #: src/components/EnvGroupTabs/EnvGroupTabs.vue:156
+#: src/views/environments/group/columns.ts:23
+#: src/views/environments/group/EnvGroup.vue:37
 #: src/views/environments/list/Environment.vue:120
 #: src/views/environments/list/Environment.vue:128
 msgid "Reload Nginx"
@@ -2784,6 +2793,10 @@ msgstr ""
 msgid "Security Token Information"
 msgstr ""
 
+#: src/views/environments/group/EnvGroup.vue:29
+msgid "Select an action after sync"
+msgstr ""
+
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:189
 msgid "Selector"
 msgstr ""
@@ -3316,7 +3329,7 @@ msgstr ""
 #: src/views/certificate/DNSCredential.vue:27
 #: src/views/config/configColumns.tsx:34
 #: src/views/config/ConfigEditor.vue:276
-#: src/views/environments/group/columns.ts:22
+#: src/views/environments/group/columns.ts:36
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/site/site_edit/RightSettings.vue:100
 #: src/views/site/site_list/columns.tsx:69
@@ -3468,11 +3481,11 @@ msgid "When Enabled, Nginx UI will automatically re-register users upon startup.
 msgstr ""
 
 #: src/views/site/site_edit/RightSettings.vue:116
-msgid "When you enable/disable, delete, or save this site, the nodes set in the environment 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 ""
 
 #: src/views/stream/components/RightSettings.vue:114
-msgid "When you enable/disable, delete, or save this stream, the nodes set in the environment group and the nodes selected below will be synchronized."
+msgid "When you enable/disable, delete, or save this stream, the nodes set in the Node Group and the nodes selected below will be synchronized."
 msgstr ""
 
 #: src/views/preference/components/RecoveryCodes.vue:140

+ 38 - 23
app/src/language/ru_RU/app.po

@@ -46,7 +46,7 @@ msgstr "Пользователь ACME"
 #: src/views/certificate/CertificateList/certColumns.tsx:97
 #: src/views/certificate/DNSCredential.vue:33
 #: src/views/config/configColumns.tsx:42
-#: src/views/environments/group/columns.ts:28
+#: src/views/environments/group/columns.ts:42
 #: src/views/environments/list/envColumns.tsx:97
 #: src/views/nginx_log/NginxLogList.vue:53
 #: src/views/notification/notificationColumns.tsx:66
@@ -628,7 +628,7 @@ msgid ""
 "Backup files will be automatically downloaded to your computer."
 msgstr ""
 
-#: src/views/environments/group/columns.ts:16
+#: src/views/environments/group/columns.ts:30
 #: src/views/notification/notificationColumns.tsx:59
 #: src/views/preference/components/Passkey.vue:95
 #: src/views/user/userColumns.tsx:48
@@ -1102,19 +1102,6 @@ msgstr "Активировано успешно"
 msgid "Encrypt website with Let's Encrypt"
 msgstr "Использовать для сайта Let's Encrypt"
 
-#: src/views/site/site_edit/RightSettings.vue:91
-#: src/views/site/site_list/columns.tsx:25
-#: src/views/stream/components/RightSettings.vue:90
-#: src/views/stream/StreamList.vue:28
-#, fuzzy
-msgid "Environment Group"
-msgstr "Окружение"
-
-#: src/views/environments/group/EnvGroup.vue:10
-#, fuzzy
-msgid "Environment Groups"
-msgstr "Окружения"
-
 #: src/language/constants.ts:22
 msgid "Environment variables cleaned"
 msgstr "Переменные окружения очищены"
@@ -1520,10 +1507,6 @@ msgstr "Получение сертификата, пожалуйста, под
 msgid "Github Proxy"
 msgstr "Прокси Github"
 
-#: src/routes/modules/environments.ts:33
-msgid "Groups"
-msgstr ""
-
 #: src/constants/errors/backup.ts:59
 msgid "Hash verification failed: file integrity compromised"
 msgstr ""
@@ -1947,7 +1930,7 @@ msgstr "Многострочная директива"
 #: src/views/certificate/DNSCredential.vue:11
 #: src/views/config/components/Mkdir.vue:64
 #: src/views/config/configColumns.tsx:7 src/views/config/ConfigEditor.vue:256
-#: src/views/environments/group/columns.ts:7
+#: src/views/environments/group/columns.ts:8
 #: src/views/environments/list/envColumns.tsx:9
 #: src/views/nginx_log/NginxLogList.vue:37
 #: src/views/preference/components/AddPasskey.vue:75
@@ -2147,11 +2130,31 @@ msgstr "Ошибка разбора конфигурации Nginx"
 msgid "No"
 msgstr "Нет"
 
+#: src/views/environments/group/columns.ts:21
+#: src/views/environments/group/EnvGroup.vue:34
+#, fuzzy
+msgid "No Action"
+msgstr "Действие"
+
 #: src/views/preference/Preference.vue:168
 #, fuzzy
 msgid "Node"
 msgstr "Имя узла"
 
+#: src/views/site/site_edit/RightSettings.vue:91
+#: src/views/site/site_list/columns.tsx:25
+#: src/views/stream/components/RightSettings.vue:90
+#: src/views/stream/StreamList.vue:28
+#, fuzzy
+msgid "Node Group"
+msgstr "Окружение"
+
+#: src/routes/modules/environments.ts:33
+#: src/views/environments/group/EnvGroup.vue:10
+#, fuzzy
+msgid "Node Groups"
+msgstr "Окружения"
+
 #: src/views/preference/NodeSettings.vue:15
 msgid "Node name"
 msgstr "Имя узла"
@@ -2497,6 +2500,12 @@ msgstr "Пожалуйста, выберите хотя бы один узел"
 msgid "Port"
 msgstr "Порт HTTP"
 
+#: src/views/environments/group/columns.ts:17
+#: src/views/environments/group/EnvGroup.vue:26
+#, fuzzy
+msgid "Post-sync Action"
+msgstr "Действие"
+
 #: src/views/environments/list/BatchUpgrader.vue:167
 #: src/views/environments/list/BatchUpgrader.vue:220
 #: src/views/system/Upgrade.vue:194 src/views/system/Upgrade.vue:245
@@ -2633,6 +2642,8 @@ msgid "Reload"
 msgstr "Перегрузить"
 
 #: src/components/EnvGroupTabs/EnvGroupTabs.vue:156
+#: src/views/environments/group/columns.ts:23
+#: src/views/environments/group/EnvGroup.vue:37
 #: src/views/environments/list/Environment.vue:120
 #: src/views/environments/list/Environment.vue:128
 #, fuzzy
@@ -2977,6 +2988,10 @@ msgstr ""
 msgid "Security Token Information"
 msgstr "Неверный код восстановления"
 
+#: src/views/environments/group/EnvGroup.vue:29
+msgid "Select an action after sync"
+msgstr ""
+
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:189
 msgid "Selector"
 msgstr "Выбор"
@@ -3611,7 +3626,7 @@ msgstr "Успешно обновлено"
 #: src/views/certificate/ACMEUser.vue:88
 #: src/views/certificate/DNSCredential.vue:27
 #: src/views/config/configColumns.tsx:34 src/views/config/ConfigEditor.vue:276
-#: src/views/environments/group/columns.ts:22
+#: src/views/environments/group/columns.ts:36
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/site/site_edit/RightSettings.vue:100
 #: src/views/site/site_list/columns.tsx:69
@@ -3779,13 +3794,13 @@ msgstr ""
 #: src/views/site/site_edit/RightSettings.vue:116
 msgid ""
 "When you enable/disable, delete, or save this site, the nodes set in the "
-"environment group and the nodes selected below will be synchronized."
+"Node Group and the nodes selected below will be synchronized."
 msgstr ""
 
 #: src/views/stream/components/RightSettings.vue:114
 msgid ""
 "When you enable/disable, delete, or save this stream, the nodes set in the "
-"environment group and the nodes selected below will be synchronized."
+"Node Group and the nodes selected below will be synchronized."
 msgstr ""
 
 #: src/views/preference/components/RecoveryCodes.vue:140

+ 38 - 23
app/src/language/tr_TR/app.po

@@ -42,7 +42,7 @@ msgstr "ACME Kullanıcısı"
 #: src/views/certificate/CertificateList/certColumns.tsx:97
 #: src/views/certificate/DNSCredential.vue:33
 #: src/views/config/configColumns.tsx:42
-#: src/views/environments/group/columns.ts:28
+#: src/views/environments/group/columns.ts:42
 #: src/views/environments/list/envColumns.tsx:97
 #: src/views/nginx_log/NginxLogList.vue:53
 #: src/views/notification/notificationColumns.tsx:66
@@ -634,7 +634,7 @@ msgid ""
 "Backup files will be automatically downloaded to your computer."
 msgstr ""
 
-#: src/views/environments/group/columns.ts:16
+#: src/views/environments/group/columns.ts:30
 #: src/views/notification/notificationColumns.tsx:59
 #: src/views/preference/components/Passkey.vue:95
 #: src/views/user/userColumns.tsx:48
@@ -1131,19 +1131,6 @@ msgstr "Başarıyla etkinleştirildi"
 msgid "Encrypt website with Let's Encrypt"
 msgstr "Let's Encrypt ile web sitesini şifreleyin"
 
-#: src/views/site/site_edit/RightSettings.vue:91
-#: src/views/site/site_list/columns.tsx:25
-#: src/views/stream/components/RightSettings.vue:90
-#: src/views/stream/StreamList.vue:28
-#, fuzzy
-msgid "Environment Group"
-msgstr "Ortam"
-
-#: src/views/environments/group/EnvGroup.vue:10
-#, fuzzy
-msgid "Environment Groups"
-msgstr "Ortamlar"
-
 #: src/language/constants.ts:22
 msgid "Environment variables cleaned"
 msgstr "Ortam değişkenleri temizlendi"
@@ -1549,10 +1536,6 @@ msgstr "Sertifika alınıyor, lütfen bekleyin..."
 msgid "Github Proxy"
 msgstr "Github Proxy"
 
-#: src/routes/modules/environments.ts:33
-msgid "Groups"
-msgstr ""
-
 #: src/constants/errors/backup.ts:59
 msgid "Hash verification failed: file integrity compromised"
 msgstr ""
@@ -1994,7 +1977,7 @@ msgstr "Çok Hatlı Direktif"
 #: src/views/certificate/DNSCredential.vue:11
 #: src/views/config/components/Mkdir.vue:64
 #: src/views/config/configColumns.tsx:7 src/views/config/ConfigEditor.vue:256
-#: src/views/environments/group/columns.ts:7
+#: src/views/environments/group/columns.ts:8
 #: src/views/environments/list/envColumns.tsx:9
 #: src/views/nginx_log/NginxLogList.vue:37
 #: src/views/preference/components/AddPasskey.vue:75
@@ -2213,11 +2196,31 @@ msgstr "Nginx Yapılandırma Ayrıştırma Hatası"
 msgid "No"
 msgstr "Hayır"
 
+#: src/views/environments/group/columns.ts:21
+#: src/views/environments/group/EnvGroup.vue:34
+#, fuzzy
+msgid "No Action"
+msgstr "Eylem"
+
 #: src/views/preference/Preference.vue:168
 #, fuzzy
 msgid "Node"
 msgstr "Yeni Ad"
 
+#: src/views/site/site_edit/RightSettings.vue:91
+#: src/views/site/site_list/columns.tsx:25
+#: src/views/stream/components/RightSettings.vue:90
+#: src/views/stream/StreamList.vue:28
+#, fuzzy
+msgid "Node Group"
+msgstr "Ortam"
+
+#: src/routes/modules/environments.ts:33
+#: src/views/environments/group/EnvGroup.vue:10
+#, fuzzy
+msgid "Node Groups"
+msgstr "Ortamlar"
+
 #: src/views/preference/NodeSettings.vue:15
 #, fuzzy
 msgid "Node name"
@@ -2611,6 +2614,12 @@ msgstr "Lütfen yükseltmek için en az bir düğüm seçin"
 msgid "Port"
 msgstr "HTTP bağlantı noktası"
 
+#: src/views/environments/group/columns.ts:17
+#: src/views/environments/group/EnvGroup.vue:26
+#, fuzzy
+msgid "Post-sync Action"
+msgstr "Eylem"
+
 #: src/views/environments/list/BatchUpgrader.vue:167
 #: src/views/environments/list/BatchUpgrader.vue:220
 #: src/views/system/Upgrade.vue:194 src/views/system/Upgrade.vue:245
@@ -2771,6 +2780,8 @@ msgid "Reload"
 msgstr "Tekrar yükle"
 
 #: src/components/EnvGroupTabs/EnvGroupTabs.vue:156
+#: src/views/environments/group/columns.ts:23
+#: src/views/environments/group/EnvGroup.vue:37
 #: src/views/environments/list/Environment.vue:120
 #: src/views/environments/list/Environment.vue:128
 #, fuzzy
@@ -3155,6 +3166,10 @@ msgstr ""
 msgid "Security Token Information"
 msgstr "Geçersiz 2FA veya kurtarma kodu"
 
+#: src/views/environments/group/EnvGroup.vue:29
+msgid "Select an action after sync"
+msgstr ""
+
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:189
 #, fuzzy
 msgid "Selector"
@@ -3858,7 +3873,7 @@ msgstr "Güncellendi"
 #: src/views/certificate/ACMEUser.vue:88
 #: src/views/certificate/DNSCredential.vue:27
 #: src/views/config/configColumns.tsx:34 src/views/config/ConfigEditor.vue:276
-#: src/views/environments/group/columns.ts:22
+#: src/views/environments/group/columns.ts:36
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/site/site_edit/RightSettings.vue:100
 #: src/views/site/site_list/columns.tsx:69
@@ -4052,13 +4067,13 @@ msgstr ""
 #: src/views/site/site_edit/RightSettings.vue:116
 msgid ""
 "When you enable/disable, delete, or save this site, the nodes set in the "
-"environment group and the nodes selected below will be synchronized."
+"Node Group and the nodes selected below will be synchronized."
 msgstr ""
 
 #: src/views/stream/components/RightSettings.vue:114
 msgid ""
 "When you enable/disable, delete, or save this stream, the nodes set in the "
-"environment group and the nodes selected below will be synchronized."
+"Node Group and the nodes selected below will be synchronized."
 msgstr ""
 
 #: src/views/preference/components/RecoveryCodes.vue:140

+ 38 - 23
app/src/language/vi_VN/app.po

@@ -40,7 +40,7 @@ msgstr "Người dùng"
 #: src/views/certificate/CertificateList/certColumns.tsx:97
 #: src/views/certificate/DNSCredential.vue:33
 #: src/views/config/configColumns.tsx:42
-#: src/views/environments/group/columns.ts:28
+#: src/views/environments/group/columns.ts:42
 #: src/views/environments/list/envColumns.tsx:97
 #: src/views/nginx_log/NginxLogList.vue:53
 #: src/views/notification/notificationColumns.tsx:66
@@ -660,7 +660,7 @@ msgid ""
 "Backup files will be automatically downloaded to your computer."
 msgstr ""
 
-#: src/views/environments/group/columns.ts:16
+#: src/views/environments/group/columns.ts:30
 #: src/views/notification/notificationColumns.tsx:59
 #: src/views/preference/components/Passkey.vue:95
 #: src/views/user/userColumns.tsx:48
@@ -1152,19 +1152,6 @@ msgstr "Đã bật"
 msgid "Encrypt website with Let's Encrypt"
 msgstr "Bảo mật trang web với Let's Encrypt"
 
-#: src/views/site/site_edit/RightSettings.vue:91
-#: src/views/site/site_list/columns.tsx:25
-#: src/views/stream/components/RightSettings.vue:90
-#: src/views/stream/StreamList.vue:28
-#, fuzzy
-msgid "Environment Group"
-msgstr "Environment"
-
-#: src/views/environments/group/EnvGroup.vue:10
-#, fuzzy
-msgid "Environment Groups"
-msgstr "Environments"
-
 #: src/language/constants.ts:22
 #, fuzzy
 msgid "Environment variables cleaned"
@@ -1575,10 +1562,6 @@ msgstr "Đang lấy chứng chỉ, vui lòng đợi..."
 msgid "Github Proxy"
 msgstr ""
 
-#: src/routes/modules/environments.ts:33
-msgid "Groups"
-msgstr ""
-
 #: src/constants/errors/backup.ts:59
 msgid "Hash verification failed: file integrity compromised"
 msgstr ""
@@ -2010,7 +1993,7 @@ msgstr "Single Directive"
 #: src/views/certificate/DNSCredential.vue:11
 #: src/views/config/components/Mkdir.vue:64
 #: src/views/config/configColumns.tsx:7 src/views/config/ConfigEditor.vue:256
-#: src/views/environments/group/columns.ts:7
+#: src/views/environments/group/columns.ts:8
 #: src/views/environments/list/envColumns.tsx:9
 #: src/views/nginx_log/NginxLogList.vue:37
 #: src/views/preference/components/AddPasskey.vue:75
@@ -2213,11 +2196,31 @@ msgstr "Lỗi phân tích cú pháp cấu hình Nginx"
 msgid "No"
 msgstr "Không"
 
+#: src/views/environments/group/columns.ts:21
+#: src/views/environments/group/EnvGroup.vue:34
+#, fuzzy
+msgid "No Action"
+msgstr "Hành động"
+
 #: src/views/preference/Preference.vue:168
 #, fuzzy
 msgid "Node"
 msgstr "Username"
 
+#: src/views/site/site_edit/RightSettings.vue:91
+#: src/views/site/site_list/columns.tsx:25
+#: src/views/stream/components/RightSettings.vue:90
+#: src/views/stream/StreamList.vue:28
+#, fuzzy
+msgid "Node Group"
+msgstr "Environment"
+
+#: src/routes/modules/environments.ts:33
+#: src/views/environments/group/EnvGroup.vue:10
+#, fuzzy
+msgid "Node Groups"
+msgstr "Environments"
+
 #: src/views/preference/NodeSettings.vue:15
 #, fuzzy
 msgid "Node name"
@@ -2556,6 +2559,12 @@ msgstr ""
 msgid "Port"
 msgstr ""
 
+#: src/views/environments/group/columns.ts:17
+#: src/views/environments/group/EnvGroup.vue:26
+#, fuzzy
+msgid "Post-sync Action"
+msgstr "Hành động"
+
 #: src/views/environments/list/BatchUpgrader.vue:167
 #: src/views/environments/list/BatchUpgrader.vue:220
 #: src/views/system/Upgrade.vue:194 src/views/system/Upgrade.vue:245
@@ -2696,6 +2705,8 @@ msgid "Reload"
 msgstr "Tải lại"
 
 #: src/components/EnvGroupTabs/EnvGroupTabs.vue:156
+#: src/views/environments/group/columns.ts:23
+#: src/views/environments/group/EnvGroup.vue:37
 #: src/views/environments/list/Environment.vue:120
 #: src/views/environments/list/Environment.vue:128
 #, fuzzy
@@ -3055,6 +3066,10 @@ msgstr ""
 msgid "Security Token Information"
 msgstr ""
 
+#: src/views/environments/group/EnvGroup.vue:29
+msgid "Select an action after sync"
+msgstr ""
+
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:189
 msgid "Selector"
 msgstr "Bộ chọn"
@@ -3672,7 +3687,7 @@ msgstr "Cập nhật thành công"
 #: src/views/certificate/ACMEUser.vue:88
 #: src/views/certificate/DNSCredential.vue:27
 #: src/views/config/configColumns.tsx:34 src/views/config/ConfigEditor.vue:276
-#: src/views/environments/group/columns.ts:22
+#: src/views/environments/group/columns.ts:36
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/site/site_edit/RightSettings.vue:100
 #: src/views/site/site_list/columns.tsx:69
@@ -3846,13 +3861,13 @@ msgstr ""
 #: src/views/site/site_edit/RightSettings.vue:116
 msgid ""
 "When you enable/disable, delete, or save this site, the nodes set in the "
-"environment group and the nodes selected below will be synchronized."
+"Node Group and the nodes selected below will be synchronized."
 msgstr ""
 
 #: src/views/stream/components/RightSettings.vue:114
 msgid ""
 "When you enable/disable, delete, or save this stream, the nodes set in the "
-"environment group and the nodes selected below will be synchronized."
+"Node Group and the nodes selected below will be synchronized."
 msgstr ""
 
 #: src/views/preference/components/RecoveryCodes.vue:140

+ 48 - 32
app/src/language/zh_CN/app.po

@@ -3,7 +3,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: \n"
 "POT-Creation-Date: \n"
-"PO-Revision-Date: 2025-04-05 15:35+0800\n"
+"PO-Revision-Date: 2025-04-05 17:43+0800\n"
 "Last-Translator: 0xJacky <me@jackyu.cn>\n"
 "Language-Team: Chinese (Simplified Han script) <https://weblate.nginxui.com/"
 "projects/nginx-ui/frontend/zh_Hans/>\n"
@@ -44,7 +44,7 @@ msgstr "ACME 用户"
 #: src/views/certificate/CertificateList/certColumns.tsx:97
 #: src/views/certificate/DNSCredential.vue:33
 #: src/views/config/configColumns.tsx:42
-#: src/views/environments/group/columns.ts:28
+#: src/views/environments/group/columns.ts:42
 #: src/views/environments/list/envColumns.tsx:97
 #: src/views/nginx_log/NginxLogList.vue:53
 #: src/views/notification/notificationColumns.tsx:66
@@ -616,7 +616,7 @@ msgid ""
 msgstr ""
 "创建系统备份,包括 Nginx 配置和 Nginx UI 设置。备份文件将自动下载到你的电脑。"
 
-#: src/views/environments/group/columns.ts:16
+#: src/views/environments/group/columns.ts:30
 #: src/views/notification/notificationColumns.tsx:59
 #: src/views/preference/components/Passkey.vue:95
 #: src/views/user/userColumns.tsx:48
@@ -1062,17 +1062,6 @@ msgstr "启用成功"
 msgid "Encrypt website with Let's Encrypt"
 msgstr "用 Let's Encrypt 对网站进行加密"
 
-#: src/views/site/site_edit/RightSettings.vue:91
-#: src/views/site/site_list/columns.tsx:25
-#: src/views/stream/components/RightSettings.vue:90
-#: src/views/stream/StreamList.vue:28
-msgid "Environment Group"
-msgstr "环境组"
-
-#: src/views/environments/group/EnvGroup.vue:10
-msgid "Environment Groups"
-msgstr "环境组"
-
 #: src/language/constants.ts:22
 msgid "Environment variables cleaned"
 msgstr "环境变量已清理"
@@ -1441,10 +1430,6 @@ msgstr "正在获取证书,请稍等..."
 msgid "Github Proxy"
 msgstr "Github 代理"
 
-#: src/routes/modules/environments.ts:33
-msgid "Groups"
-msgstr "组"
-
 #: src/constants/errors/backup.ts:59
 msgid "Hash verification failed: file integrity compromised"
 msgstr "哈希验证失败:文件完整性受损"
@@ -1856,7 +1841,7 @@ msgstr "多行指令"
 #: src/views/certificate/DNSCredential.vue:11
 #: src/views/config/components/Mkdir.vue:64
 #: src/views/config/configColumns.tsx:7 src/views/config/ConfigEditor.vue:256
-#: src/views/environments/group/columns.ts:7
+#: src/views/environments/group/columns.ts:8
 #: src/views/environments/list/envColumns.tsx:9
 #: src/views/nginx_log/NginxLogList.vue:37
 #: src/views/preference/components/AddPasskey.vue:75
@@ -2046,10 +2031,27 @@ msgstr "Nginx UI 配置已恢复,几秒钟后将自动重启。"
 msgid "No"
 msgstr "取消"
 
+#: src/views/environments/group/columns.ts:21
+#: src/views/environments/group/EnvGroup.vue:34
+msgid "No Action"
+msgstr "无操作"
+
 #: src/views/preference/Preference.vue:168
 msgid "Node"
 msgstr "节点"
 
+#: src/views/site/site_edit/RightSettings.vue:91
+#: src/views/site/site_list/columns.tsx:25
+#: src/views/stream/components/RightSettings.vue:90
+#: src/views/stream/StreamList.vue:28
+msgid "Node Group"
+msgstr "节点组"
+
+#: src/routes/modules/environments.ts:33
+#: src/views/environments/group/EnvGroup.vue:10
+msgid "Node Groups"
+msgstr "环境组"
+
 #: src/views/preference/NodeSettings.vue:15
 msgid "Node name"
 msgstr "节点名称"
@@ -2375,6 +2377,11 @@ msgstr "请至少选择一个节点进行升级"
 msgid "Port"
 msgstr "端口"
 
+#: src/views/environments/group/columns.ts:17
+#: src/views/environments/group/EnvGroup.vue:26
+msgid "Post-sync Action"
+msgstr "同步后操作"
+
 #: src/views/environments/list/BatchUpgrader.vue:167
 #: src/views/environments/list/BatchUpgrader.vue:220
 #: src/views/system/Upgrade.vue:194 src/views/system/Upgrade.vue:245
@@ -2508,6 +2515,8 @@ msgid "Reload"
 msgstr "重载"
 
 #: src/components/EnvGroupTabs/EnvGroupTabs.vue:156
+#: src/views/environments/group/columns.ts:23
+#: src/views/environments/group/EnvGroup.vue:37
 #: src/views/environments/list/Environment.vue:120
 #: src/views/environments/list/Environment.vue:128
 msgid "Reload Nginx"
@@ -2821,6 +2830,10 @@ msgstr "安全 Token"
 msgid "Security Token Information"
 msgstr "安全令牌信息"
 
+#: src/views/environments/group/EnvGroup.vue:29
+msgid "Select an action after sync"
+msgstr "选择同步后的操作"
+
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:189
 msgid "Selector"
 msgstr "选择器"
@@ -2874,19 +2887,19 @@ msgstr "使用 HTTP01 challenge provider"
 
 #: src/constants/errors/nginx_log.ts:8
 msgid ""
-"Settings.NginxLogSettings.AccessLogPath is empty, refer to https://nginxui."
-"com/guide/config-nginx.html for more information"
+"Settings.NginxLogSettings.AccessLogPath is empty, refer to https://"
+"nginxui.com/guide/config-nginx.html for more information"
 msgstr ""
-"Settings.NginxLogSettings.AccessLogPath 为空,更多信息请参阅 https://nginxui."
-"com/guide/config-nginx.html"
+"Settings.NginxLogSettings.AccessLogPath 为空,更多信息请参阅 https://"
+"nginxui.com/guide/config-nginx.html"
 
 #: src/constants/errors/nginx_log.ts:7
 msgid ""
-"Settings.NginxLogSettings.ErrorLogPath is empty, refer to https://nginxui."
-"com/guide/config-nginx.html for more information"
+"Settings.NginxLogSettings.ErrorLogPath is empty, refer to https://"
+"nginxui.com/guide/config-nginx.html for more information"
 msgstr ""
-"Settings.NginxLogSettings.ErrorLogPath为空,更多信息请参阅 https://nginxui."
-"com/guide/config-nginx.html"
+"Settings.NginxLogSettings.ErrorLogPath为空,更多信息请参阅 https://"
+"nginxui.com/guide/config-nginx.html"
 
 #: src/components/SensitiveString/SensitiveString.vue:40
 msgid "Show"
@@ -3412,7 +3425,7 @@ msgstr "更新成功"
 #: src/views/certificate/ACMEUser.vue:88
 #: src/views/certificate/DNSCredential.vue:27
 #: src/views/config/configColumns.tsx:34 src/views/config/ConfigEditor.vue:276
-#: src/views/environments/group/columns.ts:22
+#: src/views/environments/group/columns.ts:36
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/site/site_edit/RightSettings.vue:100
 #: src/views/site/site_list/columns.tsx:69
@@ -3577,7 +3590,7 @@ msgstr ""
 #: src/views/site/site_edit/RightSettings.vue:116
 msgid ""
 "When you enable/disable, delete, or save this site, the nodes set in the "
-"environment group and the nodes selected below will be synchronized."
+"Node Group and the nodes selected below will be synchronized."
 msgstr ""
 "启用/禁用、删除或保存此站点时,环境组中设置的节点和下面选择的节点将同步执行操"
 "作。"
@@ -3585,7 +3598,7 @@ msgstr ""
 #: src/views/stream/components/RightSettings.vue:114
 msgid ""
 "When you enable/disable, delete, or save this stream, the nodes set in the "
-"environment group and the nodes selected below will be synchronized."
+"Node Group and the nodes selected below will be synchronized."
 msgstr ""
 "启用/禁用、删除或保存此站点时,环境组中设置的节点和下面选择的节点将同步执行操"
 "作。"
@@ -3671,6 +3684,9 @@ msgstr "您的旧代码将不再有效。"
 msgid "Your passkeys"
 msgstr "你的 Passkeys"
 
+#~ msgid "Groups"
+#~ msgstr "组"
+
 #~ msgid "Nginx has been reloaded on all sync nodes"
 #~ msgstr "已在所有同步节点上重新加载 Nginx"
 
@@ -3715,8 +3731,8 @@ msgstr "你的 Passkeys"
 #~ msgstr "请将远程 Nginx UI 升级到最新版本"
 
 #~ msgid ""
-#~ "Rename %{orig_path} to %{new_path} on %{env_name} failed, response: "
-#~ "%{resp}"
+#~ "Rename %{orig_path} to %{new_path} on %{env_name} failed, response: %"
+#~ "{resp}"
 #~ msgstr ""
 #~ "将 %{env_name} 上的 %{orig_path} 重命名为 %{new_path} 失败,响应:%{resp}"
 

+ 38 - 23
app/src/language/zh_TW/app.po

@@ -49,7 +49,7 @@ msgstr "ACME 用戶"
 #: src/views/certificate/CertificateList/certColumns.tsx:97
 #: src/views/certificate/DNSCredential.vue:33
 #: src/views/config/configColumns.tsx:42
-#: src/views/environments/group/columns.ts:28
+#: src/views/environments/group/columns.ts:42
 #: src/views/environments/list/envColumns.tsx:97
 #: src/views/nginx_log/NginxLogList.vue:53
 #: src/views/notification/notificationColumns.tsx:66
@@ -629,7 +629,7 @@ msgid ""
 "Backup files will be automatically downloaded to your computer."
 msgstr ""
 
-#: src/views/environments/group/columns.ts:16
+#: src/views/environments/group/columns.ts:30
 #: src/views/notification/notificationColumns.tsx:59
 #: src/views/preference/components/Passkey.vue:95
 #: src/views/user/userColumns.tsx:48
@@ -1086,19 +1086,6 @@ msgstr "成功啟用"
 msgid "Encrypt website with Let's Encrypt"
 msgstr "用 Let's Encrypt 對網站進行加密"
 
-#: src/views/site/site_edit/RightSettings.vue:91
-#: src/views/site/site_list/columns.tsx:25
-#: src/views/stream/components/RightSettings.vue:90
-#: src/views/stream/StreamList.vue:28
-#, fuzzy
-msgid "Environment Group"
-msgstr "環境"
-
-#: src/views/environments/group/EnvGroup.vue:10
-#, fuzzy
-msgid "Environment Groups"
-msgstr "環境"
-
 #: src/language/constants.ts:22
 msgid "Environment variables cleaned"
 msgstr "環境變數已清理"
@@ -1503,10 +1490,6 @@ msgstr "正在取得憑證,請稍候..."
 msgid "Github Proxy"
 msgstr "Github 代理"
 
-#: src/routes/modules/environments.ts:33
-msgid "Groups"
-msgstr ""
-
 #: src/constants/errors/backup.ts:59
 msgid "Hash verification failed: file integrity compromised"
 msgstr ""
@@ -1925,7 +1908,7 @@ msgstr "多行指令"
 #: src/views/certificate/DNSCredential.vue:11
 #: src/views/config/components/Mkdir.vue:64
 #: src/views/config/configColumns.tsx:7 src/views/config/ConfigEditor.vue:256
-#: src/views/environments/group/columns.ts:7
+#: src/views/environments/group/columns.ts:8
 #: src/views/environments/list/envColumns.tsx:9
 #: src/views/nginx_log/NginxLogList.vue:37
 #: src/views/preference/components/AddPasskey.vue:75
@@ -2123,11 +2106,31 @@ msgstr "Nginx 設定解析錯誤"
 msgid "No"
 msgstr "取消"
 
+#: src/views/environments/group/columns.ts:21
+#: src/views/environments/group/EnvGroup.vue:34
+#, fuzzy
+msgid "No Action"
+msgstr "操作"
+
 #: src/views/preference/Preference.vue:168
 #, fuzzy
 msgid "Node"
 msgstr "節點名稱"
 
+#: src/views/site/site_edit/RightSettings.vue:91
+#: src/views/site/site_list/columns.tsx:25
+#: src/views/stream/components/RightSettings.vue:90
+#: src/views/stream/StreamList.vue:28
+#, fuzzy
+msgid "Node Group"
+msgstr "環境"
+
+#: src/routes/modules/environments.ts:33
+#: src/views/environments/group/EnvGroup.vue:10
+#, fuzzy
+msgid "Node Groups"
+msgstr "環境"
+
 #: src/views/preference/NodeSettings.vue:15
 msgid "Node name"
 msgstr "節點名稱"
@@ -2460,6 +2463,12 @@ msgstr "請至少選擇一個節點進行升級"
 msgid "Port"
 msgstr "HTTP 監聽埠"
 
+#: src/views/environments/group/columns.ts:17
+#: src/views/environments/group/EnvGroup.vue:26
+#, fuzzy
+msgid "Post-sync Action"
+msgstr "批次操作"
+
 #: src/views/environments/list/BatchUpgrader.vue:167
 #: src/views/environments/list/BatchUpgrader.vue:220
 #: src/views/system/Upgrade.vue:194 src/views/system/Upgrade.vue:245
@@ -2592,6 +2601,8 @@ msgid "Reload"
 msgstr "重新載入"
 
 #: src/components/EnvGroupTabs/EnvGroupTabs.vue:156
+#: src/views/environments/group/columns.ts:23
+#: src/views/environments/group/EnvGroup.vue:37
 #: src/views/environments/list/Environment.vue:120
 #: src/views/environments/list/Environment.vue:128
 #, fuzzy
@@ -2933,6 +2944,10 @@ msgstr ""
 msgid "Security Token Information"
 msgstr "無效的請求格式"
 
+#: src/views/environments/group/EnvGroup.vue:29
+msgid "Select an action after sync"
+msgstr ""
+
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:189
 msgid "Selector"
 msgstr "選擇器"
@@ -3540,7 +3555,7 @@ msgstr "更新成功"
 #: src/views/certificate/ACMEUser.vue:88
 #: src/views/certificate/DNSCredential.vue:27
 #: src/views/config/configColumns.tsx:34 src/views/config/ConfigEditor.vue:276
-#: src/views/environments/group/columns.ts:22
+#: src/views/environments/group/columns.ts:36
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/site/site_edit/RightSettings.vue:100
 #: src/views/site/site_list/columns.tsx:69
@@ -3705,7 +3720,7 @@ msgstr ""
 #, fuzzy
 msgid ""
 "When you enable/disable, delete, or save this site, the nodes set in the "
-"environment group and the nodes selected below will be synchronized."
+"Node Group and the nodes selected below will be synchronized."
 msgstr ""
 "當您啟用/禁用、刪除或儲存此網站時,網站類別中設定的節點以及下方選擇的節點將會"
 "同步。"
@@ -3714,7 +3729,7 @@ msgstr ""
 #, fuzzy
 msgid ""
 "When you enable/disable, delete, or save this stream, the nodes set in the "
-"environment group and the nodes selected below will be synchronized."
+"Node Group and the nodes selected below will be synchronized."
 msgstr ""
 "當您啟用/禁用、刪除或儲存此網站時,網站類別中設定的節點以及下方選擇的節點將會"
 "同步。"

+ 1 - 1
app/src/routes/modules/environments.ts

@@ -30,7 +30,7 @@ export const environmentsRoutes: RouteRecordRaw[] = [
         name: 'env.groups',
         component: () => import('@/views/environments/group/EnvGroup.vue'),
         meta: {
-          name: () => $gettext('Groups'),
+          name: () => $gettext('Node Groups'),
         },
       },
     ],

+ 20 - 2
app/src/views/environments/group/EnvGroup.vue

@@ -1,5 +1,5 @@
 <script setup lang="ts">
-import env_group from '@/api/env_group'
+import env_group, { PostSyncAction } from '@/api/env_group'
 import NodeSelector from '@/components/NodeSelector/NodeSelector.vue'
 import { StdCurd } from '@/components/StdDesign/StdDataDisplay'
 import columns from '@/views/environments/group/columns'
@@ -7,7 +7,7 @@ import columns from '@/views/environments/group/columns'
 
 <template>
   <StdCurd
-    :title="$gettext('Environment Groups')"
+    :title="$gettext('Node Groups')"
     :api="env_group"
     :columns="columns"
     :scroll-x="600"
@@ -21,6 +21,24 @@ import columns from '@/views/environments/group/columns'
         v-model:target="data.sync_node_ids"
         hidden-local
       />
+
+      <AForm class="mt-4" layout="vertical">
+        <AFormItem :label="$gettext('Post-sync Action')">
+          <ASelect
+            v-model:value="data.post_sync_action"
+            :placeholder="$gettext('Select an action after sync')"
+            :default-value="PostSyncAction.ReloadNginx"
+            class="w-full"
+          >
+            <ASelectOption :value="PostSyncAction.None">
+              {{ $gettext('No Action') }}
+            </ASelectOption>
+            <ASelectOption :value="PostSyncAction.ReloadNginx">
+              {{ $gettext('Reload Nginx') }}
+            </ASelectOption>
+          </ASelect>
+        </AFormItem>
+      </AForm>
     </template>
   </StdCurd>
 </template>

+ 15 - 0
app/src/views/environments/group/columns.ts

@@ -1,4 +1,5 @@
 import type { Column } from '@/components/StdDesign/types'
+import { PostSyncAction } from '@/api/env_group'
 import { datetime } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
 import { input } from '@/components/StdDesign/StdDataEntry'
 
@@ -12,6 +13,20 @@ const columns: Column[] = [{
   handle: true,
   pithy: true,
   width: 120,
+}, {
+  title: () => $gettext('Post-sync Action'),
+  dataIndex: 'post_sync_action',
+  customRender: ({ text }) => {
+    if (!text || text === PostSyncAction.None) {
+      return $gettext('No Action')
+    }
+    else if (text === PostSyncAction.ReloadNginx) {
+      return $gettext('Reload Nginx')
+    }
+    return text
+  },
+  pithy: true,
+  width: 150,
 }, {
   title: () => $gettext('Created at'),
   dataIndex: 'created_at',

+ 2 - 2
app/src/views/site/site_edit/RightSettings.vue

@@ -88,7 +88,7 @@ function onChangeEnabled(checked: CheckedType) {
           <AFormItem :label="$gettext('Name')">
             <ConfigName v-if="name" :name />
           </AFormItem>
-          <AFormItem :label="$gettext('Environment Group')">
+          <AFormItem :label="$gettext('Node Group')">
             <StdSelector
               v-model:selected-key="data.env_group_id"
               :api="envGroup"
@@ -114,7 +114,7 @@ function onChangeEnabled(checked: CheckedType) {
             <template #content>
               <div class="max-w-200px mb-2">
                 {{ $gettext('When you enable/disable, delete, or save this site, '
-                  + 'the nodes set in the environment group and the nodes selected below will be synchronized.') }}
+                  + 'the nodes set in the Node Group and the nodes selected below will be synchronized.') }}
               </div>
               <div class="max-w-200px">
                 {{ $gettext('Note, if the configuration file include other configurations or certificates, '

+ 1 - 0
app/src/views/site/site_edit/SiteEdit.vue

@@ -143,6 +143,7 @@ async function save() {
     overwrite: true,
     env_group_id: data.value.env_group_id,
     sync_node_ids: data.value.sync_node_ids,
+    post_action: 'reload_nginx',
   }).then(r => {
     handleResponse(r)
     router.push({

+ 1 - 1
app/src/views/site/site_list/columns.tsx

@@ -22,7 +22,7 @@ const columns: Column[] = [{
   search: true,
   width: 120,
 }, {
-  title: () => $gettext('Environment Group'),
+  title: () => $gettext('Node Group'),
   dataIndex: 'env_group_id',
   customRender: actualValueRender('env_group.name'),
   edit: {

+ 1 - 0
app/src/views/stream/StreamEdit.vue

@@ -131,6 +131,7 @@ async function save() {
     overwrite: true,
     env_group_id: data.value?.env_group_id,
     sync_node_ids: data.value?.sync_node_ids,
+    post_action: 'reload_nginx',
   }).then(r => {
     handleResponse(r)
     router.push({

+ 1 - 1
app/src/views/stream/StreamList.vue

@@ -25,7 +25,7 @@ const columns: Column[] = [{
   },
   search: true,
 }, {
-  title: () => $gettext('Environment Group'),
+  title: () => $gettext('Node Group'),
   dataIndex: 'env_group_id',
   customRender: actualValueRender('env_group.name'),
   edit: {

+ 2 - 2
app/src/views/stream/components/RightSettings.vue

@@ -87,7 +87,7 @@ function onChangeEnabled(checked: CheckedType) {
         <AFormItem :label="$gettext('Name')">
           <ConfigName :name="name" />
         </AFormItem>
-        <AFormItem :label="$gettext('Environment Group')">
+        <AFormItem :label="$gettext('Node Group')">
           <StdSelector
             v-model:selected-key="data.env_group_id"
             :api="envGroup"
@@ -112,7 +112,7 @@ function onChangeEnabled(checked: CheckedType) {
             <template #content>
               <div class="max-w-200px mb-2">
                 {{ $gettext('When you enable/disable, delete, or save this stream, '
-                  + 'the nodes set in the environment group and the nodes selected below will be synchronized.') }}
+                  + 'the nodes set in the Node Group and the nodes selected below will be synchronized.') }}
               </div>
               <div class="max-w-200px">
                 {{ $gettext('Note, if the configuration file include other configurations or certificates, '

+ 21 - 10
internal/site/save.go

@@ -17,7 +17,7 @@ import (
 )
 
 // Save saves a site configuration file
-func Save(name string, content string, overwrite bool, envGroupId uint64, syncNodeIds []uint64) (err error) {
+func Save(name string, content string, overwrite bool, envGroupId uint64, syncNodeIds []uint64, postAction string) (err error) {
 	path := nginx.GetConfPath("sites-available", name)
 	if !overwrite && helper.FileExists(path) {
 		return ErrDstFileExists
@@ -37,10 +37,11 @@ func Save(name string, content string, overwrite bool, envGroupId uint64, syncNo
 			return fmt.Errorf("%s", output)
 		}
 
-		output = nginx.Reload()
-
-		if nginx.GetLogLevel(output) > nginx.Warn {
-			return fmt.Errorf("%s", output)
+		if postAction == model.PostSyncActionReloadNginx {
+			output = nginx.Reload()
+			if nginx.GetLogLevel(output) > nginx.Warn {
+				return fmt.Errorf("%s", output)
+			}
 		}
 	}
 
@@ -61,13 +62,17 @@ func Save(name string, content string, overwrite bool, envGroupId uint64, syncNo
 }
 
 func syncSave(name string, content string) {
-	nodes := getSyncNodes(name)
+	nodes, postSyncAction := getSyncData(name)
 
 	wg := &sync.WaitGroup{}
 	wg.Add(len(nodes))
 
+	// Map to track successful nodes for potential post-sync action
+	successfulNodes := make([]*model.Environment, 0)
+	var nodesMutex sync.Mutex
+
 	for _, node := range nodes {
-		go func() {
+		go func(node *model.Environment) {
 			defer func() {
 				if err := recover(); err != nil {
 					buf := make([]byte, 1024)
@@ -82,8 +87,9 @@ func syncSave(name string, content string) {
 			resp, err := client.R().
 				SetHeader("X-Node-Secret", node.Token).
 				SetBody(map[string]interface{}{
-					"content":   content,
-					"overwrite": true,
+					"content":     content,
+					"overwrite":   true,
+					"post_action": postSyncAction,
 				}).
 				Post(fmt.Sprintf("/api/sites/%s", name))
 			if err != nil {
@@ -96,12 +102,17 @@ func syncSave(name string, content string) {
 			}
 			notification.Success("Save Remote Site Success", "Save site %{name} to %{node} successfully", NewSyncResult(node.Name, name, resp))
 
+			// Track successful sync for post-sync action
+			nodesMutex.Lock()
+			successfulNodes = append(successfulNodes, node)
+			nodesMutex.Unlock()
+
 			// Check if the site is enabled, if so then enable it on the remote node
 			enabledConfigFilePath := nginx.GetConfPath("sites-enabled", name)
 			if helper.FileExists(enabledConfigFilePath) {
 				syncEnable(name)
 			}
-		}()
+		}(node)
 	}
 
 	wg.Wait()

+ 10 - 2
internal/site/sync.go

@@ -2,6 +2,7 @@ package site
 
 import (
 	"encoding/json"
+
 	"github.com/0xJacky/Nginx-UI/internal/nginx"
 	"github.com/0xJacky/Nginx-UI/model"
 	"github.com/0xJacky/Nginx-UI/query"
@@ -11,8 +12,8 @@ import (
 	"github.com/uozi-tech/cosy/logger"
 )
 
-// getSyncNodes returns the nodes that need to be synchronized by site name
-func getSyncNodes(name string) (nodes []*model.Environment) {
+// getSyncData returns the nodes that need to be synchronized by site name and the post-sync action
+func getSyncData(name string) (nodes []*model.Environment, postSyncAction string) {
 	configFilePath := nginx.GetConfPath("sites-available", name)
 	s := query.Site
 	site, err := s.Where(s.Path.Eq(configFilePath)).
@@ -26,6 +27,7 @@ func getSyncNodes(name string) (nodes []*model.Environment) {
 	// inherit sync node ids from site category
 	if site.EnvGroup != nil {
 		syncNodeIds = append(syncNodeIds, site.EnvGroup.SyncNodeIds...)
+		postSyncAction = site.EnvGroup.PostSyncAction
 	}
 	syncNodeIds = lo.Uniq(syncNodeIds)
 
@@ -38,6 +40,12 @@ func getSyncNodes(name string) (nodes []*model.Environment) {
 	return
 }
 
+// getSyncNodes returns the nodes that need to be synchronized by site name (for backward compatibility)
+func getSyncNodes(name string) (nodes []*model.Environment) {
+	nodes, _ = getSyncData(name)
+	return
+}
+
 type SyncResult struct {
 	StatusCode int    `json:"status_code"`
 	Node       string `json:"node"`

+ 21 - 10
internal/stream/save.go

@@ -17,7 +17,7 @@ import (
 )
 
 // Save saves a site configuration file
-func Save(name string, content string, overwrite bool, syncNodeIds []uint64) (err error) {
+func Save(name string, content string, overwrite bool, syncNodeIds []uint64, postAction string) (err error) {
 	path := nginx.GetConfPath("streams-available", name)
 	if !overwrite && helper.FileExists(path) {
 		return ErrDstFileExists
@@ -37,10 +37,11 @@ func Save(name string, content string, overwrite bool, syncNodeIds []uint64) (er
 			return fmt.Errorf("%s", output)
 		}
 
-		output = nginx.Reload()
-
-		if nginx.GetLogLevel(output) > nginx.Warn {
-			return fmt.Errorf("%s", output)
+		if postAction == model.PostSyncActionReloadNginx {
+			output = nginx.Reload()
+			if nginx.GetLogLevel(output) > nginx.Warn {
+				return fmt.Errorf("%s", output)
+			}
 		}
 	}
 
@@ -60,13 +61,17 @@ func Save(name string, content string, overwrite bool, syncNodeIds []uint64) (er
 }
 
 func syncSave(name string, content string) {
-	nodes := getSyncNodes(name)
+	nodes, postSyncAction := getSyncData(name)
 
 	wg := &sync.WaitGroup{}
 	wg.Add(len(nodes))
 
+	// Map to track successful nodes for potential post-sync action
+	successfulNodes := make([]*model.Environment, 0)
+	var nodesMutex sync.Mutex
+
 	for _, node := range nodes {
-		go func() {
+		go func(node *model.Environment) {
 			defer func() {
 				if err := recover(); err != nil {
 					buf := make([]byte, 1024)
@@ -81,8 +86,9 @@ func syncSave(name string, content string) {
 			resp, err := client.R().
 				SetHeader("X-Node-Secret", node.Token).
 				SetBody(map[string]interface{}{
-					"content":   content,
-					"overwrite": true,
+					"content":     content,
+					"overwrite":   true,
+					"post_action": postSyncAction,
 				}).
 				Post(fmt.Sprintf("/api/streams/%s", name))
 			if err != nil {
@@ -95,12 +101,17 @@ func syncSave(name string, content string) {
 			}
 			notification.Success("Save Remote Stream Success", "Save stream %{name} to %{node} successfully", NewSyncResult(node.Name, name, resp))
 
+			// Track successful sync for post-sync action
+			nodesMutex.Lock()
+			successfulNodes = append(successfulNodes, node)
+			nodesMutex.Unlock()
+
 			// Check if the site is enabled, if so then enable it on the remote node
 			enabledConfigFilePath := nginx.GetConfPath("streams-enabled", name)
 			if helper.FileExists(enabledConfigFilePath) {
 				syncEnable(name)
 			}
-		}()
+		}(node)
 	}
 
 	wg.Wait()

+ 10 - 3
internal/stream/sync.go

@@ -11,8 +11,8 @@ import (
 	"github.com/uozi-tech/cosy/logger"
 )
 
-// getSyncNodes returns the nodes that need to be synchronized by site name
-func getSyncNodes(name string) (nodes []*model.Environment) {
+// getSyncData returns the nodes that need to be synchronized by stream name and the post-sync action
+func getSyncData(name string) (nodes []*model.Environment, postSyncAction string) {
 	configFilePath := nginx.GetConfPath("streams-available", name)
 	s := query.Stream
 	stream, err := s.Where(s.Path.Eq(configFilePath)).
@@ -23,9 +23,10 @@ func getSyncNodes(name string) (nodes []*model.Environment) {
 	}
 
 	syncNodeIds := stream.SyncNodeIDs
-	// inherit sync node ids from site category
+	// inherit sync node ids from stream category
 	if stream.EnvGroup != nil {
 		syncNodeIds = append(syncNodeIds, stream.EnvGroup.SyncNodeIds...)
+		postSyncAction = stream.EnvGroup.PostSyncAction
 	}
 
 	e := query.Environment
@@ -37,6 +38,12 @@ func getSyncNodes(name string) (nodes []*model.Environment) {
 	return
 }
 
+// getSyncNodes returns the nodes that need to be synchronized by stream name (for backward compatibility)
+func getSyncNodes(name string) (nodes []*model.Environment) {
+	nodes, _ = getSyncData(name)
+	return
+}
+
 type SyncResult struct {
 	StatusCode int    `json:"status_code"`
 	Node       string `json:"node"`

+ 12 - 3
model/env_group.go

@@ -1,9 +1,18 @@
 package model
 
+// PostSyncActionType defines the type of action after synchronization
+const (
+	// PostSyncActionNone indicates no operation after sync
+	PostSyncActionNone = "none"
+	// PostSyncActionReloadNginx indicates reload Nginx after sync
+	PostSyncActionReloadNginx = "reload_nginx"
+)
+
 // EnvGroup represents a group of environments that can be synced across nodes
 type EnvGroup struct {
 	Model
-	Name        string   `json:"name"`
-	SyncNodeIds []uint64 `json:"sync_node_ids" gorm:"serializer:json"`
-	OrderID     int      `json:"-" gorm:"default:0"`
+	Name           string   `json:"name"`
+	SyncNodeIds    []uint64 `json:"sync_node_ids" gorm:"serializer:json"`
+	OrderID        int      `json:"-" gorm:"default:0"`
+	PostSyncAction string   `json:"post_sync_action" gorm:"default:'reload_nginx'"`
 }