Преглед изворни кода

refactor: auto-cert handling logic #1095, #1104

Jacky пре 1 месец
родитељ
комит
55d54766f8
46 измењених фајлова са 1594 додато и 975 уклоњено
  1. 5 1
      .cursor/mcp.json
  2. 5 14
      api/certificate/issue.go
  3. 2 2
      api/cluster/nginx.go
  4. 2 2
      api/nginx_log/websocket.go
  5. 84 42
      app/src/language/ar/app.po
  6. 84 42
      app/src/language/de_DE/app.po
  7. 79 36
      app/src/language/en/app.po
  8. 84 42
      app/src/language/es/app.po
  9. 84 42
      app/src/language/fr_FR/app.po
  10. 82 39
      app/src/language/ja_JP/app.po
  11. 82 42
      app/src/language/ko_KR/app.po
  12. 77 36
      app/src/language/messages.pot
  13. 84 42
      app/src/language/pt_PT/app.po
  14. 84 42
      app/src/language/ru_RU/app.po
  15. 84 43
      app/src/language/tr_TR/app.po
  16. 84 39
      app/src/language/uk_UA/app.po
  17. 84 42
      app/src/language/vi_VN/app.po
  18. 82 45
      app/src/language/zh_CN/app.po
  19. 82 42
      app/src/language/zh_TW/app.po
  20. 8 13
      app/src/views/certificate/CertificateEditor.vue
  21. 3 3
      app/src/views/certificate/CertificateList/Certificate.vue
  22. 201 0
      app/src/views/certificate/components/DNSIssueCertificate.vue
  23. 4 2
      app/src/views/certificate/components/RenewCert.vue
  24. 0 107
      app/src/views/certificate/components/WildcardCertificate.vue
  25. 21 0
      app/src/views/certificate/store.ts
  26. 1 0
      app/src/views/site/site_edit/components/Cert/ObtainCertLive.vue
  27. 3 11
      internal/cert/auto_cert.go
  28. 16 0
      internal/cert/errors.go
  29. 28 31
      internal/cert/issue.go
  30. 6 9
      internal/cert/logger.go
  31. 10 5
      internal/cert/obtain.go
  32. 8 9
      internal/cert/payload.go
  33. 10 7
      internal/cert/renew.go
  34. 9 6
      internal/cert/revoke.go
  35. 0 125
      internal/cert/tencent_cloud_dns_test.go
  36. 1 1
      internal/site/delete.go
  37. 1 1
      internal/site/disable.go
  38. 1 1
      internal/site/enable.go
  39. 2 2
      internal/site/maintenance.go
  40. 1 1
      internal/site/rename.go
  41. 1 1
      internal/site/save.go
  42. 1 1
      internal/stream/delete.go
  43. 1 1
      internal/stream/disable.go
  44. 1 1
      internal/stream/enable.go
  45. 1 1
      internal/stream/rename.go
  46. 1 1
      internal/stream/save.go

+ 5 - 1
.cursor/mcp.json

@@ -4,6 +4,10 @@
 			"command": "npx",
 			"command": "npx",
 			"args": ["@eslint/mcp@latest"],
 			"args": ["@eslint/mcp@latest"],
 			"env": {}
 			"env": {}
-		}
+		},
+		"context7": {
+      "command": "npx",
+      "args": ["-y", "@upstash/context7-mcp"]
+    }
 	}
 	}
 }
 }

+ 5 - 14
api/certificate/issue.go

@@ -26,7 +26,7 @@ type IssueCertResponse struct {
 	Message           string             `json:"message"`
 	Message           string             `json:"message"`
 	SSLCertificate    string             `json:"ssl_certificate,omitempty"`
 	SSLCertificate    string             `json:"ssl_certificate,omitempty"`
 	SSLCertificateKey string             `json:"ssl_certificate_key,omitempty"`
 	SSLCertificateKey string             `json:"ssl_certificate_key,omitempty"`
-	KeyType           certcrypto.KeyType `json:"key_type"`
+	KeyType           certcrypto.KeyType `json:"key_type,omitempty"`
 }
 }
 
 
 func IssueCert(c *gin.Context) {
 func IssueCert(c *gin.Context) {
@@ -71,28 +71,19 @@ func IssueCert(c *gin.Context) {
 		}
 		}
 	}
 	}
 
 
-	errChan := make(chan error, 1)
-
 	log := cert.NewLogger()
 	log := cert.NewLogger()
 	log.SetCertModel(&certModel)
 	log.SetCertModel(&certModel)
 	log.SetWebSocket(ws)
 	log.SetWebSocket(ws)
 	defer log.Close()
 	defer log.Close()
 
 
-	go cert.IssueCert(payload, log, errChan)
-
-	// block, until errChan closes
-	if err := <-errChan; err != nil {
+	err = cert.IssueCert(payload, log)
+	if err != nil {
 		log.Error(err)
 		log.Error(err)
-		err = ws.WriteJSON(IssueCertResponse{
+		_ = ws.WriteJSON(IssueCertResponse{
 			Status:  Error,
 			Status:  Error,
 			Message: err.Error(),
 			Message: err.Error(),
 		})
 		})
-		if err != nil {
-			if helper.IsUnexpectedWebsocketError(err) {
-				logger.Error(err)
-			}
-			return
-		}
+		return
 	}
 	}
 
 
 	cert := query.Cert
 	cert := query.Cert

+ 2 - 2
api/cluster/nginx.go

@@ -39,7 +39,7 @@ func syncReload(nodeIDs []uint64) {
 				if err := recover(); err != nil {
 				if err := recover(); err != nil {
 					buf := make([]byte, 1024)
 					buf := make([]byte, 1024)
 					runtime.Stack(buf, false)
 					runtime.Stack(buf, false)
-					logger.Error(err)
+					logger.Errorf("%s\n%s", err, buf)
 				}
 				}
 			}()
 			}()
 			defer wg.Done()
 			defer wg.Done()
@@ -93,7 +93,7 @@ func syncRestart(nodeIDs []uint64) {
 				if err := recover(); err != nil {
 				if err := recover(); err != nil {
 					buf := make([]byte, 1024)
 					buf := make([]byte, 1024)
 					runtime.Stack(buf, false)
 					runtime.Stack(buf, false)
-					logger.Error(err)
+					logger.Errorf("%s\n%s", err, buf)
 				}
 				}
 			}()
 			}()
 			defer wg.Done()
 			defer wg.Done()

+ 2 - 2
api/nginx_log/websocket.go

@@ -67,7 +67,7 @@ func tailNginxLog(ws *websocket.Conn, controlChan chan controlStruct, errChan ch
 		if err := recover(); err != nil {
 		if err := recover(); err != nil {
 			buf := make([]byte, 1024)
 			buf := make([]byte, 1024)
 			runtime.Stack(buf, false)
 			runtime.Stack(buf, false)
-			logger.Error(err)
+			logger.Errorf("%s\n%s", err, buf)
 			return
 			return
 		}
 		}
 	}()
 	}()
@@ -139,7 +139,7 @@ func handleLogControl(ws *websocket.Conn, controlChan chan controlStruct, errCha
 		if err := recover(); err != nil {
 		if err := recover(); err != nil {
 			buf := make([]byte, 1024)
 			buf := make([]byte, 1024)
 			runtime.Stack(buf, false)
 			runtime.Stack(buf, false)
-			logger.Error(err)
+			logger.Errorf("%s\n%s", err, buf)
 			return
 			return
 		}
 		}
 	}()
 	}()

+ 84 - 42
app/src/language/ar/app.po

@@ -180,6 +180,10 @@ msgstr "إضافة تكوين"
 msgid "Add Directive Below"
 msgid "Add Directive Below"
 msgstr "أضف التوجيه أدناه"
 msgstr "أضف التوجيه أدناه"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:151
+msgid "Add Domain"
+msgstr "إضافة نطاق"
+
 #: src/components/NgxConfigEditor/LocationEditor.vue:131
 #: src/components/NgxConfigEditor/LocationEditor.vue:131
 #: src/components/NgxConfigEditor/LocationEditor.vue:158
 #: src/components/NgxConfigEditor/LocationEditor.vue:158
 msgid "Add Location"
 msgid "Add Location"
@@ -227,6 +231,14 @@ msgstr "الكل"
 msgid "All Recovery Codes Have Been Used"
 msgid "All Recovery Codes Have Been Used"
 msgstr "تم استخدام جميع رموز الاسترداد"
 msgstr "تم استخدام جميع رموز الاسترداد"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:156
+msgid ""
+"All selected subdomains must belong to the same DNS Provider, otherwise the "
+"certificate application will fail."
+msgstr ""
+"يجب أن تنتمي جميع النطاقات الفرعية المحددة إلى نفس موفر DNS، وإلا فشل طلب "
+"الشهادة."
+
 #: src/views/preference/tabs/OpenAISettings.vue:32
 #: src/views/preference/tabs/OpenAISettings.vue:32
 msgid "API Base Url"
 msgid "API Base Url"
 msgstr "عنوان URL الأساسي لAPI"
 msgstr "عنوان URL الأساسي لAPI"
@@ -253,7 +265,7 @@ msgstr "التطبيق"
 
 
 #: src/views/system/Upgrade.vue:195
 #: src/views/system/Upgrade.vue:195
 msgid "Arch"
 msgid "Arch"
-msgstr "\"أرك\""
+msgstr "أرك"
 
 
 #: src/views/preference/tabs/AuthSettings.vue:130
 #: src/views/preference/tabs/AuthSettings.vue:130
 msgid "Are you sure to delete this banned IP immediately?"
 msgid "Are you sure to delete this banned IP immediately?"
@@ -388,7 +400,7 @@ msgstr "تم تعطيل التجديد التلقائي لـ‎%{name}"
 msgid "Auto-renewal enabled for %{name}"
 msgid "Auto-renewal enabled for %{name}"
 msgstr "تم تمكين التجديد التلقائي لـ‏%{name}"
 msgstr "تم تمكين التجديد التلقائي لـ‏%{name}"
 
 
-#: src/views/certificate/components/RenewCert.vue:49
+#: src/views/certificate/components/RenewCert.vue:51
 #: src/views/site/site_edit/components/Cert/IssueCert.vue:84
 #: src/views/site/site_edit/components/Cert/IssueCert.vue:84
 msgid "AutoCert is running, please wait..."
 msgid "AutoCert is running, please wait..."
 msgstr "AutoCert قيد التشغيل، يرجى الانتظار..."
 msgstr "AutoCert قيد التشغيل، يرجى الانتظار..."
@@ -401,7 +413,7 @@ msgstr "\"AutoCert قيد التشغيل...\""
 msgid "Automatic Restart"
 msgid "Automatic Restart"
 msgstr "\"إعادة التشغيل التلقائي\""
 msgstr "\"إعادة التشغيل التلقائي\""
 
 
-#: src/views/certificate/CertificateEditor.vue:259
+#: src/views/certificate/CertificateEditor.vue:257
 #: src/views/config/components/ConfigLeftPanel.vue:273
 #: src/views/config/components/ConfigLeftPanel.vue:273
 #: src/views/config/ConfigList.vue:112 src/views/config/ConfigList.vue:195
 #: src/views/config/ConfigList.vue:112 src/views/config/ConfigList.vue:195
 #: src/views/nginx_log/NginxLog.vue:174
 #: src/views/nginx_log/NginxLog.vue:174
@@ -696,7 +708,7 @@ msgstr "تم تجديد الشهادة بنجاح"
 msgid "Certificate revoked successfully"
 msgid "Certificate revoked successfully"
 msgstr "تم إلغاء الشهادة بنجاح"
 msgstr "تم إلغاء الشهادة بنجاح"
 
 
-#: src/views/certificate/CertificateEditor.vue:128
+#: src/views/certificate/CertificateEditor.vue:126
 #: src/views/site/site_edit/components/Cert/Cert.vue:58
 #: src/views/site/site_edit/components/Cert/Cert.vue:58
 msgid "Certificate Status"
 msgid "Certificate Status"
 msgid_plural "Certificates Status"
 msgid_plural "Certificates Status"
@@ -707,6 +719,10 @@ msgstr[3] "حالة الشهادات"
 msgstr[4] "حالة الشهادات"
 msgstr[4] "حالة الشهادات"
 msgstr[5] "حالة الشهادة"
 msgstr[5] "حالة الشهادة"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:104
+msgid "Certificate Type"
+msgstr "نوع الشهادة"
+
 #: src/routes/modules/certificates.ts:11
 #: src/routes/modules/certificates.ts:11
 #: src/views/certificate/CertificateList/Certificate.vue:19
 #: src/views/certificate/CertificateList/Certificate.vue:19
 msgid "Certificates"
 msgid "Certificates"
@@ -1193,6 +1209,14 @@ msgstr "تعبير كرون مخصص"
 msgid "Custom Directory"
 msgid "Custom Directory"
 msgstr "دليل مخصص"
 msgstr "دليل مخصص"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:126
+msgid "Custom Domains"
+msgstr "نطاقات مخصصة"
+
+#: src/views/certificate/components/DNSIssueCertificate.vue:110
+msgid "Custom Domains Certificate"
+msgstr "شهادة النطاقات المخصصة"
+
 #: src/views/preference/tabs/NodeSettings.vue:19
 #: src/views/preference/tabs/NodeSettings.vue:19
 msgid ""
 msgid ""
 "Customize the name of local node to be displayed in the environment "
 "Customize the name of local node to be displayed in the environment "
@@ -1500,11 +1524,11 @@ msgid "Document"
 msgid_plural "Documents"
 msgid_plural "Documents"
 msgstr[0] "وثيقة"
 msgstr[0] "وثيقة"
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:66
+#: src/views/certificate/components/DNSIssueCertificate.vue:116
 msgid "Domain"
 msgid "Domain"
 msgstr "نطاق"
 msgstr "نطاق"
 
 
-#: src/views/certificate/CertificateEditor.vue:112
+#: src/views/certificate/CertificateEditor.vue:110
 msgid "Domains list is empty, try to reopen Auto Cert for %{config}"
 msgid "Domains list is empty, try to reopen Auto Cert for %{config}"
 msgstr "قائمة النطاقات فارغة، حاول إعادة فتح Auto Cert لـ %{config}"
 msgstr "قائمة النطاقات فارغة، حاول إعادة فتح Auto Cert لـ %{config}"
 
 
@@ -1706,6 +1730,14 @@ msgstr "تشفير الموقع باستخدام Let's Encrypt"
 msgid "End"
 msgid "End"
 msgstr "النهاية"
 msgstr "النهاية"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:135
+msgid "Enter domain name"
+msgstr "أدخل اسم النطاق"
+
+#: src/views/certificate/components/DNSIssueCertificate.vue:120
+msgid "Enter your domain"
+msgstr "أدخل نطاقك"
+
 #: src/language/constants.ts:22
 #: src/language/constants.ts:22
 msgid "Environment variables cleaned"
 msgid "Environment variables cleaned"
 msgstr "تم تنظيف متغيرات البيئة"
 msgstr "تم تنظيف متغيرات البيئة"
@@ -1780,7 +1812,7 @@ msgstr "حاوية Docker خارجية"
 msgid "External Notify"
 msgid "External Notify"
 msgstr "إشعار خارجي"
 msgstr "إشعار خارجي"
 
 
-#: src/views/site/site_edit/components/Cert/ObtainCertLive.vue:80
+#: src/views/site/site_edit/components/Cert/ObtainCertLive.vue:81
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
 msgstr "فشل في الحصول على الشهادة"
 msgstr "فشل في الحصول على الشهادة"
 
 
@@ -2305,7 +2337,7 @@ msgid "Import"
 msgstr "استيراد"
 msgstr "استيراد"
 
 
 #: src/routes/modules/certificates.ts:46
 #: src/routes/modules/certificates.ts:46
-#: src/views/certificate/CertificateEditor.vue:85
+#: src/views/certificate/CertificateEditor.vue:83
 msgid "Import Certificate"
 msgid "Import Certificate"
 msgstr "استيراد شهادة"
 msgstr "استيراد شهادة"
 
 
@@ -2450,12 +2482,12 @@ msgid "IP"
 msgstr "IP"
 msgstr "IP"
 
 
 #: src/views/certificate/CertificateList/Certificate.vue:37
 #: src/views/certificate/CertificateList/Certificate.vue:37
-msgid "Issue wildcard certificate"
-msgstr "إصدار شهادة wildcard"
+msgid "Issue certificate"
+msgstr "إصدار شهادة"
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:57
-msgid "Issue Wildcard Certificate"
-msgstr "إصدار شهادة Wildcard"
+#: src/views/certificate/components/DNSIssueCertificate.vue:95
+msgid "Issue Certificate"
+msgstr "إصدار الشهادة"
 
 
 #: src/language/constants.ts:20
 #: src/language/constants.ts:20
 msgid "Issued certificate successfully"
 msgid "Issued certificate successfully"
@@ -2538,8 +2570,8 @@ msgstr "اتركه فارغًا إذا كنت لا تريد التعديل"
 msgid "Leave blank if you don't need this."
 msgid "Leave blank if you don't need this."
 msgstr "اتركه فارغًا إذا لم تكن بحاجة إلى ذلك."
 msgstr "اتركه فارغًا إذا لم تكن بحاجة إلى ذلك."
 
 
-#: src/views/certificate/CertificateEditor.vue:223
-#: src/views/certificate/CertificateEditor.vue:237
+#: src/views/certificate/CertificateEditor.vue:221
+#: src/views/certificate/CertificateEditor.vue:235
 msgid "Leave blank will not change anything"
 msgid "Leave blank will not change anything"
 msgstr "تركه فارغًا لن يغير شيئًا"
 msgstr "تركه فارغًا لن يغير شيئًا"
 
 
@@ -2626,7 +2658,7 @@ msgstr "مكان"
 msgid "Locations"
 msgid "Locations"
 msgstr "أماكن"
 msgstr "أماكن"
 
 
-#: src/views/certificate/CertificateEditor.vue:247
+#: src/views/certificate/CertificateEditor.vue:245
 msgid "Log"
 msgid "Log"
 msgstr "سجل"
 msgstr "سجل"
 
 
@@ -2839,7 +2871,7 @@ msgid "Modify"
 msgstr "تعديل"
 msgstr "تعديل"
 
 
 #: src/routes/modules/certificates.ts:36
 #: src/routes/modules/certificates.ts:36
-#: src/views/certificate/CertificateEditor.vue:85
+#: src/views/certificate/CertificateEditor.vue:83
 msgid "Modify Certificate"
 msgid "Modify Certificate"
 msgstr "تعديل الشهادة"
 msgstr "تعديل الشهادة"
 
 
@@ -2874,7 +2906,7 @@ msgstr "توجيه متعدد الأسطر"
 #: src/components/NgxConfigEditor/NgxUpstream.vue:199
 #: src/components/NgxConfigEditor/NgxUpstream.vue:199
 #: src/views/backup/AutoBackup/AutoBackup.vue:11
 #: src/views/backup/AutoBackup/AutoBackup.vue:11
 #: src/views/certificate/ACMEUser.vue:11
 #: src/views/certificate/ACMEUser.vue:11
-#: src/views/certificate/CertificateEditor.vue:162
+#: src/views/certificate/CertificateEditor.vue:160
 #: src/views/certificate/CertificateList/certColumns.tsx:9
 #: src/views/certificate/CertificateList/certColumns.tsx:9
 #: src/views/certificate/DNSCredential.vue:9
 #: src/views/certificate/DNSCredential.vue:9
 #: src/views/config/components/ConfigRightPanel/Basic.vue:34
 #: src/views/config/components/ConfigRightPanel/Basic.vue:34
@@ -2934,7 +2966,7 @@ msgstr "مسار جديد"
 msgid "New version released"
 msgid "New version released"
 msgstr "تم إصدار نسخة جديدة"
 msgstr "تم إصدار نسخة جديدة"
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:89
+#: src/views/certificate/components/DNSIssueCertificate.vue:181
 #: src/views/install/components/InstallView.vue:96
 #: src/views/install/components/InstallView.vue:96
 #: src/views/site/site_add/SiteAdd.vue:132
 #: src/views/site/site_add/SiteAdd.vue:132
 #: src/views/site/site_edit/components/Cert/ObtainCert.vue:214
 #: src/views/site/site_edit/components/Cert/ObtainCert.vue:214
@@ -3516,6 +3548,10 @@ msgstr "يرجى إدخال اسم لمفتاح المرور الذي ترغب 
 msgid "Please enter a valid port range"
 msgid "Please enter a valid port range"
 msgstr "الرجاء إدخال نطاق منافذ صالح"
 msgstr "الرجاء إدخال نطاق منافذ صالح"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:74
+msgid "Please enter at least one domain"
+msgstr "الرجاء إدخال مجال واحد على الأقل"
+
 #: src/components/TwoFA/Authorization.vue:85
 #: src/components/TwoFA/Authorization.vue:85
 msgid "Please enter the OTP code:"
 msgid "Please enter the OTP code:"
 msgstr "يرجى إدخال رمز OTP:"
 msgstr "يرجى إدخال رمز OTP:"
@@ -3845,6 +3881,7 @@ msgstr "إعادة التحميل"
 msgid "Reloading nginx"
 msgid "Reloading nginx"
 msgstr "إعادة تحميل nginx"
 msgstr "إعادة تحميل nginx"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:144
 #: src/views/preference/tabs/AuthSettings.vue:137
 #: src/views/preference/tabs/AuthSettings.vue:137
 msgid "Remove"
 msgid "Remove"
 msgstr "إزالة"
 msgstr "إزالة"
@@ -3927,8 +3964,8 @@ msgstr "إعادة التسمية بنجاح"
 msgid "Renamed successfully"
 msgid "Renamed successfully"
 msgstr "تمت إعادة التسمية بنجاح"
 msgstr "تمت إعادة التسمية بنجاح"
 
 
-#: src/views/certificate/components/RenewCert.vue:46
-#: src/views/certificate/components/RenewCert.vue:53
+#: src/views/certificate/components/RenewCert.vue:48
+#: src/views/certificate/components/RenewCert.vue:55
 msgid "Renew Certificate"
 msgid "Renew Certificate"
 msgstr "تجديد الشهادة"
 msgstr "تجديد الشهادة"
 
 
@@ -3940,8 +3977,8 @@ msgstr "خطأ في تجديد الشهادة"
 msgid "Renew Certificate Success"
 msgid "Renew Certificate Success"
 msgstr "تجديد الشهادة بنجاح"
 msgstr "تجديد الشهادة بنجاح"
 
 
-#: src/views/certificate/components/RenewCert.vue:28
-#: src/views/certificate/components/WildcardCertificate.vue:46
+#: src/views/certificate/components/DNSIssueCertificate.vue:84
+#: src/views/certificate/components/RenewCert.vue:30
 msgid "Renew successfully"
 msgid "Renew successfully"
 msgstr "تم التجديد بنجاح"
 msgstr "تم التجديد بنجاح"
 
 
@@ -4199,7 +4236,7 @@ msgstr "السبت"
 
 
 #: src/components/ChatGPT/ChatMessage.vue:215
 #: src/components/ChatGPT/ChatMessage.vue:215
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:129
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:129
-#: src/language/curd.ts:18 src/views/certificate/CertificateEditor.vue:266
+#: src/language/curd.ts:18 src/views/certificate/CertificateEditor.vue:264
 #: src/views/config/components/ConfigLeftPanel.vue:282
 #: src/views/config/components/ConfigLeftPanel.vue:282
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/preference/components/AuthSettings/Passkey.vue:130
 #: src/views/preference/components/AuthSettings/Passkey.vue:130
@@ -4254,7 +4291,7 @@ msgstr "فشل حفظ الدفق %{name} إلى %{node}"
 msgid "Save stream %{name} to %{node} successfully"
 msgid "Save stream %{name} to %{node} successfully"
 msgstr "تم حفظ الدفق %{name} في %{node} بنجاح"
 msgstr "تم حفظ الدفق %{name} في %{node} بنجاح"
 
 
-#: src/language/curd.ts:35 src/views/certificate/CertificateEditor.vue:49
+#: src/language/curd.ts:35 src/views/certificate/store.ts:13
 #: src/views/preference/store/index.ts:118
 #: src/views/preference/store/index.ts:118
 msgid "Save successfully"
 msgid "Save successfully"
 msgstr "تم الحفظ بنجاح"
 msgstr "تم الحفظ بنجاح"
@@ -4362,6 +4399,10 @@ msgstr "إرسال"
 msgid "Server"
 msgid "Server"
 msgstr "الخادم"
 msgstr "الخادم"
 
 
+#: src/views/certificate/CertificateEditor.vue:55
+msgid "Server error"
+msgstr "خطأ في الخادم"
+
 #: src/views/dashboard/ServerAnalytic.vue:175
 #: src/views/dashboard/ServerAnalytic.vue:175
 msgid "Server Info"
 msgid "Server Info"
 msgstr "معلومات الخادم"
 msgstr "معلومات الخادم"
@@ -4498,7 +4539,7 @@ msgstr "وقت الانتظار بين تكرارات محمل ذاكرة الت
 msgid "Sleep time between cache manager iterations"
 msgid "Sleep time between cache manager iterations"
 msgstr "وقت الانتظار بين تكرارات مدير الذاكرة المؤقتة"
 msgstr "وقت الانتظار بين تكرارات مدير الذاكرة المؤقتة"
 
 
-#: src/views/certificate/CertificateEditor.vue:213
+#: src/views/certificate/CertificateEditor.vue:211
 msgid "SSL Certificate Content"
 msgid "SSL Certificate Content"
 msgstr "محتوى شهادة SSL"
 msgstr "محتوى شهادة SSL"
 
 
@@ -4510,15 +4551,15 @@ msgstr "يجب أن يكون ملف شهادة SSL ضمن دليل تكوين Ng
 msgid "SSL certificate file not found"
 msgid "SSL certificate file not found"
 msgstr "لم يتم العثور على ملف شهادة SSL"
 msgstr "لم يتم العثور على ملف شهادة SSL"
 
 
-#: src/views/certificate/CertificateEditor.vue:227
+#: src/views/certificate/CertificateEditor.vue:225
 msgid "SSL Certificate Key Content"
 msgid "SSL Certificate Key Content"
 msgstr "محتوى مفتاح شهادة SSL"
 msgstr "محتوى مفتاح شهادة SSL"
 
 
-#: src/views/certificate/CertificateEditor.vue:192
+#: src/views/certificate/CertificateEditor.vue:190
 msgid "SSL Certificate Key Path"
 msgid "SSL Certificate Key Path"
 msgstr "مسار مفتاح شهادة SSL"
 msgstr "مسار مفتاح شهادة SSL"
 
 
-#: src/views/certificate/CertificateEditor.vue:177
+#: src/views/certificate/CertificateEditor.vue:175
 #: src/views/preference/tabs/ServerSettings.vue:37
 #: src/views/preference/tabs/ServerSettings.vue:37
 msgid "SSL Certificate Path"
 msgid "SSL Certificate Path"
 msgstr "مسار شهادة SSL"
 msgstr "مسار شهادة SSL"
@@ -4753,7 +4794,7 @@ msgstr "مزامنة العقد"
 msgid "Sync strategy"
 msgid "Sync strategy"
 msgstr "استراتيجية المزامنة"
 msgstr "استراتيجية المزامنة"
 
 
-#: src/views/certificate/CertificateEditor.vue:206
+#: src/views/certificate/CertificateEditor.vue:204
 msgid "Sync to"
 msgid "Sync to"
 msgstr "مزامنة إلى"
 msgstr "مزامنة إلى"
 
 
@@ -4828,11 +4869,11 @@ msgstr ""
 "يجب أن يحتوي رقم ICP فقط على أحرف، وunicode، وأرقام، وشرطات، وشرطات طويلة، "
 "يجب أن يحتوي رقم ICP فقط على أحرف، وunicode، وأرقام، وشرطات، وشرطات طويلة، "
 "ونقطتين، ونقاط."
 "ونقطتين، ونقاط."
 
 
-#: src/views/certificate/CertificateEditor.vue:216
+#: src/views/certificate/CertificateEditor.vue:214
 msgid "The input is not a SSL Certificate"
 msgid "The input is not a SSL Certificate"
 msgstr "الإدخال ليس شهادة SSL"
 msgstr "الإدخال ليس شهادة SSL"
 
 
-#: src/views/certificate/CertificateEditor.vue:230
+#: src/views/certificate/CertificateEditor.vue:228
 msgid "The input is not a SSL Certificate Key"
 msgid "The input is not a SSL Certificate Key"
 msgstr "المدخل ليس مفتاح شهادة SSL"
 msgstr "المدخل ليس مفتاح شهادة SSL"
 
 
@@ -4871,11 +4912,11 @@ msgstr ""
 msgid "The parameter of server_name is required"
 msgid "The parameter of server_name is required"
 msgstr "معلمة server_name مطلوبة"
 msgstr "معلمة server_name مطلوبة"
 
 
-#: src/views/certificate/CertificateEditor.vue:181
+#: src/views/certificate/CertificateEditor.vue:179
 msgid "The path exists, but the file is not a certificate"
 msgid "The path exists, but the file is not a certificate"
 msgstr "المسار موجود، لكن الملف ليس شهادة"
 msgstr "المسار موجود، لكن الملف ليس شهادة"
 
 
-#: src/views/certificate/CertificateEditor.vue:196
+#: src/views/certificate/CertificateEditor.vue:194
 msgid "The path exists, but the file is not a private key"
 msgid "The path exists, but the file is not a private key"
 msgstr "المسار موجود، لكن الملف ليس مفتاحًا خاصًا"
 msgstr "المسار موجود، لكن الملف ليس مفتاحًا خاصًا"
 
 
@@ -4936,17 +4977,17 @@ msgstr ""
 "والعوامل الثانية. إذا لم تتمكن من العثور على هذه الرموز، فستفقد الوصول إلى "
 "والعوامل الثانية. إذا لم تتمكن من العثور على هذه الرموز، فستفقد الوصول إلى "
 "حسابك."
 "حسابك."
 
 
-#: src/views/certificate/CertificateEditor.vue:102
+#: src/views/certificate/CertificateEditor.vue:100
 msgid "This Auto Cert item is invalid, please remove it."
 msgid "This Auto Cert item is invalid, please remove it."
 msgstr "هذا العنصر في الشهادة التلقائية غير صالح، يرجى إزالته."
 msgstr "هذا العنصر في الشهادة التلقائية غير صالح، يرجى إزالته."
 
 
-#: src/views/certificate/CertificateEditor.vue:92
+#: src/views/certificate/CertificateEditor.vue:90
 msgid "This certificate is managed by Nginx UI"
 msgid "This certificate is managed by Nginx UI"
 msgstr "يتم إدارة هذه الشهادة بواسطة Nginx UI"
 msgstr "يتم إدارة هذه الشهادة بواسطة Nginx UI"
 
 
-#: src/views/certificate/CertificateEditor.vue:165
-#: src/views/certificate/CertificateEditor.vue:179
-#: src/views/certificate/CertificateEditor.vue:194
+#: src/views/certificate/CertificateEditor.vue:163
+#: src/views/certificate/CertificateEditor.vue:177
+#: src/views/certificate/CertificateEditor.vue:192
 msgid "This field is required"
 msgid "This field is required"
 msgstr "هذا الحقل مطلوب"
 msgstr "هذا الحقل مطلوب"
 
 
@@ -5416,6 +5457,10 @@ msgstr "عند إنشاء رموز استرداد جديدة، يجب عليك 
 msgid "Whether to use a temporary path when writing temporary files"
 msgid "Whether to use a temporary path when writing temporary files"
 msgstr "ما إذا كان سيتم استخدام مسار مؤقت عند كتابة الملفات المؤقتة"
 msgstr "ما إذا كان سيتم استخدام مسار مؤقت عند كتابة الملفات المؤقتة"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:107
+msgid "Wildcard Certificate"
+msgstr "شهادة البدل"
+
 #: src/views/dashboard/components/ParamsOpt/PerformanceConfig.vue:48
 #: src/views/dashboard/components/ParamsOpt/PerformanceConfig.vue:48
 msgid "Worker Connections"
 msgid "Worker Connections"
 msgstr "اتصالات العامل"
 msgstr "اتصالات العامل"
@@ -5757,9 +5802,6 @@ msgstr "مفاتيح المرور الخاصة بك"
 #~ msgid "File"
 #~ msgid "File"
 #~ msgstr "ملف"
 #~ msgstr "ملف"
 
 
-#~ msgid "Server error"
-#~ msgstr "خطأ في الخادم"
-
 #~ msgid "Incorrect username or password"
 #~ msgid "Incorrect username or password"
 #~ msgstr "اسم المستخدم أو كلمة المرور غير صحيحة"
 #~ msgstr "اسم المستخدم أو كلمة المرور غير صحيحة"
 
 

+ 84 - 42
app/src/language/de_DE/app.po

@@ -180,6 +180,10 @@ msgstr "Konfiguration hinzufügen"
 msgid "Add Directive Below"
 msgid "Add Directive Below"
 msgstr "Anweisung darunter hinzufügen"
 msgstr "Anweisung darunter hinzufügen"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:151
+msgid "Add Domain"
+msgstr "Domain hinzufügen"
+
 #: src/components/NgxConfigEditor/LocationEditor.vue:131
 #: src/components/NgxConfigEditor/LocationEditor.vue:131
 #: src/components/NgxConfigEditor/LocationEditor.vue:158
 #: src/components/NgxConfigEditor/LocationEditor.vue:158
 msgid "Add Location"
 msgid "Add Location"
@@ -229,6 +233,14 @@ msgstr "Alle"
 msgid "All Recovery Codes Have Been Used"
 msgid "All Recovery Codes Have Been Used"
 msgstr "Alle Wiederherstellungscodes wurden verwendet"
 msgstr "Alle Wiederherstellungscodes wurden verwendet"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:156
+msgid ""
+"All selected subdomains must belong to the same DNS Provider, otherwise the "
+"certificate application will fail."
+msgstr ""
+"Alle ausgewählten Subdomains müssen zum selben DNS-Anbieter gehören, "
+"ansonsten schlägt die Zertifikatsbeantragung fehl."
+
 #: src/views/preference/tabs/OpenAISettings.vue:32
 #: src/views/preference/tabs/OpenAISettings.vue:32
 msgid "API Base Url"
 msgid "API Base Url"
 msgstr "API-Basis-URL"
 msgstr "API-Basis-URL"
@@ -255,7 +267,7 @@ msgstr "App"
 
 
 #: src/views/system/Upgrade.vue:195
 #: src/views/system/Upgrade.vue:195
 msgid "Arch"
 msgid "Arch"
-msgstr "\"Arch\""
+msgstr "Arch"
 
 
 #: src/views/preference/tabs/AuthSettings.vue:130
 #: src/views/preference/tabs/AuthSettings.vue:130
 msgid "Are you sure to delete this banned IP immediately?"
 msgid "Are you sure to delete this banned IP immediately?"
@@ -394,7 +406,7 @@ msgstr "Automatische Verlängerung deaktiviert für %{name}"
 msgid "Auto-renewal enabled for %{name}"
 msgid "Auto-renewal enabled for %{name}"
 msgstr "Automatische Verlängerung aktiviert für %{name}"
 msgstr "Automatische Verlängerung aktiviert für %{name}"
 
 
-#: src/views/certificate/components/RenewCert.vue:49
+#: src/views/certificate/components/RenewCert.vue:51
 #: src/views/site/site_edit/components/Cert/IssueCert.vue:84
 #: src/views/site/site_edit/components/Cert/IssueCert.vue:84
 msgid "AutoCert is running, please wait..."
 msgid "AutoCert is running, please wait..."
 msgstr "AutoCert wird ausgeführt, bitte warten..."
 msgstr "AutoCert wird ausgeführt, bitte warten..."
@@ -407,7 +419,7 @@ msgstr "\"AutoCert wird ausgeführt...\""
 msgid "Automatic Restart"
 msgid "Automatic Restart"
 msgstr "\"Automatischer Neustart\""
 msgstr "\"Automatischer Neustart\""
 
 
-#: src/views/certificate/CertificateEditor.vue:259
+#: src/views/certificate/CertificateEditor.vue:257
 #: src/views/config/components/ConfigLeftPanel.vue:273
 #: src/views/config/components/ConfigLeftPanel.vue:273
 #: src/views/config/ConfigList.vue:112 src/views/config/ConfigList.vue:195
 #: src/views/config/ConfigList.vue:112 src/views/config/ConfigList.vue:195
 #: src/views/nginx_log/NginxLog.vue:174
 #: src/views/nginx_log/NginxLog.vue:174
@@ -712,12 +724,16 @@ msgstr "Zertifikat erfolgreich erneuert"
 msgid "Certificate revoked successfully"
 msgid "Certificate revoked successfully"
 msgstr "Zertifikat erfolgreich widerrufen"
 msgstr "Zertifikat erfolgreich widerrufen"
 
 
-#: src/views/certificate/CertificateEditor.vue:128
+#: src/views/certificate/CertificateEditor.vue:126
 #: src/views/site/site_edit/components/Cert/Cert.vue:58
 #: src/views/site/site_edit/components/Cert/Cert.vue:58
 msgid "Certificate Status"
 msgid "Certificate Status"
 msgid_plural "Certificates Status"
 msgid_plural "Certificates Status"
 msgstr[0] "Zertifikatsstatus"
 msgstr[0] "Zertifikatsstatus"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:104
+msgid "Certificate Type"
+msgstr "Zertifikatstyp"
+
 #: src/routes/modules/certificates.ts:11
 #: src/routes/modules/certificates.ts:11
 #: src/views/certificate/CertificateList/Certificate.vue:19
 #: src/views/certificate/CertificateList/Certificate.vue:19
 msgid "Certificates"
 msgid "Certificates"
@@ -1210,6 +1226,14 @@ msgstr "Benutzerdefinierter Cron-Ausdruck"
 msgid "Custom Directory"
 msgid "Custom Directory"
 msgstr "Benutzerdefiniertes Verzeichnis"
 msgstr "Benutzerdefiniertes Verzeichnis"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:126
+msgid "Custom Domains"
+msgstr "Benutzerdefinierte Domains"
+
+#: src/views/certificate/components/DNSIssueCertificate.vue:110
+msgid "Custom Domains Certificate"
+msgstr "Benutzerdefinierte Domänenzertifikate"
+
 #: src/views/preference/tabs/NodeSettings.vue:19
 #: src/views/preference/tabs/NodeSettings.vue:19
 msgid ""
 msgid ""
 "Customize the name of local node to be displayed in the environment "
 "Customize the name of local node to be displayed in the environment "
@@ -1521,11 +1545,11 @@ msgid "Document"
 msgid_plural "Documents"
 msgid_plural "Documents"
 msgstr[0] "Dokument"
 msgstr[0] "Dokument"
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:66
+#: src/views/certificate/components/DNSIssueCertificate.vue:116
 msgid "Domain"
 msgid "Domain"
 msgstr "Domain"
 msgstr "Domain"
 
 
-#: src/views/certificate/CertificateEditor.vue:112
+#: src/views/certificate/CertificateEditor.vue:110
 msgid "Domains list is empty, try to reopen Auto Cert for %{config}"
 msgid "Domains list is empty, try to reopen Auto Cert for %{config}"
 msgstr ""
 msgstr ""
 "Domänenliste ist leer, versuche Auto-Zertifikat für %{config} erneut zu "
 "Domänenliste ist leer, versuche Auto-Zertifikat für %{config} erneut zu "
@@ -1730,6 +1754,14 @@ msgstr "Webseite mit Let's Encrypt verschlüsseln"
 msgid "End"
 msgid "End"
 msgstr "Ende"
 msgstr "Ende"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:135
+msgid "Enter domain name"
+msgstr "Domänennamen eingeben"
+
+#: src/views/certificate/components/DNSIssueCertificate.vue:120
+msgid "Enter your domain"
+msgstr "Geben Sie Ihre Domain ein"
+
 #: src/language/constants.ts:22
 #: src/language/constants.ts:22
 msgid "Environment variables cleaned"
 msgid "Environment variables cleaned"
 msgstr "Umgebungsvariablen gesäubert"
 msgstr "Umgebungsvariablen gesäubert"
@@ -1804,7 +1836,7 @@ msgstr "Externer Docker-Container"
 msgid "External Notify"
 msgid "External Notify"
 msgstr "Externe Benachrichtigung"
 msgstr "Externe Benachrichtigung"
 
 
-#: src/views/site/site_edit/components/Cert/ObtainCertLive.vue:80
+#: src/views/site/site_edit/components/Cert/ObtainCertLive.vue:81
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
 msgstr "Zertifikat konnte nicht abgerufen werden"
 msgstr "Zertifikat konnte nicht abgerufen werden"
 
 
@@ -2336,7 +2368,7 @@ msgid "Import"
 msgstr "Import"
 msgstr "Import"
 
 
 #: src/routes/modules/certificates.ts:46
 #: src/routes/modules/certificates.ts:46
-#: src/views/certificate/CertificateEditor.vue:85
+#: src/views/certificate/CertificateEditor.vue:83
 msgid "Import Certificate"
 msgid "Import Certificate"
 msgstr "Zertifikat importieren"
 msgstr "Zertifikat importieren"
 
 
@@ -2481,12 +2513,12 @@ msgid "IP"
 msgstr "IP"
 msgstr "IP"
 
 
 #: src/views/certificate/CertificateList/Certificate.vue:37
 #: src/views/certificate/CertificateList/Certificate.vue:37
-msgid "Issue wildcard certificate"
-msgstr "Wildcard-Zertifikat ausstellen"
+msgid "Issue certificate"
+msgstr "Zertifikat ausstellen"
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:57
-msgid "Issue Wildcard Certificate"
-msgstr "Wildcard-Zertifikat ausstellen"
+#: src/views/certificate/components/DNSIssueCertificate.vue:95
+msgid "Issue Certificate"
+msgstr "Zertifikat ausstellen"
 
 
 #: src/language/constants.ts:20
 #: src/language/constants.ts:20
 msgid "Issued certificate successfully"
 msgid "Issued certificate successfully"
@@ -2569,8 +2601,8 @@ msgstr "Leer lassen, wenn keine Änderung gewünscht ist"
 msgid "Leave blank if you don't need this."
 msgid "Leave blank if you don't need this."
 msgstr "Lassen Sie dieses Feld leer, wenn Sie es nicht benötigen."
 msgstr "Lassen Sie dieses Feld leer, wenn Sie es nicht benötigen."
 
 
-#: src/views/certificate/CertificateEditor.vue:223
-#: src/views/certificate/CertificateEditor.vue:237
+#: src/views/certificate/CertificateEditor.vue:221
+#: src/views/certificate/CertificateEditor.vue:235
 msgid "Leave blank will not change anything"
 msgid "Leave blank will not change anything"
 msgstr "Leer lassen ändert nichts"
 msgstr "Leer lassen ändert nichts"
 
 
@@ -2657,7 +2689,7 @@ msgstr "Ort"
 msgid "Locations"
 msgid "Locations"
 msgstr "Orte"
 msgstr "Orte"
 
 
-#: src/views/certificate/CertificateEditor.vue:247
+#: src/views/certificate/CertificateEditor.vue:245
 msgid "Log"
 msgid "Log"
 msgstr "Protokoll"
 msgstr "Protokoll"
 
 
@@ -2871,7 +2903,7 @@ msgid "Modify"
 msgstr "Ändern"
 msgstr "Ändern"
 
 
 #: src/routes/modules/certificates.ts:36
 #: src/routes/modules/certificates.ts:36
-#: src/views/certificate/CertificateEditor.vue:85
+#: src/views/certificate/CertificateEditor.vue:83
 msgid "Modify Certificate"
 msgid "Modify Certificate"
 msgstr "Zertifikat ändern"
 msgstr "Zertifikat ändern"
 
 
@@ -2906,7 +2938,7 @@ msgstr "Mehrzeilige Direktive"
 #: src/components/NgxConfigEditor/NgxUpstream.vue:199
 #: src/components/NgxConfigEditor/NgxUpstream.vue:199
 #: src/views/backup/AutoBackup/AutoBackup.vue:11
 #: src/views/backup/AutoBackup/AutoBackup.vue:11
 #: src/views/certificate/ACMEUser.vue:11
 #: src/views/certificate/ACMEUser.vue:11
-#: src/views/certificate/CertificateEditor.vue:162
+#: src/views/certificate/CertificateEditor.vue:160
 #: src/views/certificate/CertificateList/certColumns.tsx:9
 #: src/views/certificate/CertificateList/certColumns.tsx:9
 #: src/views/certificate/DNSCredential.vue:9
 #: src/views/certificate/DNSCredential.vue:9
 #: src/views/config/components/ConfigRightPanel/Basic.vue:34
 #: src/views/config/components/ConfigRightPanel/Basic.vue:34
@@ -2966,7 +2998,7 @@ msgstr "Neuer Pfad"
 msgid "New version released"
 msgid "New version released"
 msgstr "Neue Version veröffentlicht"
 msgstr "Neue Version veröffentlicht"
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:89
+#: src/views/certificate/components/DNSIssueCertificate.vue:181
 #: src/views/install/components/InstallView.vue:96
 #: src/views/install/components/InstallView.vue:96
 #: src/views/site/site_add/SiteAdd.vue:132
 #: src/views/site/site_add/SiteAdd.vue:132
 #: src/views/site/site_edit/components/Cert/ObtainCert.vue:214
 #: src/views/site/site_edit/components/Cert/ObtainCert.vue:214
@@ -3555,6 +3587,10 @@ msgstr ""
 msgid "Please enter a valid port range"
 msgid "Please enter a valid port range"
 msgstr "Bitte geben Sie einen gültigen Portbereich ein"
 msgstr "Bitte geben Sie einen gültigen Portbereich ein"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:74
+msgid "Please enter at least one domain"
+msgstr "Bitte geben Sie mindestens eine Domain ein"
+
 #: src/components/TwoFA/Authorization.vue:85
 #: src/components/TwoFA/Authorization.vue:85
 msgid "Please enter the OTP code:"
 msgid "Please enter the OTP code:"
 msgstr "Bitte gib den OTP-Code ein:"
 msgstr "Bitte gib den OTP-Code ein:"
@@ -3902,6 +3938,7 @@ msgstr "Lade neu"
 msgid "Reloading nginx"
 msgid "Reloading nginx"
 msgstr "Lade Nginx neu"
 msgstr "Lade Nginx neu"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:144
 #: src/views/preference/tabs/AuthSettings.vue:137
 #: src/views/preference/tabs/AuthSettings.vue:137
 msgid "Remove"
 msgid "Remove"
 msgstr "Löschen"
 msgstr "Löschen"
@@ -3984,8 +4021,8 @@ msgstr "Erfolgreich umbenannt"
 msgid "Renamed successfully"
 msgid "Renamed successfully"
 msgstr "Erfolgreich umbenannt"
 msgstr "Erfolgreich umbenannt"
 
 
-#: src/views/certificate/components/RenewCert.vue:46
-#: src/views/certificate/components/RenewCert.vue:53
+#: src/views/certificate/components/RenewCert.vue:48
+#: src/views/certificate/components/RenewCert.vue:55
 msgid "Renew Certificate"
 msgid "Renew Certificate"
 msgstr "Zertifikat erneuern"
 msgstr "Zertifikat erneuern"
 
 
@@ -3997,8 +4034,8 @@ msgstr "Fehler bei der Zertifikatsverlängerung"
 msgid "Renew Certificate Success"
 msgid "Renew Certificate Success"
 msgstr "Zertifikat erfolgreich verlängert"
 msgstr "Zertifikat erfolgreich verlängert"
 
 
-#: src/views/certificate/components/RenewCert.vue:28
-#: src/views/certificate/components/WildcardCertificate.vue:46
+#: src/views/certificate/components/DNSIssueCertificate.vue:84
+#: src/views/certificate/components/RenewCert.vue:30
 msgid "Renew successfully"
 msgid "Renew successfully"
 msgstr "Erfolgreich erneuert"
 msgstr "Erfolgreich erneuert"
 
 
@@ -4259,7 +4296,7 @@ msgstr "Samstag"
 
 
 #: src/components/ChatGPT/ChatMessage.vue:215
 #: src/components/ChatGPT/ChatMessage.vue:215
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:129
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:129
-#: src/language/curd.ts:18 src/views/certificate/CertificateEditor.vue:266
+#: src/language/curd.ts:18 src/views/certificate/CertificateEditor.vue:264
 #: src/views/config/components/ConfigLeftPanel.vue:282
 #: src/views/config/components/ConfigLeftPanel.vue:282
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/preference/components/AuthSettings/Passkey.vue:130
 #: src/views/preference/components/AuthSettings/Passkey.vue:130
@@ -4314,7 +4351,7 @@ msgstr "Speichern des Streams %{name} auf %{node} fehlgeschlagen"
 msgid "Save stream %{name} to %{node} successfully"
 msgid "Save stream %{name} to %{node} successfully"
 msgstr "Stream %{name} erfolgreich auf %{node} gespeichert"
 msgstr "Stream %{name} erfolgreich auf %{node} gespeichert"
 
 
-#: src/language/curd.ts:35 src/views/certificate/CertificateEditor.vue:49
+#: src/language/curd.ts:35 src/views/certificate/store.ts:13
 #: src/views/preference/store/index.ts:118
 #: src/views/preference/store/index.ts:118
 msgid "Save successfully"
 msgid "Save successfully"
 msgstr "Erfolgreich gespeichert"
 msgstr "Erfolgreich gespeichert"
@@ -4424,6 +4461,10 @@ msgstr "Senden"
 msgid "Server"
 msgid "Server"
 msgstr "Server"
 msgstr "Server"
 
 
+#: src/views/certificate/CertificateEditor.vue:55
+msgid "Server error"
+msgstr "Serverfehler"
+
 #: src/views/dashboard/ServerAnalytic.vue:175
 #: src/views/dashboard/ServerAnalytic.vue:175
 msgid "Server Info"
 msgid "Server Info"
 msgstr "Serverinformationen"
 msgstr "Serverinformationen"
@@ -4560,7 +4601,7 @@ msgstr "Wartezeit zwischen den Iterationen des Cache-Loaders"
 msgid "Sleep time between cache manager iterations"
 msgid "Sleep time between cache manager iterations"
 msgstr "Wartezeit zwischen den Iterationen des Cache-Managers"
 msgstr "Wartezeit zwischen den Iterationen des Cache-Managers"
 
 
-#: src/views/certificate/CertificateEditor.vue:213
+#: src/views/certificate/CertificateEditor.vue:211
 msgid "SSL Certificate Content"
 msgid "SSL Certificate Content"
 msgstr "SSL-Zertifikatsinhalt"
 msgstr "SSL-Zertifikatsinhalt"
 
 
@@ -4574,15 +4615,15 @@ msgstr ""
 msgid "SSL certificate file not found"
 msgid "SSL certificate file not found"
 msgstr "SSL-Zertifikatsdatei nicht gefunden"
 msgstr "SSL-Zertifikatsdatei nicht gefunden"
 
 
-#: src/views/certificate/CertificateEditor.vue:227
+#: src/views/certificate/CertificateEditor.vue:225
 msgid "SSL Certificate Key Content"
 msgid "SSL Certificate Key Content"
 msgstr "SSL-Zertifikatsschlüsselinhalt"
 msgstr "SSL-Zertifikatsschlüsselinhalt"
 
 
-#: src/views/certificate/CertificateEditor.vue:192
+#: src/views/certificate/CertificateEditor.vue:190
 msgid "SSL Certificate Key Path"
 msgid "SSL Certificate Key Path"
 msgstr "SSL-Zertifikatsschlüssel-Pfad"
 msgstr "SSL-Zertifikatsschlüssel-Pfad"
 
 
-#: src/views/certificate/CertificateEditor.vue:177
+#: src/views/certificate/CertificateEditor.vue:175
 #: src/views/preference/tabs/ServerSettings.vue:37
 #: src/views/preference/tabs/ServerSettings.vue:37
 msgid "SSL Certificate Path"
 msgid "SSL Certificate Path"
 msgstr "SSL-Zertifikatspfad"
 msgstr "SSL-Zertifikatspfad"
@@ -4824,7 +4865,7 @@ msgstr "Synchrone Knoten"
 msgid "Sync strategy"
 msgid "Sync strategy"
 msgstr "Synchronisierungsstrategie"
 msgstr "Synchronisierungsstrategie"
 
 
-#: src/views/certificate/CertificateEditor.vue:206
+#: src/views/certificate/CertificateEditor.vue:204
 msgid "Sync to"
 msgid "Sync to"
 msgstr "Synchronisieren mit"
 msgstr "Synchronisieren mit"
 
 
@@ -4900,11 +4941,11 @@ msgstr ""
 "Die ICP-Nummer sollte nur Buchstaben, Unicode, Zahlen, Bindestriche, "
 "Die ICP-Nummer sollte nur Buchstaben, Unicode, Zahlen, Bindestriche, "
 "Doppelpunkte und Punkte enthalten."
 "Doppelpunkte und Punkte enthalten."
 
 
-#: src/views/certificate/CertificateEditor.vue:216
+#: src/views/certificate/CertificateEditor.vue:214
 msgid "The input is not a SSL Certificate"
 msgid "The input is not a SSL Certificate"
 msgstr "Die Eingabe ist kein SSL-Zertifikat"
 msgstr "Die Eingabe ist kein SSL-Zertifikat"
 
 
-#: src/views/certificate/CertificateEditor.vue:230
+#: src/views/certificate/CertificateEditor.vue:228
 msgid "The input is not a SSL Certificate Key"
 msgid "The input is not a SSL Certificate Key"
 msgstr "Die Eingabe ist kein SSL-Zertifikatsschlüssel"
 msgstr "Die Eingabe ist kein SSL-Zertifikatsschlüssel"
 
 
@@ -4943,11 +4984,11 @@ msgstr ""
 msgid "The parameter of server_name is required"
 msgid "The parameter of server_name is required"
 msgstr "Der Parameter server_name ist erforderlich"
 msgstr "Der Parameter server_name ist erforderlich"
 
 
-#: src/views/certificate/CertificateEditor.vue:181
+#: src/views/certificate/CertificateEditor.vue:179
 msgid "The path exists, but the file is not a certificate"
 msgid "The path exists, but the file is not a certificate"
 msgstr "Der Pfad existiert, aber die Datei ist kein Zertifikat"
 msgstr "Der Pfad existiert, aber die Datei ist kein Zertifikat"
 
 
-#: src/views/certificate/CertificateEditor.vue:196
+#: src/views/certificate/CertificateEditor.vue:194
 msgid "The path exists, but the file is not a private key"
 msgid "The path exists, but the file is not a private key"
 msgstr "Der Pfad existiert, aber die Datei ist kein privater Schlüssel"
 msgstr "Der Pfad existiert, aber die Datei ist kein privater Schlüssel"
 
 
@@ -5009,17 +5050,17 @@ msgstr ""
 "Ihr Passwort und die zweiten Faktoren verlieren. Wenn Sie diese Codes nicht "
 "Ihr Passwort und die zweiten Faktoren verlieren. Wenn Sie diese Codes nicht "
 "finden können, verlieren Sie den Zugriff auf Ihr Konto."
 "finden können, verlieren Sie den Zugriff auf Ihr Konto."
 
 
-#: src/views/certificate/CertificateEditor.vue:102
+#: src/views/certificate/CertificateEditor.vue:100
 msgid "This Auto Cert item is invalid, please remove it."
 msgid "This Auto Cert item is invalid, please remove it."
 msgstr "Dieses Auto-Zertifikatselement ist ungültig, bitte entferne es."
 msgstr "Dieses Auto-Zertifikatselement ist ungültig, bitte entferne es."
 
 
-#: src/views/certificate/CertificateEditor.vue:92
+#: src/views/certificate/CertificateEditor.vue:90
 msgid "This certificate is managed by Nginx UI"
 msgid "This certificate is managed by Nginx UI"
 msgstr "Dieses Zertifikat wird von Nginx UI verwaltet"
 msgstr "Dieses Zertifikat wird von Nginx UI verwaltet"
 
 
-#: src/views/certificate/CertificateEditor.vue:165
-#: src/views/certificate/CertificateEditor.vue:179
-#: src/views/certificate/CertificateEditor.vue:194
+#: src/views/certificate/CertificateEditor.vue:163
+#: src/views/certificate/CertificateEditor.vue:177
+#: src/views/certificate/CertificateEditor.vue:192
 msgid "This field is required"
 msgid "This field is required"
 msgstr "Dieses Feld ist erforderlich"
 msgstr "Dieses Feld ist erforderlich"
 
 
@@ -5505,6 +5546,10 @@ msgstr ""
 "Ob ein temporärer Pfad beim Schreiben temporärer Dateien verwendet werden "
 "Ob ein temporärer Pfad beim Schreiben temporärer Dateien verwendet werden "
 "soll"
 "soll"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:107
+msgid "Wildcard Certificate"
+msgstr "Wildcard-Zertifikat"
+
 #: src/views/dashboard/components/ParamsOpt/PerformanceConfig.vue:48
 #: src/views/dashboard/components/ParamsOpt/PerformanceConfig.vue:48
 msgid "Worker Connections"
 msgid "Worker Connections"
 msgstr "Worker-Verbindungen"
 msgstr "Worker-Verbindungen"
@@ -5860,9 +5905,6 @@ msgstr "Deine Passkeys"
 #~ msgid "Recovery Code:"
 #~ msgid "Recovery Code:"
 #~ msgstr "Wiederherstellungscode:"
 #~ msgstr "Wiederherstellungscode:"
 
 
-#~ msgid "Server error"
-#~ msgstr "Serverfehler"
-
 #~ msgid "The recovery code is only displayed once, please save it in a safe place."
 #~ msgid "The recovery code is only displayed once, please save it in a safe place."
 #~ msgstr ""
 #~ msgstr ""
 #~ "Der Wiederherstellungscode wird nur einmal angezeigt, bitte speichere ihn "
 #~ "Der Wiederherstellungscode wird nur einmal angezeigt, bitte speichere ihn "

+ 79 - 36
app/src/language/en/app.po

@@ -164,6 +164,10 @@ msgstr ""
 msgid "Add Directive Below"
 msgid "Add Directive Below"
 msgstr ""
 msgstr ""
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:151
+msgid "Add Domain"
+msgstr ""
+
 #: src/components/NgxConfigEditor/LocationEditor.vue:131
 #: src/components/NgxConfigEditor/LocationEditor.vue:131
 #: src/components/NgxConfigEditor/LocationEditor.vue:158
 #: src/components/NgxConfigEditor/LocationEditor.vue:158
 msgid "Add Location"
 msgid "Add Location"
@@ -211,6 +215,12 @@ msgstr ""
 msgid "All Recovery Codes Have Been Used"
 msgid "All Recovery Codes Have Been Used"
 msgstr ""
 msgstr ""
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:156
+msgid ""
+"All selected subdomains must belong to the same DNS Provider, otherwise the "
+"certificate application will fail."
+msgstr ""
+
 #: src/views/preference/tabs/OpenAISettings.vue:32
 #: src/views/preference/tabs/OpenAISettings.vue:32
 msgid "API Base Url"
 msgid "API Base Url"
 msgstr ""
 msgstr ""
@@ -372,7 +382,7 @@ msgstr ""
 msgid "Auto-renewal enabled for %{name}"
 msgid "Auto-renewal enabled for %{name}"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/components/RenewCert.vue:49
+#: src/views/certificate/components/RenewCert.vue:51
 #: src/views/site/site_edit/components/Cert/IssueCert.vue:84
 #: src/views/site/site_edit/components/Cert/IssueCert.vue:84
 msgid "AutoCert is running, please wait..."
 msgid "AutoCert is running, please wait..."
 msgstr ""
 msgstr ""
@@ -385,7 +395,7 @@ msgstr ""
 msgid "Automatic Restart"
 msgid "Automatic Restart"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/CertificateEditor.vue:259
+#: src/views/certificate/CertificateEditor.vue:257
 #: src/views/config/components/ConfigLeftPanel.vue:273
 #: src/views/config/components/ConfigLeftPanel.vue:273
 #: src/views/config/ConfigList.vue:112 src/views/config/ConfigList.vue:195
 #: src/views/config/ConfigList.vue:112 src/views/config/ConfigList.vue:195
 #: src/views/nginx_log/NginxLog.vue:174
 #: src/views/nginx_log/NginxLog.vue:174
@@ -677,13 +687,17 @@ msgstr ""
 msgid "Certificate revoked successfully"
 msgid "Certificate revoked successfully"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/CertificateEditor.vue:128
+#: src/views/certificate/CertificateEditor.vue:126
 #: src/views/site/site_edit/components/Cert/Cert.vue:58
 #: src/views/site/site_edit/components/Cert/Cert.vue:58
 msgid "Certificate Status"
 msgid "Certificate Status"
 msgid_plural "Certificates Status"
 msgid_plural "Certificates Status"
 msgstr[0] ""
 msgstr[0] ""
 msgstr[1] ""
 msgstr[1] ""
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:104
+msgid "Certificate Type"
+msgstr ""
+
 #: src/routes/modules/certificates.ts:11
 #: src/routes/modules/certificates.ts:11
 #: src/views/certificate/CertificateList/Certificate.vue:19
 #: src/views/certificate/CertificateList/Certificate.vue:19
 msgid "Certificates"
 msgid "Certificates"
@@ -1133,6 +1147,14 @@ msgstr ""
 msgid "Custom Directory"
 msgid "Custom Directory"
 msgstr ""
 msgstr ""
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:126
+msgid "Custom Domains"
+msgstr ""
+
+#: src/views/certificate/components/DNSIssueCertificate.vue:110
+msgid "Custom Domains Certificate"
+msgstr ""
+
 #: src/views/preference/tabs/NodeSettings.vue:19
 #: src/views/preference/tabs/NodeSettings.vue:19
 msgid ""
 msgid ""
 "Customize the name of local node to be displayed in the environment "
 "Customize the name of local node to be displayed in the environment "
@@ -1441,11 +1463,11 @@ msgid_plural "Documents"
 msgstr[0] ""
 msgstr[0] ""
 msgstr[1] ""
 msgstr[1] ""
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:66
+#: src/views/certificate/components/DNSIssueCertificate.vue:116
 msgid "Domain"
 msgid "Domain"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/CertificateEditor.vue:112
+#: src/views/certificate/CertificateEditor.vue:110
 msgid "Domains list is empty, try to reopen Auto Cert for %{config}"
 msgid "Domains list is empty, try to reopen Auto Cert for %{config}"
 msgstr ""
 msgstr ""
 
 
@@ -1645,6 +1667,14 @@ msgstr ""
 msgid "End"
 msgid "End"
 msgstr ""
 msgstr ""
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:135
+msgid "Enter domain name"
+msgstr ""
+
+#: src/views/certificate/components/DNSIssueCertificate.vue:120
+msgid "Enter your domain"
+msgstr ""
+
 #: src/language/constants.ts:22
 #: src/language/constants.ts:22
 msgid "Environment variables cleaned"
 msgid "Environment variables cleaned"
 msgstr ""
 msgstr ""
@@ -1719,7 +1749,7 @@ msgstr ""
 msgid "External Notify"
 msgid "External Notify"
 msgstr ""
 msgstr ""
 
 
-#: src/views/site/site_edit/components/Cert/ObtainCertLive.vue:80
+#: src/views/site/site_edit/components/Cert/ObtainCertLive.vue:81
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
 msgstr ""
 msgstr ""
 
 
@@ -2240,7 +2270,7 @@ msgid "Import"
 msgstr ""
 msgstr ""
 
 
 #: src/routes/modules/certificates.ts:46
 #: src/routes/modules/certificates.ts:46
-#: src/views/certificate/CertificateEditor.vue:85
+#: src/views/certificate/CertificateEditor.vue:83
 msgid "Import Certificate"
 msgid "Import Certificate"
 msgstr ""
 msgstr ""
 
 
@@ -2381,11 +2411,11 @@ msgid "IP"
 msgstr ""
 msgstr ""
 
 
 #: src/views/certificate/CertificateList/Certificate.vue:37
 #: src/views/certificate/CertificateList/Certificate.vue:37
-msgid "Issue wildcard certificate"
+msgid "Issue certificate"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:57
-msgid "Issue Wildcard Certificate"
+#: src/views/certificate/components/DNSIssueCertificate.vue:95
+msgid "Issue Certificate"
 msgstr ""
 msgstr ""
 
 
 #: src/language/constants.ts:20
 #: src/language/constants.ts:20
@@ -2467,8 +2497,8 @@ msgstr ""
 msgid "Leave blank if you don't need this."
 msgid "Leave blank if you don't need this."
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/CertificateEditor.vue:223
-#: src/views/certificate/CertificateEditor.vue:237
+#: src/views/certificate/CertificateEditor.vue:221
+#: src/views/certificate/CertificateEditor.vue:235
 msgid "Leave blank will not change anything"
 msgid "Leave blank will not change anything"
 msgstr ""
 msgstr ""
 
 
@@ -2555,7 +2585,7 @@ msgstr ""
 msgid "Locations"
 msgid "Locations"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/CertificateEditor.vue:247
+#: src/views/certificate/CertificateEditor.vue:245
 msgid "Log"
 msgid "Log"
 msgstr ""
 msgstr ""
 
 
@@ -2757,7 +2787,7 @@ msgid "Modify"
 msgstr ""
 msgstr ""
 
 
 #: src/routes/modules/certificates.ts:36
 #: src/routes/modules/certificates.ts:36
-#: src/views/certificate/CertificateEditor.vue:85
+#: src/views/certificate/CertificateEditor.vue:83
 msgid "Modify Certificate"
 msgid "Modify Certificate"
 msgstr ""
 msgstr ""
 
 
@@ -2792,7 +2822,7 @@ msgstr ""
 #: src/components/NgxConfigEditor/NgxUpstream.vue:199
 #: src/components/NgxConfigEditor/NgxUpstream.vue:199
 #: src/views/backup/AutoBackup/AutoBackup.vue:11
 #: src/views/backup/AutoBackup/AutoBackup.vue:11
 #: src/views/certificate/ACMEUser.vue:11
 #: src/views/certificate/ACMEUser.vue:11
-#: src/views/certificate/CertificateEditor.vue:162
+#: src/views/certificate/CertificateEditor.vue:160
 #: src/views/certificate/CertificateList/certColumns.tsx:9
 #: src/views/certificate/CertificateList/certColumns.tsx:9
 #: src/views/certificate/DNSCredential.vue:9
 #: src/views/certificate/DNSCredential.vue:9
 #: src/views/config/components/ConfigRightPanel/Basic.vue:34
 #: src/views/config/components/ConfigRightPanel/Basic.vue:34
@@ -2852,7 +2882,7 @@ msgstr ""
 msgid "New version released"
 msgid "New version released"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:89
+#: src/views/certificate/components/DNSIssueCertificate.vue:181
 #: src/views/install/components/InstallView.vue:96
 #: src/views/install/components/InstallView.vue:96
 #: src/views/site/site_add/SiteAdd.vue:132
 #: src/views/site/site_add/SiteAdd.vue:132
 #: src/views/site/site_edit/components/Cert/ObtainCert.vue:214
 #: src/views/site/site_edit/components/Cert/ObtainCert.vue:214
@@ -3425,6 +3455,10 @@ msgstr ""
 msgid "Please enter a valid port range"
 msgid "Please enter a valid port range"
 msgstr ""
 msgstr ""
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:74
+msgid "Please enter at least one domain"
+msgstr ""
+
 #: src/components/TwoFA/Authorization.vue:85
 #: src/components/TwoFA/Authorization.vue:85
 msgid "Please enter the OTP code:"
 msgid "Please enter the OTP code:"
 msgstr ""
 msgstr ""
@@ -3751,6 +3785,7 @@ msgstr ""
 msgid "Reloading nginx"
 msgid "Reloading nginx"
 msgstr ""
 msgstr ""
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:144
 #: src/views/preference/tabs/AuthSettings.vue:137
 #: src/views/preference/tabs/AuthSettings.vue:137
 msgid "Remove"
 msgid "Remove"
 msgstr ""
 msgstr ""
@@ -3833,8 +3868,8 @@ msgstr ""
 msgid "Renamed successfully"
 msgid "Renamed successfully"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/components/RenewCert.vue:46
-#: src/views/certificate/components/RenewCert.vue:53
+#: src/views/certificate/components/RenewCert.vue:48
+#: src/views/certificate/components/RenewCert.vue:55
 msgid "Renew Certificate"
 msgid "Renew Certificate"
 msgstr ""
 msgstr ""
 
 
@@ -3846,8 +3881,8 @@ msgstr ""
 msgid "Renew Certificate Success"
 msgid "Renew Certificate Success"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/components/RenewCert.vue:28
-#: src/views/certificate/components/WildcardCertificate.vue:46
+#: src/views/certificate/components/DNSIssueCertificate.vue:84
+#: src/views/certificate/components/RenewCert.vue:30
 msgid "Renew successfully"
 msgid "Renew successfully"
 msgstr ""
 msgstr ""
 
 
@@ -4101,7 +4136,7 @@ msgstr ""
 
 
 #: src/components/ChatGPT/ChatMessage.vue:215
 #: src/components/ChatGPT/ChatMessage.vue:215
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:129
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:129
-#: src/language/curd.ts:18 src/views/certificate/CertificateEditor.vue:266
+#: src/language/curd.ts:18 src/views/certificate/CertificateEditor.vue:264
 #: src/views/config/components/ConfigLeftPanel.vue:282
 #: src/views/config/components/ConfigLeftPanel.vue:282
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/preference/components/AuthSettings/Passkey.vue:130
 #: src/views/preference/components/AuthSettings/Passkey.vue:130
@@ -4156,7 +4191,7 @@ msgstr ""
 msgid "Save stream %{name} to %{node} successfully"
 msgid "Save stream %{name} to %{node} successfully"
 msgstr ""
 msgstr ""
 
 
-#: src/language/curd.ts:35 src/views/certificate/CertificateEditor.vue:49
+#: src/language/curd.ts:35 src/views/certificate/store.ts:13
 #: src/views/preference/store/index.ts:118
 #: src/views/preference/store/index.ts:118
 msgid "Save successfully"
 msgid "Save successfully"
 msgstr ""
 msgstr ""
@@ -4264,6 +4299,10 @@ msgstr ""
 msgid "Server"
 msgid "Server"
 msgstr ""
 msgstr ""
 
 
+#: src/views/certificate/CertificateEditor.vue:55
+msgid "Server error"
+msgstr ""
+
 #: src/views/dashboard/ServerAnalytic.vue:175
 #: src/views/dashboard/ServerAnalytic.vue:175
 msgid "Server Info"
 msgid "Server Info"
 msgstr ""
 msgstr ""
@@ -4394,7 +4433,7 @@ msgstr ""
 msgid "Sleep time between cache manager iterations"
 msgid "Sleep time between cache manager iterations"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/CertificateEditor.vue:213
+#: src/views/certificate/CertificateEditor.vue:211
 msgid "SSL Certificate Content"
 msgid "SSL Certificate Content"
 msgstr ""
 msgstr ""
 
 
@@ -4406,15 +4445,15 @@ msgstr ""
 msgid "SSL certificate file not found"
 msgid "SSL certificate file not found"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/CertificateEditor.vue:227
+#: src/views/certificate/CertificateEditor.vue:225
 msgid "SSL Certificate Key Content"
 msgid "SSL Certificate Key Content"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/CertificateEditor.vue:192
+#: src/views/certificate/CertificateEditor.vue:190
 msgid "SSL Certificate Key Path"
 msgid "SSL Certificate Key Path"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/CertificateEditor.vue:177
+#: src/views/certificate/CertificateEditor.vue:175
 #: src/views/preference/tabs/ServerSettings.vue:37
 #: src/views/preference/tabs/ServerSettings.vue:37
 msgid "SSL Certificate Path"
 msgid "SSL Certificate Path"
 msgstr ""
 msgstr ""
@@ -4641,7 +4680,7 @@ msgstr ""
 msgid "Sync strategy"
 msgid "Sync strategy"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/CertificateEditor.vue:206
+#: src/views/certificate/CertificateEditor.vue:204
 msgid "Sync to"
 msgid "Sync to"
 msgstr ""
 msgstr ""
 
 
@@ -4712,11 +4751,11 @@ msgid ""
 "dashes, colons, and dots."
 "dashes, colons, and dots."
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/CertificateEditor.vue:216
+#: src/views/certificate/CertificateEditor.vue:214
 msgid "The input is not a SSL Certificate"
 msgid "The input is not a SSL Certificate"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/CertificateEditor.vue:230
+#: src/views/certificate/CertificateEditor.vue:228
 msgid "The input is not a SSL Certificate Key"
 msgid "The input is not a SSL Certificate Key"
 msgstr ""
 msgstr ""
 
 
@@ -4747,11 +4786,11 @@ msgstr ""
 msgid "The parameter of server_name is required"
 msgid "The parameter of server_name is required"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/CertificateEditor.vue:181
+#: src/views/certificate/CertificateEditor.vue:179
 msgid "The path exists, but the file is not a certificate"
 msgid "The path exists, but the file is not a certificate"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/CertificateEditor.vue:196
+#: src/views/certificate/CertificateEditor.vue:194
 msgid "The path exists, but the file is not a private key"
 msgid "The path exists, but the file is not a private key"
 msgstr ""
 msgstr ""
 
 
@@ -4803,17 +4842,17 @@ msgid ""
 "lose access to your account."
 "lose access to your account."
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/CertificateEditor.vue:102
+#: src/views/certificate/CertificateEditor.vue:100
 msgid "This Auto Cert item is invalid, please remove it."
 msgid "This Auto Cert item is invalid, please remove it."
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/CertificateEditor.vue:92
+#: src/views/certificate/CertificateEditor.vue:90
 msgid "This certificate is managed by Nginx UI"
 msgid "This certificate is managed by Nginx UI"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/CertificateEditor.vue:165
-#: src/views/certificate/CertificateEditor.vue:179
-#: src/views/certificate/CertificateEditor.vue:194
+#: src/views/certificate/CertificateEditor.vue:163
+#: src/views/certificate/CertificateEditor.vue:177
+#: src/views/certificate/CertificateEditor.vue:192
 msgid "This field is required"
 msgid "This field is required"
 msgstr ""
 msgstr ""
 
 
@@ -5252,6 +5291,10 @@ msgstr ""
 msgid "Whether to use a temporary path when writing temporary files"
 msgid "Whether to use a temporary path when writing temporary files"
 msgstr ""
 msgstr ""
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:107
+msgid "Wildcard Certificate"
+msgstr ""
+
 #: src/views/dashboard/components/ParamsOpt/PerformanceConfig.vue:48
 #: src/views/dashboard/components/ParamsOpt/PerformanceConfig.vue:48
 msgid "Worker Connections"
 msgid "Worker Connections"
 msgstr ""
 msgstr ""

+ 84 - 42
app/src/language/es/app.po

@@ -187,6 +187,10 @@ msgstr "Agregar configuración"
 msgid "Add Directive Below"
 msgid "Add Directive Below"
 msgstr "Añadir directiva a continuación"
 msgstr "Añadir directiva a continuación"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:151
+msgid "Add Domain"
+msgstr "Agregar dominio"
+
 #: src/components/NgxConfigEditor/LocationEditor.vue:131
 #: src/components/NgxConfigEditor/LocationEditor.vue:131
 #: src/components/NgxConfigEditor/LocationEditor.vue:158
 #: src/components/NgxConfigEditor/LocationEditor.vue:158
 msgid "Add Location"
 msgid "Add Location"
@@ -236,6 +240,14 @@ msgstr "Todos"
 msgid "All Recovery Codes Have Been Used"
 msgid "All Recovery Codes Have Been Used"
 msgstr "Todos los códigos de recuperación han sido utilizados"
 msgstr "Todos los códigos de recuperación han sido utilizados"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:156
+msgid ""
+"All selected subdomains must belong to the same DNS Provider, otherwise the "
+"certificate application will fail."
+msgstr ""
+"Todos los subdominios seleccionados deben pertenecer al mismo proveedor de "
+"DNS, de lo contrario, la solicitud de certificado fallará."
+
 #: src/views/preference/tabs/OpenAISettings.vue:32
 #: src/views/preference/tabs/OpenAISettings.vue:32
 msgid "API Base Url"
 msgid "API Base Url"
 msgstr "URL Base de la API"
 msgstr "URL Base de la API"
@@ -262,7 +274,7 @@ msgstr "Aplicación"
 
 
 #: src/views/system/Upgrade.vue:195
 #: src/views/system/Upgrade.vue:195
 msgid "Arch"
 msgid "Arch"
-msgstr "\"Arquitectura\""
+msgstr "Arquitectura"
 
 
 #: src/views/preference/tabs/AuthSettings.vue:130
 #: src/views/preference/tabs/AuthSettings.vue:130
 msgid "Are you sure to delete this banned IP immediately?"
 msgid "Are you sure to delete this banned IP immediately?"
@@ -401,7 +413,7 @@ msgstr "Renovación automática deshabilitada por %{name}"
 msgid "Auto-renewal enabled for %{name}"
 msgid "Auto-renewal enabled for %{name}"
 msgstr "Renovación automática habilitada por %{name}"
 msgstr "Renovación automática habilitada por %{name}"
 
 
-#: src/views/certificate/components/RenewCert.vue:49
+#: src/views/certificate/components/RenewCert.vue:51
 #: src/views/site/site_edit/components/Cert/IssueCert.vue:84
 #: src/views/site/site_edit/components/Cert/IssueCert.vue:84
 msgid "AutoCert is running, please wait..."
 msgid "AutoCert is running, please wait..."
 msgstr "AutoCert se está ejecutando, por favor espere..."
 msgstr "AutoCert se está ejecutando, por favor espere..."
@@ -414,7 +426,7 @@ msgstr "\"AutoCert se está ejecutando...\""
 msgid "Automatic Restart"
 msgid "Automatic Restart"
 msgstr "\"Reinicio Automático\""
 msgstr "\"Reinicio Automático\""
 
 
-#: src/views/certificate/CertificateEditor.vue:259
+#: src/views/certificate/CertificateEditor.vue:257
 #: src/views/config/components/ConfigLeftPanel.vue:273
 #: src/views/config/components/ConfigLeftPanel.vue:273
 #: src/views/config/ConfigList.vue:112 src/views/config/ConfigList.vue:195
 #: src/views/config/ConfigList.vue:112 src/views/config/ConfigList.vue:195
 #: src/views/nginx_log/NginxLog.vue:174
 #: src/views/nginx_log/NginxLog.vue:174
@@ -723,13 +735,17 @@ msgstr "Certificado renovado con éxito"
 msgid "Certificate revoked successfully"
 msgid "Certificate revoked successfully"
 msgstr "Certificado revocado con éxito"
 msgstr "Certificado revocado con éxito"
 
 
-#: src/views/certificate/CertificateEditor.vue:128
+#: src/views/certificate/CertificateEditor.vue:126
 #: src/views/site/site_edit/components/Cert/Cert.vue:58
 #: src/views/site/site_edit/components/Cert/Cert.vue:58
 msgid "Certificate Status"
 msgid "Certificate Status"
 msgid_plural "Certificates Status"
 msgid_plural "Certificates Status"
 msgstr[0] "Estado del Certificado"
 msgstr[0] "Estado del Certificado"
 msgstr[1] "Estado de los Certificados"
 msgstr[1] "Estado de los Certificados"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:104
+msgid "Certificate Type"
+msgstr "Tipo de certificado"
+
 #: src/routes/modules/certificates.ts:11
 #: src/routes/modules/certificates.ts:11
 #: src/views/certificate/CertificateList/Certificate.vue:19
 #: src/views/certificate/CertificateList/Certificate.vue:19
 msgid "Certificates"
 msgid "Certificates"
@@ -1219,6 +1235,14 @@ msgstr "Expresión cron personalizada"
 msgid "Custom Directory"
 msgid "Custom Directory"
 msgstr "Directorio personalizado"
 msgstr "Directorio personalizado"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:126
+msgid "Custom Domains"
+msgstr "Dominios personalizados"
+
+#: src/views/certificate/components/DNSIssueCertificate.vue:110
+msgid "Custom Domains Certificate"
+msgstr "Certificado de Dominios Personalizados"
+
 #: src/views/preference/tabs/NodeSettings.vue:19
 #: src/views/preference/tabs/NodeSettings.vue:19
 msgid ""
 msgid ""
 "Customize the name of local node to be displayed in the environment "
 "Customize the name of local node to be displayed in the environment "
@@ -1530,11 +1554,11 @@ msgid "Document"
 msgid_plural "Documents"
 msgid_plural "Documents"
 msgstr[0] "Documento"
 msgstr[0] "Documento"
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:66
+#: src/views/certificate/components/DNSIssueCertificate.vue:116
 msgid "Domain"
 msgid "Domain"
 msgstr "Dominio"
 msgstr "Dominio"
 
 
-#: src/views/certificate/CertificateEditor.vue:112
+#: src/views/certificate/CertificateEditor.vue:110
 msgid "Domains list is empty, try to reopen Auto Cert for %{config}"
 msgid "Domains list is empty, try to reopen Auto Cert for %{config}"
 msgstr ""
 msgstr ""
 "La lista de dominios está vacía, intente reabrir la certificación "
 "La lista de dominios está vacía, intente reabrir la certificación "
@@ -1739,6 +1763,14 @@ msgstr "Encriptar sitio web con Let's Encrypt"
 msgid "End"
 msgid "End"
 msgstr "Fin"
 msgstr "Fin"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:135
+msgid "Enter domain name"
+msgstr "Ingresar nombre de dominio"
+
+#: src/views/certificate/components/DNSIssueCertificate.vue:120
+msgid "Enter your domain"
+msgstr "Ingrese su dominio"
+
 #: src/language/constants.ts:22
 #: src/language/constants.ts:22
 msgid "Environment variables cleaned"
 msgid "Environment variables cleaned"
 msgstr "Variables de entorno limpiadas"
 msgstr "Variables de entorno limpiadas"
@@ -1813,7 +1845,7 @@ msgstr "Contenedor Docker externo"
 msgid "External Notify"
 msgid "External Notify"
 msgstr "Notificación Externa"
 msgstr "Notificación Externa"
 
 
-#: src/views/site/site_edit/components/Cert/ObtainCertLive.vue:80
+#: src/views/site/site_edit/components/Cert/ObtainCertLive.vue:81
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
 msgstr "Falla al obtener el certificado"
 msgstr "Falla al obtener el certificado"
 
 
@@ -2343,7 +2375,7 @@ msgid "Import"
 msgstr "Importar"
 msgstr "Importar"
 
 
 #: src/routes/modules/certificates.ts:46
 #: src/routes/modules/certificates.ts:46
-#: src/views/certificate/CertificateEditor.vue:85
+#: src/views/certificate/CertificateEditor.vue:83
 msgid "Import Certificate"
 msgid "Import Certificate"
 msgstr "Importar Certificado"
 msgstr "Importar Certificado"
 
 
@@ -2488,12 +2520,12 @@ msgid "IP"
 msgstr "IP"
 msgstr "IP"
 
 
 #: src/views/certificate/CertificateList/Certificate.vue:37
 #: src/views/certificate/CertificateList/Certificate.vue:37
-msgid "Issue wildcard certificate"
-msgstr "Obtener certificado comodín"
+msgid "Issue certificate"
+msgstr "Emitir certificado"
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:57
-msgid "Issue Wildcard Certificate"
-msgstr "Obtener certificado Comodín"
+#: src/views/certificate/components/DNSIssueCertificate.vue:95
+msgid "Issue Certificate"
+msgstr "Emitir certificado"
 
 
 #: src/language/constants.ts:20
 #: src/language/constants.ts:20
 msgid "Issued certificate successfully"
 msgid "Issued certificate successfully"
@@ -2576,8 +2608,8 @@ msgstr "Dejar en blanco si no desea modificar"
 msgid "Leave blank if you don't need this."
 msgid "Leave blank if you don't need this."
 msgstr "Déjelo en blanco si no lo necesita."
 msgstr "Déjelo en blanco si no lo necesita."
 
 
-#: src/views/certificate/CertificateEditor.vue:223
-#: src/views/certificate/CertificateEditor.vue:237
+#: src/views/certificate/CertificateEditor.vue:221
+#: src/views/certificate/CertificateEditor.vue:235
 msgid "Leave blank will not change anything"
 msgid "Leave blank will not change anything"
 msgstr "Dejarlo en blanco no cambiará nada"
 msgstr "Dejarlo en blanco no cambiará nada"
 
 
@@ -2664,7 +2696,7 @@ msgstr "Ubicación"
 msgid "Locations"
 msgid "Locations"
 msgstr "Ubicaciones"
 msgstr "Ubicaciones"
 
 
-#: src/views/certificate/CertificateEditor.vue:247
+#: src/views/certificate/CertificateEditor.vue:245
 msgid "Log"
 msgid "Log"
 msgstr "Registro"
 msgstr "Registro"
 
 
@@ -2879,7 +2911,7 @@ msgid "Modify"
 msgstr "Modificar"
 msgstr "Modificar"
 
 
 #: src/routes/modules/certificates.ts:36
 #: src/routes/modules/certificates.ts:36
-#: src/views/certificate/CertificateEditor.vue:85
+#: src/views/certificate/CertificateEditor.vue:83
 msgid "Modify Certificate"
 msgid "Modify Certificate"
 msgstr "Modificar Certificado"
 msgstr "Modificar Certificado"
 
 
@@ -2914,7 +2946,7 @@ msgstr "Directiva multilínea"
 #: src/components/NgxConfigEditor/NgxUpstream.vue:199
 #: src/components/NgxConfigEditor/NgxUpstream.vue:199
 #: src/views/backup/AutoBackup/AutoBackup.vue:11
 #: src/views/backup/AutoBackup/AutoBackup.vue:11
 #: src/views/certificate/ACMEUser.vue:11
 #: src/views/certificate/ACMEUser.vue:11
-#: src/views/certificate/CertificateEditor.vue:162
+#: src/views/certificate/CertificateEditor.vue:160
 #: src/views/certificate/CertificateList/certColumns.tsx:9
 #: src/views/certificate/CertificateList/certColumns.tsx:9
 #: src/views/certificate/DNSCredential.vue:9
 #: src/views/certificate/DNSCredential.vue:9
 #: src/views/config/components/ConfigRightPanel/Basic.vue:34
 #: src/views/config/components/ConfigRightPanel/Basic.vue:34
@@ -2974,7 +3006,7 @@ msgstr "Nueva ruta"
 msgid "New version released"
 msgid "New version released"
 msgstr "Se liberó una nueva versión"
 msgstr "Se liberó una nueva versión"
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:89
+#: src/views/certificate/components/DNSIssueCertificate.vue:181
 #: src/views/install/components/InstallView.vue:96
 #: src/views/install/components/InstallView.vue:96
 #: src/views/site/site_add/SiteAdd.vue:132
 #: src/views/site/site_add/SiteAdd.vue:132
 #: src/views/site/site_edit/components/Cert/ObtainCert.vue:214
 #: src/views/site/site_edit/components/Cert/ObtainCert.vue:214
@@ -3564,6 +3596,10 @@ msgstr ""
 msgid "Please enter a valid port range"
 msgid "Please enter a valid port range"
 msgstr "Por favor, introduzca un rango de puertos válido"
 msgstr "Por favor, introduzca un rango de puertos válido"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:74
+msgid "Please enter at least one domain"
+msgstr "Por favor, ingrese al menos un dominio"
+
 #: src/components/TwoFA/Authorization.vue:85
 #: src/components/TwoFA/Authorization.vue:85
 msgid "Please enter the OTP code:"
 msgid "Please enter the OTP code:"
 msgstr "Por favor, ingrese el código OTP:"
 msgstr "Por favor, ingrese el código OTP:"
@@ -3911,6 +3947,7 @@ msgstr "Recargando"
 msgid "Reloading nginx"
 msgid "Reloading nginx"
 msgstr "Recargando Nginx"
 msgstr "Recargando Nginx"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:144
 #: src/views/preference/tabs/AuthSettings.vue:137
 #: src/views/preference/tabs/AuthSettings.vue:137
 msgid "Remove"
 msgid "Remove"
 msgstr "Eliminar"
 msgstr "Eliminar"
@@ -3993,8 +4030,8 @@ msgstr "Renombrado con éxito"
 msgid "Renamed successfully"
 msgid "Renamed successfully"
 msgstr "Renombrado con éxito"
 msgstr "Renombrado con éxito"
 
 
-#: src/views/certificate/components/RenewCert.vue:46
-#: src/views/certificate/components/RenewCert.vue:53
+#: src/views/certificate/components/RenewCert.vue:48
+#: src/views/certificate/components/RenewCert.vue:55
 msgid "Renew Certificate"
 msgid "Renew Certificate"
 msgstr "Renovar Certificado"
 msgstr "Renovar Certificado"
 
 
@@ -4006,8 +4043,8 @@ msgstr "Error al renovar el Certificado"
 msgid "Renew Certificate Success"
 msgid "Renew Certificate Success"
 msgstr "Renovado de Certificado exitoso"
 msgstr "Renovado de Certificado exitoso"
 
 
-#: src/views/certificate/components/RenewCert.vue:28
-#: src/views/certificate/components/WildcardCertificate.vue:46
+#: src/views/certificate/components/DNSIssueCertificate.vue:84
+#: src/views/certificate/components/RenewCert.vue:30
 msgid "Renew successfully"
 msgid "Renew successfully"
 msgstr "Renovado con éxito"
 msgstr "Renovado con éxito"
 
 
@@ -4266,7 +4303,7 @@ msgstr "Sábado"
 
 
 #: src/components/ChatGPT/ChatMessage.vue:215
 #: src/components/ChatGPT/ChatMessage.vue:215
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:129
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:129
-#: src/language/curd.ts:18 src/views/certificate/CertificateEditor.vue:266
+#: src/language/curd.ts:18 src/views/certificate/CertificateEditor.vue:264
 #: src/views/config/components/ConfigLeftPanel.vue:282
 #: src/views/config/components/ConfigLeftPanel.vue:282
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/preference/components/AuthSettings/Passkey.vue:130
 #: src/views/preference/components/AuthSettings/Passkey.vue:130
@@ -4321,7 +4358,7 @@ msgstr "Error al guardar el flujo %{name} en %{node}"
 msgid "Save stream %{name} to %{node} successfully"
 msgid "Save stream %{name} to %{node} successfully"
 msgstr "Flujo %{name} guardado en %{node} correctamente"
 msgstr "Flujo %{name} guardado en %{node} correctamente"
 
 
-#: src/language/curd.ts:35 src/views/certificate/CertificateEditor.vue:49
+#: src/language/curd.ts:35 src/views/certificate/store.ts:13
 #: src/views/preference/store/index.ts:118
 #: src/views/preference/store/index.ts:118
 msgid "Save successfully"
 msgid "Save successfully"
 msgstr "Guardado con éxito"
 msgstr "Guardado con éxito"
@@ -4433,6 +4470,10 @@ msgstr "Enviado"
 msgid "Server"
 msgid "Server"
 msgstr "Servidor"
 msgstr "Servidor"
 
 
+#: src/views/certificate/CertificateEditor.vue:55
+msgid "Server error"
+msgstr "Error del servidor"
+
 #: src/views/dashboard/ServerAnalytic.vue:175
 #: src/views/dashboard/ServerAnalytic.vue:175
 msgid "Server Info"
 msgid "Server Info"
 msgstr "Información del servidor"
 msgstr "Información del servidor"
@@ -4569,7 +4610,7 @@ msgstr "Tiempo de espera entre iteraciones del cargador de caché"
 msgid "Sleep time between cache manager iterations"
 msgid "Sleep time between cache manager iterations"
 msgstr "Tiempo de espera entre iteraciones del administrador de caché"
 msgstr "Tiempo de espera entre iteraciones del administrador de caché"
 
 
-#: src/views/certificate/CertificateEditor.vue:213
+#: src/views/certificate/CertificateEditor.vue:211
 msgid "SSL Certificate Content"
 msgid "SSL Certificate Content"
 msgstr "Contenido de certificado SSL"
 msgstr "Contenido de certificado SSL"
 
 
@@ -4583,15 +4624,15 @@ msgstr ""
 msgid "SSL certificate file not found"
 msgid "SSL certificate file not found"
 msgstr "Archivo de certificado SSL no encontrado"
 msgstr "Archivo de certificado SSL no encontrado"
 
 
-#: src/views/certificate/CertificateEditor.vue:227
+#: src/views/certificate/CertificateEditor.vue:225
 msgid "SSL Certificate Key Content"
 msgid "SSL Certificate Key Content"
 msgstr "Contenido de la llave del certificado SSL"
 msgstr "Contenido de la llave del certificado SSL"
 
 
-#: src/views/certificate/CertificateEditor.vue:192
+#: src/views/certificate/CertificateEditor.vue:190
 msgid "SSL Certificate Key Path"
 msgid "SSL Certificate Key Path"
 msgstr "Ruta de la llave del certificado SSL"
 msgstr "Ruta de la llave del certificado SSL"
 
 
-#: src/views/certificate/CertificateEditor.vue:177
+#: src/views/certificate/CertificateEditor.vue:175
 #: src/views/preference/tabs/ServerSettings.vue:37
 #: src/views/preference/tabs/ServerSettings.vue:37
 msgid "SSL Certificate Path"
 msgid "SSL Certificate Path"
 msgstr "Ruta del certificado SSL"
 msgstr "Ruta del certificado SSL"
@@ -4831,7 +4872,7 @@ msgstr "Nodos de sincronización"
 msgid "Sync strategy"
 msgid "Sync strategy"
 msgstr "Estrategia de sincronización"
 msgstr "Estrategia de sincronización"
 
 
-#: src/views/certificate/CertificateEditor.vue:206
+#: src/views/certificate/CertificateEditor.vue:204
 msgid "Sync to"
 msgid "Sync to"
 msgstr "Sincronizar con"
 msgstr "Sincronizar con"
 
 
@@ -4907,11 +4948,11 @@ msgstr ""
 "El número ICP solo debe contener letras, unicode, números, guiones, guiones "
 "El número ICP solo debe contener letras, unicode, números, guiones, guiones "
 "bajos, dos puntos y puntos."
 "bajos, dos puntos y puntos."
 
 
-#: src/views/certificate/CertificateEditor.vue:216
+#: src/views/certificate/CertificateEditor.vue:214
 msgid "The input is not a SSL Certificate"
 msgid "The input is not a SSL Certificate"
 msgstr "La entrada no es un Certificado SSL"
 msgstr "La entrada no es un Certificado SSL"
 
 
-#: src/views/certificate/CertificateEditor.vue:230
+#: src/views/certificate/CertificateEditor.vue:228
 msgid "The input is not a SSL Certificate Key"
 msgid "The input is not a SSL Certificate Key"
 msgstr "La entrada no es una clave de certificado SSL"
 msgstr "La entrada no es una clave de certificado SSL"
 
 
@@ -4950,11 +4991,11 @@ msgstr ""
 msgid "The parameter of server_name is required"
 msgid "The parameter of server_name is required"
 msgstr "El parámetro de server_name es obligatorio"
 msgstr "El parámetro de server_name es obligatorio"
 
 
-#: src/views/certificate/CertificateEditor.vue:181
+#: src/views/certificate/CertificateEditor.vue:179
 msgid "The path exists, but the file is not a certificate"
 msgid "The path exists, but the file is not a certificate"
 msgstr "La ruta existe, pero el archivo no es un certificado"
 msgstr "La ruta existe, pero el archivo no es un certificado"
 
 
-#: src/views/certificate/CertificateEditor.vue:196
+#: src/views/certificate/CertificateEditor.vue:194
 msgid "The path exists, but the file is not a private key"
 msgid "The path exists, but the file is not a private key"
 msgstr "La ruta existe, pero el archivo no es una clave privada"
 msgstr "La ruta existe, pero el archivo no es una clave privada"
 
 
@@ -5016,17 +5057,17 @@ msgstr ""
 "pierda su contraseña y los segundos factores. Si no puede encontrar estos "
 "pierda su contraseña y los segundos factores. Si no puede encontrar estos "
 "códigos, perderá el acceso a su cuenta."
 "códigos, perderá el acceso a su cuenta."
 
 
-#: src/views/certificate/CertificateEditor.vue:102
+#: src/views/certificate/CertificateEditor.vue:100
 msgid "This Auto Cert item is invalid, please remove it."
 msgid "This Auto Cert item is invalid, please remove it."
 msgstr "Este elemento de Auto Cert es inválido, elimínelo por favor."
 msgstr "Este elemento de Auto Cert es inválido, elimínelo por favor."
 
 
-#: src/views/certificate/CertificateEditor.vue:92
+#: src/views/certificate/CertificateEditor.vue:90
 msgid "This certificate is managed by Nginx UI"
 msgid "This certificate is managed by Nginx UI"
 msgstr "Este certificado es administrado por Nginx UI"
 msgstr "Este certificado es administrado por Nginx UI"
 
 
-#: src/views/certificate/CertificateEditor.vue:165
-#: src/views/certificate/CertificateEditor.vue:179
-#: src/views/certificate/CertificateEditor.vue:194
+#: src/views/certificate/CertificateEditor.vue:163
+#: src/views/certificate/CertificateEditor.vue:177
+#: src/views/certificate/CertificateEditor.vue:192
 msgid "This field is required"
 msgid "This field is required"
 msgstr "Este campo es obligatorio"
 msgstr "Este campo es obligatorio"
 
 
@@ -5509,6 +5550,10 @@ msgstr ""
 msgid "Whether to use a temporary path when writing temporary files"
 msgid "Whether to use a temporary path when writing temporary files"
 msgstr "Si se debe usar una ruta temporal al escribir archivos temporales"
 msgstr "Si se debe usar una ruta temporal al escribir archivos temporales"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:107
+msgid "Wildcard Certificate"
+msgstr "Certificado comodín"
+
 #: src/views/dashboard/components/ParamsOpt/PerformanceConfig.vue:48
 #: src/views/dashboard/components/ParamsOpt/PerformanceConfig.vue:48
 msgid "Worker Connections"
 msgid "Worker Connections"
 msgstr "Conexiones de trabajador"
 msgstr "Conexiones de trabajador"
@@ -5851,9 +5896,6 @@ msgstr "Sus llaves de acceso"
 #~ msgid "Recovery Code:"
 #~ msgid "Recovery Code:"
 #~ msgstr "Código de Recuperación:"
 #~ msgstr "Código de Recuperación:"
 
 
-#~ msgid "Server error"
-#~ msgstr "Error del servidor"
-
 #~ msgid "The recovery code is only displayed once, please save it in a safe place."
 #~ msgid "The recovery code is only displayed once, please save it in a safe place."
 #~ msgstr ""
 #~ msgstr ""
 #~ "El código de recuperación se muestra solo una vez, por favor guárdalo en un "
 #~ "El código de recuperación se muestra solo una vez, por favor guárdalo en un "

+ 84 - 42
app/src/language/fr_FR/app.po

@@ -185,6 +185,10 @@ msgstr "Ajouter une configuration"
 msgid "Add Directive Below"
 msgid "Add Directive Below"
 msgstr "Ajouter une directive"
 msgstr "Ajouter une directive"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:151
+msgid "Add Domain"
+msgstr "Ajouter un domaine"
+
 #: src/components/NgxConfigEditor/LocationEditor.vue:131
 #: src/components/NgxConfigEditor/LocationEditor.vue:131
 #: src/components/NgxConfigEditor/LocationEditor.vue:158
 #: src/components/NgxConfigEditor/LocationEditor.vue:158
 msgid "Add Location"
 msgid "Add Location"
@@ -234,6 +238,14 @@ msgstr "Tous"
 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"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:156
+msgid ""
+"All selected subdomains must belong to the same DNS Provider, otherwise the "
+"certificate application will fail."
+msgstr ""
+"Tous les sous-domaines sélectionnés doivent appartenir au même fournisseur "
+"DNS, sinon la demande de certificat échouera."
+
 #: src/views/preference/tabs/OpenAISettings.vue:32
 #: src/views/preference/tabs/OpenAISettings.vue:32
 msgid "API Base Url"
 msgid "API Base Url"
 msgstr "URL de base de l'API"
 msgstr "URL de base de l'API"
@@ -260,7 +272,7 @@ msgstr "Application"
 
 
 #: src/views/system/Upgrade.vue:195
 #: src/views/system/Upgrade.vue:195
 msgid "Arch"
 msgid "Arch"
-msgstr "\"Arch\""
+msgstr "Arch"
 
 
 #: src/views/preference/tabs/AuthSettings.vue:130
 #: src/views/preference/tabs/AuthSettings.vue:130
 msgid "Are you sure to delete this banned IP immediately?"
 msgid "Are you sure to delete this banned IP immediately?"
@@ -399,7 +411,7 @@ msgstr "Renouvellement automatique désactivé pour %{name}"
 msgid "Auto-renewal enabled for %{name}"
 msgid "Auto-renewal enabled for %{name}"
 msgstr "Renouvellement automatique activé pour %{name}"
 msgstr "Renouvellement automatique activé pour %{name}"
 
 
-#: src/views/certificate/components/RenewCert.vue:49
+#: src/views/certificate/components/RenewCert.vue:51
 #: src/views/site/site_edit/components/Cert/IssueCert.vue:84
 #: src/views/site/site_edit/components/Cert/IssueCert.vue:84
 msgid "AutoCert is running, please wait..."
 msgid "AutoCert is running, please wait..."
 msgstr "AutoCert est en cours d'exécution, veuillez patienter..."
 msgstr "AutoCert est en cours d'exécution, veuillez patienter..."
@@ -412,7 +424,7 @@ msgstr "\"AutoCert est en cours d'exécution...\""
 msgid "Automatic Restart"
 msgid "Automatic Restart"
 msgstr "\"Redémarrage Automatique\""
 msgstr "\"Redémarrage Automatique\""
 
 
-#: src/views/certificate/CertificateEditor.vue:259
+#: src/views/certificate/CertificateEditor.vue:257
 #: src/views/config/components/ConfigLeftPanel.vue:273
 #: src/views/config/components/ConfigLeftPanel.vue:273
 #: src/views/config/ConfigList.vue:112 src/views/config/ConfigList.vue:195
 #: src/views/config/ConfigList.vue:112 src/views/config/ConfigList.vue:195
 #: src/views/nginx_log/NginxLog.vue:174
 #: src/views/nginx_log/NginxLog.vue:174
@@ -716,12 +728,16 @@ msgstr "Certificat renouvelé avec succès"
 msgid "Certificate revoked successfully"
 msgid "Certificate revoked successfully"
 msgstr "Certificat révoqué avec succès"
 msgstr "Certificat révoqué avec succès"
 
 
-#: src/views/certificate/CertificateEditor.vue:128
+#: src/views/certificate/CertificateEditor.vue:126
 #: src/views/site/site_edit/components/Cert/Cert.vue:58
 #: src/views/site/site_edit/components/Cert/Cert.vue:58
 msgid "Certificate Status"
 msgid "Certificate Status"
 msgid_plural "Certificates Status"
 msgid_plural "Certificates Status"
 msgstr[0] "État du certificat"
 msgstr[0] "État du certificat"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:104
+msgid "Certificate Type"
+msgstr "Type de certificat"
+
 #: src/routes/modules/certificates.ts:11
 #: src/routes/modules/certificates.ts:11
 #: src/views/certificate/CertificateList/Certificate.vue:19
 #: src/views/certificate/CertificateList/Certificate.vue:19
 msgid "Certificates"
 msgid "Certificates"
@@ -1215,6 +1231,14 @@ msgstr "Expression cron personnalisée"
 msgid "Custom Directory"
 msgid "Custom Directory"
 msgstr "Répertoire personnalisé"
 msgstr "Répertoire personnalisé"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:126
+msgid "Custom Domains"
+msgstr "Domaines personnalisés"
+
+#: src/views/certificate/components/DNSIssueCertificate.vue:110
+msgid "Custom Domains Certificate"
+msgstr "Certificat de domaines personnalisés"
+
 #: src/views/preference/tabs/NodeSettings.vue:19
 #: src/views/preference/tabs/NodeSettings.vue:19
 msgid ""
 msgid ""
 "Customize the name of local node to be displayed in the environment "
 "Customize the name of local node to be displayed in the environment "
@@ -1526,11 +1550,11 @@ msgid "Document"
 msgid_plural "Documents"
 msgid_plural "Documents"
 msgstr[0] "Document"
 msgstr[0] "Document"
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:66
+#: src/views/certificate/components/DNSIssueCertificate.vue:116
 msgid "Domain"
 msgid "Domain"
 msgstr "Domaine"
 msgstr "Domaine"
 
 
-#: src/views/certificate/CertificateEditor.vue:112
+#: src/views/certificate/CertificateEditor.vue:110
 msgid "Domains list is empty, try to reopen Auto Cert for %{config}"
 msgid "Domains list is empty, try to reopen Auto Cert for %{config}"
 msgstr "La liste des domaines est vide, essayez de rouvrir Auto Cert pour %{config}"
 msgstr "La liste des domaines est vide, essayez de rouvrir Auto Cert pour %{config}"
 
 
@@ -1733,6 +1757,14 @@ msgstr "Crypter le site Web avec Let's Encrypt"
 msgid "End"
 msgid "End"
 msgstr "Fin"
 msgstr "Fin"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:135
+msgid "Enter domain name"
+msgstr "Entrez le nom de domaine"
+
+#: src/views/certificate/components/DNSIssueCertificate.vue:120
+msgid "Enter your domain"
+msgstr "Entrez votre domaine"
+
 #: src/language/constants.ts:22
 #: src/language/constants.ts:22
 msgid "Environment variables cleaned"
 msgid "Environment variables cleaned"
 msgstr "Variables d'environnement nettoyées"
 msgstr "Variables d'environnement nettoyées"
@@ -1807,7 +1839,7 @@ msgstr "Conteneur Docker externe"
 msgid "External Notify"
 msgid "External Notify"
 msgstr "Notification Externe"
 msgstr "Notification Externe"
 
 
-#: src/views/site/site_edit/components/Cert/ObtainCertLive.vue:80
+#: src/views/site/site_edit/components/Cert/ObtainCertLive.vue:81
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
 msgstr "Échec de l'obtention du certificat"
 msgstr "Échec de l'obtention du certificat"
 
 
@@ -2341,7 +2373,7 @@ msgid "Import"
 msgstr "Importer"
 msgstr "Importer"
 
 
 #: src/routes/modules/certificates.ts:46
 #: src/routes/modules/certificates.ts:46
-#: src/views/certificate/CertificateEditor.vue:85
+#: src/views/certificate/CertificateEditor.vue:83
 msgid "Import Certificate"
 msgid "Import Certificate"
 msgstr "Importer un certificat"
 msgstr "Importer un certificat"
 
 
@@ -2486,12 +2518,12 @@ msgid "IP"
 msgstr "IP"
 msgstr "IP"
 
 
 #: src/views/certificate/CertificateList/Certificate.vue:37
 #: src/views/certificate/CertificateList/Certificate.vue:37
-msgid "Issue wildcard certificate"
-msgstr "Émettre un certificat générique"
+msgid "Issue certificate"
+msgstr "Émettre un certificat"
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:57
-msgid "Issue Wildcard Certificate"
-msgstr "Émettre un certificat générique"
+#: src/views/certificate/components/DNSIssueCertificate.vue:95
+msgid "Issue Certificate"
+msgstr "Émettre un certificat"
 
 
 #: src/language/constants.ts:20
 #: src/language/constants.ts:20
 msgid "Issued certificate successfully"
 msgid "Issued certificate successfully"
@@ -2574,8 +2606,8 @@ msgstr "Laisser vide si vous ne souhaitez pas modifier"
 msgid "Leave blank if you don't need this."
 msgid "Leave blank if you don't need this."
 msgstr "Laissez vide si vous n'en avez pas besoin."
 msgstr "Laissez vide si vous n'en avez pas besoin."
 
 
-#: src/views/certificate/CertificateEditor.vue:223
-#: src/views/certificate/CertificateEditor.vue:237
+#: src/views/certificate/CertificateEditor.vue:221
+#: src/views/certificate/CertificateEditor.vue:235
 msgid "Leave blank will not change anything"
 msgid "Leave blank will not change anything"
 msgstr "Laisser vide ne changera rien"
 msgstr "Laisser vide ne changera rien"
 
 
@@ -2662,7 +2694,7 @@ msgstr "Emplacement"
 msgid "Locations"
 msgid "Locations"
 msgstr "Emplacements"
 msgstr "Emplacements"
 
 
-#: src/views/certificate/CertificateEditor.vue:247
+#: src/views/certificate/CertificateEditor.vue:245
 msgid "Log"
 msgid "Log"
 msgstr "Journal"
 msgstr "Journal"
 
 
@@ -2877,7 +2909,7 @@ msgid "Modify"
 msgstr "Modifier"
 msgstr "Modifier"
 
 
 #: src/routes/modules/certificates.ts:36
 #: src/routes/modules/certificates.ts:36
-#: src/views/certificate/CertificateEditor.vue:85
+#: src/views/certificate/CertificateEditor.vue:83
 msgid "Modify Certificate"
 msgid "Modify Certificate"
 msgstr "Modifier le certificat"
 msgstr "Modifier le certificat"
 
 
@@ -2912,7 +2944,7 @@ msgstr "Directive multiligne"
 #: src/components/NgxConfigEditor/NgxUpstream.vue:199
 #: src/components/NgxConfigEditor/NgxUpstream.vue:199
 #: src/views/backup/AutoBackup/AutoBackup.vue:11
 #: src/views/backup/AutoBackup/AutoBackup.vue:11
 #: src/views/certificate/ACMEUser.vue:11
 #: src/views/certificate/ACMEUser.vue:11
-#: src/views/certificate/CertificateEditor.vue:162
+#: src/views/certificate/CertificateEditor.vue:160
 #: src/views/certificate/CertificateList/certColumns.tsx:9
 #: src/views/certificate/CertificateList/certColumns.tsx:9
 #: src/views/certificate/DNSCredential.vue:9
 #: src/views/certificate/DNSCredential.vue:9
 #: src/views/config/components/ConfigRightPanel/Basic.vue:34
 #: src/views/config/components/ConfigRightPanel/Basic.vue:34
@@ -2972,7 +3004,7 @@ msgstr "Nouveau chemin"
 msgid "New version released"
 msgid "New version released"
 msgstr "Nouvelle version publiée"
 msgstr "Nouvelle version publiée"
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:89
+#: src/views/certificate/components/DNSIssueCertificate.vue:181
 #: src/views/install/components/InstallView.vue:96
 #: src/views/install/components/InstallView.vue:96
 #: src/views/site/site_add/SiteAdd.vue:132
 #: src/views/site/site_add/SiteAdd.vue:132
 #: src/views/site/site_edit/components/Cert/ObtainCert.vue:214
 #: src/views/site/site_edit/components/Cert/ObtainCert.vue:214
@@ -3563,6 +3595,10 @@ msgstr ""
 msgid "Please enter a valid port range"
 msgid "Please enter a valid port range"
 msgstr "Veuillez entrer une plage de ports valide"
 msgstr "Veuillez entrer une plage de ports valide"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:74
+msgid "Please enter at least one domain"
+msgstr "Veuillez saisir au moins un domaine"
+
 #: src/components/TwoFA/Authorization.vue:85
 #: src/components/TwoFA/Authorization.vue:85
 msgid "Please enter the OTP code:"
 msgid "Please enter the OTP code:"
 msgstr "Veuillez entrer le code OTP :"
 msgstr "Veuillez entrer le code OTP :"
@@ -3910,6 +3946,7 @@ msgstr "Rechargement"
 msgid "Reloading nginx"
 msgid "Reloading nginx"
 msgstr "Rechargement de nginx"
 msgstr "Rechargement de nginx"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:144
 #: src/views/preference/tabs/AuthSettings.vue:137
 #: src/views/preference/tabs/AuthSettings.vue:137
 msgid "Remove"
 msgid "Remove"
 msgstr "Supprimer"
 msgstr "Supprimer"
@@ -3992,8 +4029,8 @@ msgstr "Renommage réussi"
 msgid "Renamed successfully"
 msgid "Renamed successfully"
 msgstr "Renommé avec succès"
 msgstr "Renommé avec succès"
 
 
-#: src/views/certificate/components/RenewCert.vue:46
-#: src/views/certificate/components/RenewCert.vue:53
+#: src/views/certificate/components/RenewCert.vue:48
+#: src/views/certificate/components/RenewCert.vue:55
 msgid "Renew Certificate"
 msgid "Renew Certificate"
 msgstr "Renouveler le certificat"
 msgstr "Renouveler le certificat"
 
 
@@ -4005,8 +4042,8 @@ msgstr "Erreur de renouvellement du certificat"
 msgid "Renew Certificate Success"
 msgid "Renew Certificate Success"
 msgstr "Renouvellement du certificat réussi"
 msgstr "Renouvellement du certificat réussi"
 
 
-#: src/views/certificate/components/RenewCert.vue:28
-#: src/views/certificate/components/WildcardCertificate.vue:46
+#: src/views/certificate/components/DNSIssueCertificate.vue:84
+#: src/views/certificate/components/RenewCert.vue:30
 msgid "Renew successfully"
 msgid "Renew successfully"
 msgstr "Renouvellement réussi"
 msgstr "Renouvellement réussi"
 
 
@@ -4265,7 +4302,7 @@ msgstr "Samedi"
 
 
 #: src/components/ChatGPT/ChatMessage.vue:215
 #: src/components/ChatGPT/ChatMessage.vue:215
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:129
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:129
-#: src/language/curd.ts:18 src/views/certificate/CertificateEditor.vue:266
+#: src/language/curd.ts:18 src/views/certificate/CertificateEditor.vue:264
 #: src/views/config/components/ConfigLeftPanel.vue:282
 #: src/views/config/components/ConfigLeftPanel.vue:282
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/preference/components/AuthSettings/Passkey.vue:130
 #: src/views/preference/components/AuthSettings/Passkey.vue:130
@@ -4320,7 +4357,7 @@ msgstr "Échec de l'enregistrement du flux %{name} sur %{node}"
 msgid "Save stream %{name} to %{node} successfully"
 msgid "Save stream %{name} to %{node} successfully"
 msgstr "Flux %{name} enregistré sur %{node} avec succès"
 msgstr "Flux %{name} enregistré sur %{node} avec succès"
 
 
-#: src/language/curd.ts:35 src/views/certificate/CertificateEditor.vue:49
+#: src/language/curd.ts:35 src/views/certificate/store.ts:13
 #: src/views/preference/store/index.ts:118
 #: src/views/preference/store/index.ts:118
 msgid "Save successfully"
 msgid "Save successfully"
 msgstr "Sauvegarde réussie"
 msgstr "Sauvegarde réussie"
@@ -4432,6 +4469,10 @@ msgstr "Envoyer"
 msgid "Server"
 msgid "Server"
 msgstr "Serveur"
 msgstr "Serveur"
 
 
+#: src/views/certificate/CertificateEditor.vue:55
+msgid "Server error"
+msgstr "Erreur du serveur"
+
 #: src/views/dashboard/ServerAnalytic.vue:175
 #: src/views/dashboard/ServerAnalytic.vue:175
 msgid "Server Info"
 msgid "Server Info"
 msgstr "Informations sur le serveur"
 msgstr "Informations sur le serveur"
@@ -4568,7 +4609,7 @@ msgstr "Temps d'attente entre les itérations du chargeur de cache"
 msgid "Sleep time between cache manager iterations"
 msgid "Sleep time between cache manager iterations"
 msgstr "Temps d'attente entre les itérations du gestionnaire de cache"
 msgstr "Temps d'attente entre les itérations du gestionnaire de cache"
 
 
-#: src/views/certificate/CertificateEditor.vue:213
+#: src/views/certificate/CertificateEditor.vue:211
 msgid "SSL Certificate Content"
 msgid "SSL Certificate Content"
 msgstr "Contenu du certificat SSL"
 msgstr "Contenu du certificat SSL"
 
 
@@ -4582,15 +4623,15 @@ msgstr ""
 msgid "SSL certificate file not found"
 msgid "SSL certificate file not found"
 msgstr "Fichier de certificat SSL introuvable"
 msgstr "Fichier de certificat SSL introuvable"
 
 
-#: src/views/certificate/CertificateEditor.vue:227
+#: src/views/certificate/CertificateEditor.vue:225
 msgid "SSL Certificate Key Content"
 msgid "SSL Certificate Key Content"
 msgstr "Contenu de la clé du certificat SSL"
 msgstr "Contenu de la clé du certificat SSL"
 
 
-#: src/views/certificate/CertificateEditor.vue:192
+#: src/views/certificate/CertificateEditor.vue:190
 msgid "SSL Certificate Key Path"
 msgid "SSL Certificate Key Path"
 msgstr "Chemin de la clé du certificat SSL"
 msgstr "Chemin de la clé du certificat SSL"
 
 
-#: src/views/certificate/CertificateEditor.vue:177
+#: src/views/certificate/CertificateEditor.vue:175
 #: src/views/preference/tabs/ServerSettings.vue:37
 #: src/views/preference/tabs/ServerSettings.vue:37
 msgid "SSL Certificate Path"
 msgid "SSL Certificate Path"
 msgstr "Chemin du certificat SSL"
 msgstr "Chemin du certificat SSL"
@@ -4832,7 +4873,7 @@ msgstr "Nœuds de synchronisation"
 msgid "Sync strategy"
 msgid "Sync strategy"
 msgstr "Stratégie de synchronisation"
 msgstr "Stratégie de synchronisation"
 
 
-#: src/views/certificate/CertificateEditor.vue:206
+#: src/views/certificate/CertificateEditor.vue:204
 msgid "Sync to"
 msgid "Sync to"
 msgstr "Synchroniser vers"
 msgstr "Synchroniser vers"
 
 
@@ -4908,11 +4949,11 @@ msgstr ""
 "Le numéro ICP ne doit contenir que des lettres, unicode, des chiffres, des "
 "Le numéro ICP ne doit contenir que des lettres, unicode, des chiffres, des "
 "traits d'union, des tirets, des deux-points et des points."
 "traits d'union, des tirets, des deux-points et des points."
 
 
-#: src/views/certificate/CertificateEditor.vue:216
+#: src/views/certificate/CertificateEditor.vue:214
 msgid "The input is not a SSL Certificate"
 msgid "The input is not a SSL Certificate"
 msgstr "L'entrée n'est pas un certificat SSL"
 msgstr "L'entrée n'est pas un certificat SSL"
 
 
-#: src/views/certificate/CertificateEditor.vue:230
+#: src/views/certificate/CertificateEditor.vue:228
 msgid "The input is not a SSL Certificate Key"
 msgid "The input is not a SSL Certificate Key"
 msgstr "L'entrée n'est pas une clé de certificat SSL"
 msgstr "L'entrée n'est pas une clé de certificat SSL"
 
 
@@ -4951,11 +4992,11 @@ msgstr ""
 msgid "The parameter of server_name is required"
 msgid "The parameter of server_name is required"
 msgstr "Le paramètre server_name est requis"
 msgstr "Le paramètre server_name est requis"
 
 
-#: src/views/certificate/CertificateEditor.vue:181
+#: src/views/certificate/CertificateEditor.vue:179
 msgid "The path exists, but the file is not a certificate"
 msgid "The path exists, but the file is not a certificate"
 msgstr "Le chemin existe, mais le fichier n'est pas un certificat"
 msgstr "Le chemin existe, mais le fichier n'est pas un certificat"
 
 
-#: src/views/certificate/CertificateEditor.vue:196
+#: src/views/certificate/CertificateEditor.vue:194
 msgid "The path exists, but the file is not a private key"
 msgid "The path exists, but the file is not a private key"
 msgstr "Le chemin existe, mais le fichier n'est pas une clé privée"
 msgstr "Le chemin existe, mais le fichier n'est pas une clé privée"
 
 
@@ -5018,17 +5059,17 @@ msgstr ""
 "perdez votre mot de passe et vos seconds facteurs. Si vous ne trouvez pas "
 "perdez votre mot de passe et vos seconds facteurs. Si vous ne trouvez pas "
 "ces codes, vous perdrez l'accès à votre compte."
 "ces codes, vous perdrez l'accès à votre compte."
 
 
-#: src/views/certificate/CertificateEditor.vue:102
+#: src/views/certificate/CertificateEditor.vue:100
 msgid "This Auto Cert item is invalid, please remove it."
 msgid "This Auto Cert item is invalid, please remove it."
 msgstr "Cet élément de certificat automatique est invalide, veuillez le supprimer."
 msgstr "Cet élément de certificat automatique est invalide, veuillez le supprimer."
 
 
-#: src/views/certificate/CertificateEditor.vue:92
+#: src/views/certificate/CertificateEditor.vue:90
 msgid "This certificate is managed by Nginx UI"
 msgid "This certificate is managed by Nginx UI"
 msgstr "Ce certificat est géré par Nginx UI"
 msgstr "Ce certificat est géré par Nginx UI"
 
 
-#: src/views/certificate/CertificateEditor.vue:165
-#: src/views/certificate/CertificateEditor.vue:179
-#: src/views/certificate/CertificateEditor.vue:194
+#: src/views/certificate/CertificateEditor.vue:163
+#: src/views/certificate/CertificateEditor.vue:177
+#: src/views/certificate/CertificateEditor.vue:192
 msgid "This field is required"
 msgid "This field is required"
 msgstr "Ce champ est obligatoire"
 msgstr "Ce champ est obligatoire"
 
 
@@ -5520,6 +5561,10 @@ msgstr ""
 "S'il faut utiliser un chemin temporaire lors de l'écriture de fichiers "
 "S'il faut utiliser un chemin temporaire lors de l'écriture de fichiers "
 "temporaires"
 "temporaires"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:107
+msgid "Wildcard Certificate"
+msgstr "Certificat générique"
+
 #: src/views/dashboard/components/ParamsOpt/PerformanceConfig.vue:48
 #: src/views/dashboard/components/ParamsOpt/PerformanceConfig.vue:48
 msgid "Worker Connections"
 msgid "Worker Connections"
 msgstr "Connexions des travailleurs"
 msgstr "Connexions des travailleurs"
@@ -5837,9 +5882,6 @@ msgstr "Vos clés d'accès"
 #~ msgid "File"
 #~ msgid "File"
 #~ msgstr "Fichier"
 #~ msgstr "Fichier"
 
 
-#~ msgid "Server error"
-#~ msgstr "Erreur du serveur"
-
 #, fuzzy
 #, fuzzy
 #~ msgid "Incorrect username or password"
 #~ msgid "Incorrect username or password"
 #~ msgstr "Le pseudo ou mot de passe est incorect"
 #~ msgstr "Le pseudo ou mot de passe est incorect"

+ 82 - 39
app/src/language/ja_JP/app.po

@@ -181,6 +181,10 @@ msgstr "設定を追加"
 msgid "Add Directive Below"
 msgid "Add Directive Below"
 msgstr "ディレクティブを追加"
 msgstr "ディレクティブを追加"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:151
+msgid "Add Domain"
+msgstr "ドメインを追加"
+
 #: src/components/NgxConfigEditor/LocationEditor.vue:131
 #: src/components/NgxConfigEditor/LocationEditor.vue:131
 #: src/components/NgxConfigEditor/LocationEditor.vue:158
 #: src/components/NgxConfigEditor/LocationEditor.vue:158
 msgid "Add Location"
 msgid "Add Location"
@@ -228,6 +232,12 @@ msgstr "すべて"
 msgid "All Recovery Codes Have Been Used"
 msgid "All Recovery Codes Have Been Used"
 msgstr "すべてのリカバリーコードが使用済みです"
 msgstr "すべてのリカバリーコードが使用済みです"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:156
+msgid ""
+"All selected subdomains must belong to the same DNS Provider, otherwise the "
+"certificate application will fail."
+msgstr "選択したすべてのサブドメインは同じ DNS プロバイダーに属している必要があります。そうでない場合、証明書の申請は失敗します。"
+
 #: src/views/preference/tabs/OpenAISettings.vue:32
 #: src/views/preference/tabs/OpenAISettings.vue:32
 msgid "API Base Url"
 msgid "API Base Url"
 msgstr "APIベースURL"
 msgstr "APIベースURL"
@@ -254,7 +264,7 @@ msgstr "アプリ"
 
 
 #: src/views/system/Upgrade.vue:195
 #: src/views/system/Upgrade.vue:195
 msgid "Arch"
 msgid "Arch"
-msgstr "\"アーキテクチャ\""
+msgstr "アーキテクチャ"
 
 
 #: src/views/preference/tabs/AuthSettings.vue:130
 #: src/views/preference/tabs/AuthSettings.vue:130
 msgid "Are you sure to delete this banned IP immediately?"
 msgid "Are you sure to delete this banned IP immediately?"
@@ -389,7 +399,7 @@ msgstr "%{name}の自動更新が無効になっています"
 msgid "Auto-renewal enabled for %{name}"
 msgid "Auto-renewal enabled for %{name}"
 msgstr "%{name}の自動更新が有効になっています"
 msgstr "%{name}の自動更新が有効になっています"
 
 
-#: src/views/certificate/components/RenewCert.vue:49
+#: src/views/certificate/components/RenewCert.vue:51
 #: src/views/site/site_edit/components/Cert/IssueCert.vue:84
 #: src/views/site/site_edit/components/Cert/IssueCert.vue:84
 msgid "AutoCert is running, please wait..."
 msgid "AutoCert is running, please wait..."
 msgstr "AutoCert が実行中です。お待ちください..."
 msgstr "AutoCert が実行中です。お待ちください..."
@@ -402,7 +412,7 @@ msgstr "AutoCert が実行中..."
 msgid "Automatic Restart"
 msgid "Automatic Restart"
 msgstr "自動再起動"
 msgstr "自動再起動"
 
 
-#: src/views/certificate/CertificateEditor.vue:259
+#: src/views/certificate/CertificateEditor.vue:257
 #: src/views/config/components/ConfigLeftPanel.vue:273
 #: src/views/config/components/ConfigLeftPanel.vue:273
 #: src/views/config/ConfigList.vue:112 src/views/config/ConfigList.vue:195
 #: src/views/config/ConfigList.vue:112 src/views/config/ConfigList.vue:195
 #: src/views/nginx_log/NginxLog.vue:174
 #: src/views/nginx_log/NginxLog.vue:174
@@ -695,12 +705,16 @@ msgstr "証明書の更新に成功しました"
 msgid "Certificate revoked successfully"
 msgid "Certificate revoked successfully"
 msgstr "証明書の失効に成功しました"
 msgstr "証明書の失効に成功しました"
 
 
-#: src/views/certificate/CertificateEditor.vue:128
+#: src/views/certificate/CertificateEditor.vue:126
 #: src/views/site/site_edit/components/Cert/Cert.vue:58
 #: src/views/site/site_edit/components/Cert/Cert.vue:58
 msgid "Certificate Status"
 msgid "Certificate Status"
 msgid_plural "Certificates Status"
 msgid_plural "Certificates Status"
 msgstr[0] "証明書のステータス"
 msgstr[0] "証明書のステータス"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:104
+msgid "Certificate Type"
+msgstr "証明書の種類"
+
 #: src/routes/modules/certificates.ts:11
 #: src/routes/modules/certificates.ts:11
 #: src/views/certificate/CertificateList/Certificate.vue:19
 #: src/views/certificate/CertificateList/Certificate.vue:19
 msgid "Certificates"
 msgid "Certificates"
@@ -1170,6 +1184,14 @@ msgstr "カスタム cron 式"
 msgid "Custom Directory"
 msgid "Custom Directory"
 msgstr "カスタムディレクトリ"
 msgstr "カスタムディレクトリ"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:126
+msgid "Custom Domains"
+msgstr "カスタムドメイン"
+
+#: src/views/certificate/components/DNSIssueCertificate.vue:110
+msgid "Custom Domains Certificate"
+msgstr "カスタムドメイン証明書"
+
 #: src/views/preference/tabs/NodeSettings.vue:19
 #: src/views/preference/tabs/NodeSettings.vue:19
 msgid ""
 msgid ""
 "Customize the name of local node to be displayed in the environment "
 "Customize the name of local node to be displayed in the environment "
@@ -1477,11 +1499,11 @@ msgid "Document"
 msgid_plural "Documents"
 msgid_plural "Documents"
 msgstr[0] "ドキュメント"
 msgstr[0] "ドキュメント"
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:66
+#: src/views/certificate/components/DNSIssueCertificate.vue:116
 msgid "Domain"
 msgid "Domain"
 msgstr "ドメイン"
 msgstr "ドメイン"
 
 
-#: src/views/certificate/CertificateEditor.vue:112
+#: src/views/certificate/CertificateEditor.vue:110
 msgid "Domains list is empty, try to reopen Auto Cert for %{config}"
 msgid "Domains list is empty, try to reopen Auto Cert for %{config}"
 msgstr "ドメインリストが空です。%{config} の自動証明書を再度開いてみてください"
 msgstr "ドメインリストが空です。%{config} の自動証明書を再度開いてみてください"
 
 
@@ -1681,6 +1703,14 @@ msgstr "Let's Encryptでウェブサイトを暗号化"
 msgid "End"
 msgid "End"
 msgstr "終了"
 msgstr "終了"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:135
+msgid "Enter domain name"
+msgstr "ドメイン名を入力"
+
+#: src/views/certificate/components/DNSIssueCertificate.vue:120
+msgid "Enter your domain"
+msgstr "ドメインを入力してください"
+
 #: src/language/constants.ts:22
 #: src/language/constants.ts:22
 msgid "Environment variables cleaned"
 msgid "Environment variables cleaned"
 msgstr "環境変数をクリーンアップしました"
 msgstr "環境変数をクリーンアップしました"
@@ -1755,7 +1785,7 @@ msgstr "外部 Docker コンテナ"
 msgid "External Notify"
 msgid "External Notify"
 msgstr "外部通知"
 msgstr "外部通知"
 
 
-#: src/views/site/site_edit/components/Cert/ObtainCertLive.vue:80
+#: src/views/site/site_edit/components/Cert/ObtainCertLive.vue:81
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
 msgstr "証明書の取得に失敗しました"
 msgstr "証明書の取得に失敗しました"
 
 
@@ -2276,7 +2306,7 @@ msgid "Import"
 msgstr "インポート"
 msgstr "インポート"
 
 
 #: src/routes/modules/certificates.ts:46
 #: src/routes/modules/certificates.ts:46
-#: src/views/certificate/CertificateEditor.vue:85
+#: src/views/certificate/CertificateEditor.vue:83
 msgid "Import Certificate"
 msgid "Import Certificate"
 msgstr "証明書をインポート"
 msgstr "証明書をインポート"
 
 
@@ -2417,12 +2447,12 @@ msgid "IP"
 msgstr "IP"
 msgstr "IP"
 
 
 #: src/views/certificate/CertificateList/Certificate.vue:37
 #: src/views/certificate/CertificateList/Certificate.vue:37
-msgid "Issue wildcard certificate"
-msgstr "ワイルドカード証明書を発行"
+msgid "Issue certificate"
+msgstr "証明書を発行"
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:57
-msgid "Issue Wildcard Certificate"
-msgstr "ワイルドカード証明書を発行"
+#: src/views/certificate/components/DNSIssueCertificate.vue:95
+msgid "Issue Certificate"
+msgstr "証明書を発行"
 
 
 #: src/language/constants.ts:20
 #: src/language/constants.ts:20
 msgid "Issued certificate successfully"
 msgid "Issued certificate successfully"
@@ -2503,8 +2533,8 @@ msgstr "変更しない場合は空白のままにしてください"
 msgid "Leave blank if you don't need this."
 msgid "Leave blank if you don't need this."
 msgstr "必要なければ空白のままにしてください。"
 msgstr "必要なければ空白のままにしてください。"
 
 
-#: src/views/certificate/CertificateEditor.vue:223
-#: src/views/certificate/CertificateEditor.vue:237
+#: src/views/certificate/CertificateEditor.vue:221
+#: src/views/certificate/CertificateEditor.vue:235
 msgid "Leave blank will not change anything"
 msgid "Leave blank will not change anything"
 msgstr "空白のままにすると何も変更されません"
 msgstr "空白のままにすると何も変更されません"
 
 
@@ -2591,7 +2621,7 @@ msgstr "ロケーション"
 msgid "Locations"
 msgid "Locations"
 msgstr "ロケーション"
 msgstr "ロケーション"
 
 
-#: src/views/certificate/CertificateEditor.vue:247
+#: src/views/certificate/CertificateEditor.vue:245
 msgid "Log"
 msgid "Log"
 msgstr "ログ"
 msgstr "ログ"
 
 
@@ -2801,7 +2831,7 @@ msgid "Modify"
 msgstr "変更"
 msgstr "変更"
 
 
 #: src/routes/modules/certificates.ts:36
 #: src/routes/modules/certificates.ts:36
-#: src/views/certificate/CertificateEditor.vue:85
+#: src/views/certificate/CertificateEditor.vue:83
 msgid "Modify Certificate"
 msgid "Modify Certificate"
 msgstr "証明書を変更"
 msgstr "証明書を変更"
 
 
@@ -2836,7 +2866,7 @@ msgstr "複数行ディレクティブ"
 #: src/components/NgxConfigEditor/NgxUpstream.vue:199
 #: src/components/NgxConfigEditor/NgxUpstream.vue:199
 #: src/views/backup/AutoBackup/AutoBackup.vue:11
 #: src/views/backup/AutoBackup/AutoBackup.vue:11
 #: src/views/certificate/ACMEUser.vue:11
 #: src/views/certificate/ACMEUser.vue:11
-#: src/views/certificate/CertificateEditor.vue:162
+#: src/views/certificate/CertificateEditor.vue:160
 #: src/views/certificate/CertificateList/certColumns.tsx:9
 #: src/views/certificate/CertificateList/certColumns.tsx:9
 #: src/views/certificate/DNSCredential.vue:9
 #: src/views/certificate/DNSCredential.vue:9
 #: src/views/config/components/ConfigRightPanel/Basic.vue:34
 #: src/views/config/components/ConfigRightPanel/Basic.vue:34
@@ -2896,7 +2926,7 @@ msgstr "新しいパス"
 msgid "New version released"
 msgid "New version released"
 msgstr "新しいバージョンがリリースされました"
 msgstr "新しいバージョンがリリースされました"
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:89
+#: src/views/certificate/components/DNSIssueCertificate.vue:181
 #: src/views/install/components/InstallView.vue:96
 #: src/views/install/components/InstallView.vue:96
 #: src/views/site/site_add/SiteAdd.vue:132
 #: src/views/site/site_add/SiteAdd.vue:132
 #: src/views/site/site_edit/components/Cert/ObtainCert.vue:214
 #: src/views/site/site_edit/components/Cert/ObtainCert.vue:214
@@ -3471,6 +3501,10 @@ msgstr "作成したいパスキーの名前を入力し、下のOKボタンを
 msgid "Please enter a valid port range"
 msgid "Please enter a valid port range"
 msgstr "有効なポート範囲を入力してください"
 msgstr "有効なポート範囲を入力してください"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:74
+msgid "Please enter at least one domain"
+msgstr "少なくとも1つのドメインを入力してください"
+
 #: src/components/TwoFA/Authorization.vue:85
 #: src/components/TwoFA/Authorization.vue:85
 msgid "Please enter the OTP code:"
 msgid "Please enter the OTP code:"
 msgstr "OTPコードを入力してください:"
 msgstr "OTPコードを入力してください:"
@@ -3798,6 +3832,7 @@ msgstr "再読み込み中"
 msgid "Reloading nginx"
 msgid "Reloading nginx"
 msgstr "nginx をリロード中"
 msgstr "nginx をリロード中"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:144
 #: src/views/preference/tabs/AuthSettings.vue:137
 #: src/views/preference/tabs/AuthSettings.vue:137
 msgid "Remove"
 msgid "Remove"
 msgstr "削除"
 msgstr "削除"
@@ -3880,8 +3915,8 @@ msgstr "名前の変更に成功しました"
 msgid "Renamed successfully"
 msgid "Renamed successfully"
 msgstr "名前の変更に成功しました"
 msgstr "名前の変更に成功しました"
 
 
-#: src/views/certificate/components/RenewCert.vue:46
-#: src/views/certificate/components/RenewCert.vue:53
+#: src/views/certificate/components/RenewCert.vue:48
+#: src/views/certificate/components/RenewCert.vue:55
 msgid "Renew Certificate"
 msgid "Renew Certificate"
 msgstr "証明書を更新"
 msgstr "証明書を更新"
 
 
@@ -3893,8 +3928,8 @@ msgstr "証明書の更新エラー"
 msgid "Renew Certificate Success"
 msgid "Renew Certificate Success"
 msgstr "証明書の更新に成功しました"
 msgstr "証明書の更新に成功しました"
 
 
-#: src/views/certificate/components/RenewCert.vue:28
-#: src/views/certificate/components/WildcardCertificate.vue:46
+#: src/views/certificate/components/DNSIssueCertificate.vue:84
+#: src/views/certificate/components/RenewCert.vue:30
 msgid "Renew successfully"
 msgid "Renew successfully"
 msgstr "証明書の更新に成功しました"
 msgstr "証明書の更新に成功しました"
 
 
@@ -4148,7 +4183,7 @@ msgstr "土曜日"
 
 
 #: src/components/ChatGPT/ChatMessage.vue:215
 #: src/components/ChatGPT/ChatMessage.vue:215
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:129
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:129
-#: src/language/curd.ts:18 src/views/certificate/CertificateEditor.vue:266
+#: src/language/curd.ts:18 src/views/certificate/CertificateEditor.vue:264
 #: src/views/config/components/ConfigLeftPanel.vue:282
 #: src/views/config/components/ConfigLeftPanel.vue:282
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/preference/components/AuthSettings/Passkey.vue:130
 #: src/views/preference/components/AuthSettings/Passkey.vue:130
@@ -4203,7 +4238,7 @@ msgstr "ストリーム %{name} を %{node} に保存できませんでした"
 msgid "Save stream %{name} to %{node} successfully"
 msgid "Save stream %{name} to %{node} successfully"
 msgstr "ストリーム %{name} を %{node} に正常に保存しました"
 msgstr "ストリーム %{name} を %{node} に正常に保存しました"
 
 
-#: src/language/curd.ts:35 src/views/certificate/CertificateEditor.vue:49
+#: src/language/curd.ts:35 src/views/certificate/store.ts:13
 #: src/views/preference/store/index.ts:118
 #: src/views/preference/store/index.ts:118
 msgid "Save successfully"
 msgid "Save successfully"
 msgstr "保存に成功しました"
 msgstr "保存に成功しました"
@@ -4311,6 +4346,10 @@ msgstr "送信"
 msgid "Server"
 msgid "Server"
 msgstr "サーバー"
 msgstr "サーバー"
 
 
+#: src/views/certificate/CertificateEditor.vue:55
+msgid "Server error"
+msgstr "サーバーエラー"
+
 #: src/views/dashboard/ServerAnalytic.vue:175
 #: src/views/dashboard/ServerAnalytic.vue:175
 msgid "Server Info"
 msgid "Server Info"
 msgstr "サーバー情報"
 msgstr "サーバー情報"
@@ -4445,7 +4484,7 @@ msgstr "キャッシュローダーの反復処理間の待機時間"
 msgid "Sleep time between cache manager iterations"
 msgid "Sleep time between cache manager iterations"
 msgstr "キャッシュマネージャーの反復処理間の待機時間"
 msgstr "キャッシュマネージャーの反復処理間の待機時間"
 
 
-#: src/views/certificate/CertificateEditor.vue:213
+#: src/views/certificate/CertificateEditor.vue:211
 msgid "SSL Certificate Content"
 msgid "SSL Certificate Content"
 msgstr "SSL証明書の内容"
 msgstr "SSL証明書の内容"
 
 
@@ -4457,15 +4496,15 @@ msgstr "SSL証明書ファイルはNginx設定ディレクトリの下にある
 msgid "SSL certificate file not found"
 msgid "SSL certificate file not found"
 msgstr "SSL証明書ファイルが見つかりません"
 msgstr "SSL証明書ファイルが見つかりません"
 
 
-#: src/views/certificate/CertificateEditor.vue:227
+#: src/views/certificate/CertificateEditor.vue:225
 msgid "SSL Certificate Key Content"
 msgid "SSL Certificate Key Content"
 msgstr "SSL証明書キーの内容"
 msgstr "SSL証明書キーの内容"
 
 
-#: src/views/certificate/CertificateEditor.vue:192
+#: src/views/certificate/CertificateEditor.vue:190
 msgid "SSL Certificate Key Path"
 msgid "SSL Certificate Key Path"
 msgstr "SSL証明書キーパス"
 msgstr "SSL証明書キーパス"
 
 
-#: src/views/certificate/CertificateEditor.vue:177
+#: src/views/certificate/CertificateEditor.vue:175
 #: src/views/preference/tabs/ServerSettings.vue:37
 #: src/views/preference/tabs/ServerSettings.vue:37
 msgid "SSL Certificate Path"
 msgid "SSL Certificate Path"
 msgstr "SSL証明書のパス"
 msgstr "SSL証明書のパス"
@@ -4698,7 +4737,7 @@ msgstr "同期ノード"
 msgid "Sync strategy"
 msgid "Sync strategy"
 msgstr "同期戦略"
 msgstr "同期戦略"
 
 
-#: src/views/certificate/CertificateEditor.vue:206
+#: src/views/certificate/CertificateEditor.vue:204
 msgid "Sync to"
 msgid "Sync to"
 msgstr "同期先"
 msgstr "同期先"
 
 
@@ -4769,11 +4808,11 @@ msgid ""
 "dashes, colons, and dots."
 "dashes, colons, and dots."
 msgstr "ICP番号には、文字、Unicode、数字、ハイフン、ダッシュ、コロン、およびドットのみを含める必要があります。"
 msgstr "ICP番号には、文字、Unicode、数字、ハイフン、ダッシュ、コロン、およびドットのみを含める必要があります。"
 
 
-#: src/views/certificate/CertificateEditor.vue:216
+#: src/views/certificate/CertificateEditor.vue:214
 msgid "The input is not a SSL Certificate"
 msgid "The input is not a SSL Certificate"
 msgstr "入力はSSL証明書ではありません"
 msgstr "入力はSSL証明書ではありません"
 
 
-#: src/views/certificate/CertificateEditor.vue:230
+#: src/views/certificate/CertificateEditor.vue:228
 msgid "The input is not a SSL Certificate Key"
 msgid "The input is not a SSL Certificate Key"
 msgstr "入力はSSL証明書キーではありません"
 msgstr "入力はSSL証明書キーではありません"
 
 
@@ -4804,11 +4843,11 @@ msgstr "ノード名には、文字、Unicode、数字、ハイフン、ダッ
 msgid "The parameter of server_name is required"
 msgid "The parameter of server_name is required"
 msgstr "server_name のパラメーターが必要です"
 msgstr "server_name のパラメーターが必要です"
 
 
-#: src/views/certificate/CertificateEditor.vue:181
+#: src/views/certificate/CertificateEditor.vue:179
 msgid "The path exists, but the file is not a certificate"
 msgid "The path exists, but the file is not a certificate"
 msgstr "パスは存在しますが、ファイルは証明書ではありません"
 msgstr "パスは存在しますが、ファイルは証明書ではありません"
 
 
-#: src/views/certificate/CertificateEditor.vue:196
+#: src/views/certificate/CertificateEditor.vue:194
 msgid "The path exists, but the file is not a private key"
 msgid "The path exists, but the file is not a private key"
 msgstr "パスは存在しますが、ファイルは秘密鍵ではありません"
 msgstr "パスは存在しますが、ファイルは秘密鍵ではありません"
 
 
@@ -4864,17 +4903,17 @@ msgstr ""
 "これらのコードは、パスワードと第二要素を失った場合にアカウントにアクセスするための最後の手段です。これらのコードが見つからない場合、アカウントにアクセス"
 "これらのコードは、パスワードと第二要素を失った場合にアカウントにアクセスするための最後の手段です。これらのコードが見つからない場合、アカウントにアクセス"
 "できなくなります。"
 "できなくなります。"
 
 
-#: src/views/certificate/CertificateEditor.vue:102
+#: src/views/certificate/CertificateEditor.vue:100
 msgid "This Auto Cert item is invalid, please remove it."
 msgid "This Auto Cert item is invalid, please remove it."
 msgstr "この自動証明書項目は無効です。削除してください。"
 msgstr "この自動証明書項目は無効です。削除してください。"
 
 
-#: src/views/certificate/CertificateEditor.vue:92
+#: src/views/certificate/CertificateEditor.vue:90
 msgid "This certificate is managed by Nginx UI"
 msgid "This certificate is managed by Nginx UI"
 msgstr "この証明書はNginx UIによって管理されています"
 msgstr "この証明書はNginx UIによって管理されています"
 
 
-#: src/views/certificate/CertificateEditor.vue:165
-#: src/views/certificate/CertificateEditor.vue:179
-#: src/views/certificate/CertificateEditor.vue:194
+#: src/views/certificate/CertificateEditor.vue:163
+#: src/views/certificate/CertificateEditor.vue:177
+#: src/views/certificate/CertificateEditor.vue:192
 msgid "This field is required"
 msgid "This field is required"
 msgstr "このフィールドは必須です"
 msgstr "このフィールドは必須です"
 
 
@@ -5321,6 +5360,10 @@ msgstr "新しいリカバリーコードを生成するときは、新しいコ
 msgid "Whether to use a temporary path when writing temporary files"
 msgid "Whether to use a temporary path when writing temporary files"
 msgstr "一時ファイルを書き込む際に一時パスを使用するかどうか"
 msgstr "一時ファイルを書き込む際に一時パスを使用するかどうか"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:107
+msgid "Wildcard Certificate"
+msgstr "ワイルドカード証明書"
+
 #: src/views/dashboard/components/ParamsOpt/PerformanceConfig.vue:48
 #: src/views/dashboard/components/ParamsOpt/PerformanceConfig.vue:48
 msgid "Worker Connections"
 msgid "Worker Connections"
 msgstr "ワーカー接続数"
 msgstr "ワーカー接続数"

+ 82 - 42
app/src/language/ko_KR/app.po

@@ -179,6 +179,10 @@ msgstr "구성 추가"
 msgid "Add Directive Below"
 msgid "Add Directive Below"
 msgstr "아래에 지시문 추가"
 msgstr "아래에 지시문 추가"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:151
+msgid "Add Domain"
+msgstr "도메인 추가"
+
 #: src/components/NgxConfigEditor/LocationEditor.vue:131
 #: src/components/NgxConfigEditor/LocationEditor.vue:131
 #: src/components/NgxConfigEditor/LocationEditor.vue:158
 #: src/components/NgxConfigEditor/LocationEditor.vue:158
 msgid "Add Location"
 msgid "Add Location"
@@ -226,6 +230,12 @@ msgstr "모두"
 msgid "All Recovery Codes Have Been Used"
 msgid "All Recovery Codes Have Been Used"
 msgstr "모든 복구 코드가 사용되었습니다"
 msgstr "모든 복구 코드가 사용되었습니다"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:156
+msgid ""
+"All selected subdomains must belong to the same DNS Provider, otherwise the "
+"certificate application will fail."
+msgstr "선택한 모든 서브도메인은 동일한 DNS 공급자에 속해야 합니다. 그렇지 않으면 인증서 신청이 실패합니다."
+
 #: src/views/preference/tabs/OpenAISettings.vue:32
 #: src/views/preference/tabs/OpenAISettings.vue:32
 msgid "API Base Url"
 msgid "API Base Url"
 msgstr "API 기본 URL"
 msgstr "API 기본 URL"
@@ -252,7 +262,7 @@ msgstr "앱"
 
 
 #: src/views/system/Upgrade.vue:195
 #: src/views/system/Upgrade.vue:195
 msgid "Arch"
 msgid "Arch"
-msgstr "\"아키텍처\""
+msgstr "아키텍처"
 
 
 #: src/views/preference/tabs/AuthSettings.vue:130
 #: src/views/preference/tabs/AuthSettings.vue:130
 msgid "Are you sure to delete this banned IP immediately?"
 msgid "Are you sure to delete this banned IP immediately?"
@@ -387,7 +397,7 @@ msgstr "%{name}에 대한 자동 갱신 비활성화됨"
 msgid "Auto-renewal enabled for %{name}"
 msgid "Auto-renewal enabled for %{name}"
 msgstr "%{name}에 대한 자동 갱신 활성화됨"
 msgstr "%{name}에 대한 자동 갱신 활성화됨"
 
 
-#: src/views/certificate/components/RenewCert.vue:49
+#: src/views/certificate/components/RenewCert.vue:51
 #: src/views/site/site_edit/components/Cert/IssueCert.vue:84
 #: src/views/site/site_edit/components/Cert/IssueCert.vue:84
 msgid "AutoCert is running, please wait..."
 msgid "AutoCert is running, please wait..."
 msgstr "AutoCert가 실행 중입니다. 잠시 기다려 주세요..."
 msgstr "AutoCert가 실행 중입니다. 잠시 기다려 주세요..."
@@ -400,7 +410,7 @@ msgstr "\"AutoCert 실행 중...\""
 msgid "Automatic Restart"
 msgid "Automatic Restart"
 msgstr "\"자동 재시작\""
 msgstr "\"자동 재시작\""
 
 
-#: src/views/certificate/CertificateEditor.vue:259
+#: src/views/certificate/CertificateEditor.vue:257
 #: src/views/config/components/ConfigLeftPanel.vue:273
 #: src/views/config/components/ConfigLeftPanel.vue:273
 #: src/views/config/ConfigList.vue:112 src/views/config/ConfigList.vue:195
 #: src/views/config/ConfigList.vue:112 src/views/config/ConfigList.vue:195
 #: src/views/nginx_log/NginxLog.vue:174
 #: src/views/nginx_log/NginxLog.vue:174
@@ -693,13 +703,17 @@ msgstr "인증서 갱신 성공"
 msgid "Certificate revoked successfully"
 msgid "Certificate revoked successfully"
 msgstr "인증서가 성공적으로 취소되었습니다"
 msgstr "인증서가 성공적으로 취소되었습니다"
 
 
-#: src/views/certificate/CertificateEditor.vue:128
+#: src/views/certificate/CertificateEditor.vue:126
 #: src/views/site/site_edit/components/Cert/Cert.vue:58
 #: src/views/site/site_edit/components/Cert/Cert.vue:58
 msgid "Certificate Status"
 msgid "Certificate Status"
 msgid_plural "Certificates Status"
 msgid_plural "Certificates Status"
 msgstr[0] "인증서 상태"
 msgstr[0] "인증서 상태"
 msgstr[1] "인증서 상태"
 msgstr[1] "인증서 상태"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:104
+msgid "Certificate Type"
+msgstr "인증서 유형"
+
 #: src/routes/modules/certificates.ts:11
 #: src/routes/modules/certificates.ts:11
 #: src/views/certificate/CertificateList/Certificate.vue:19
 #: src/views/certificate/CertificateList/Certificate.vue:19
 msgid "Certificates"
 msgid "Certificates"
@@ -1167,6 +1181,14 @@ msgstr "사용자 정의 cron 표현식"
 msgid "Custom Directory"
 msgid "Custom Directory"
 msgstr "사용자 지정 디렉토리"
 msgstr "사용자 지정 디렉토리"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:126
+msgid "Custom Domains"
+msgstr "사용자 정의 도메인"
+
+#: src/views/certificate/components/DNSIssueCertificate.vue:110
+msgid "Custom Domains Certificate"
+msgstr "사용자 정의 도메인 인증서"
+
 #: src/views/preference/tabs/NodeSettings.vue:19
 #: src/views/preference/tabs/NodeSettings.vue:19
 msgid ""
 msgid ""
 "Customize the name of local node to be displayed in the environment "
 "Customize the name of local node to be displayed in the environment "
@@ -1474,11 +1496,11 @@ msgid "Document"
 msgid_plural "Documents"
 msgid_plural "Documents"
 msgstr[0] "문서"
 msgstr[0] "문서"
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:66
+#: src/views/certificate/components/DNSIssueCertificate.vue:116
 msgid "Domain"
 msgid "Domain"
 msgstr "도메인"
 msgstr "도메인"
 
 
-#: src/views/certificate/CertificateEditor.vue:112
+#: src/views/certificate/CertificateEditor.vue:110
 msgid "Domains list is empty, try to reopen Auto Cert for %{config}"
 msgid "Domains list is empty, try to reopen Auto Cert for %{config}"
 msgstr "도메인 목록이 비어 있습니다. %{config}에 대한 자동 인증서를 다시 열어보세요"
 msgstr "도메인 목록이 비어 있습니다. %{config}에 대한 자동 인증서를 다시 열어보세요"
 
 
@@ -1680,6 +1702,14 @@ msgstr "Let's Encrypt로 웹사이트 암호화"
 msgid "End"
 msgid "End"
 msgstr "끝"
 msgstr "끝"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:135
+msgid "Enter domain name"
+msgstr "도메인 이름 입력"
+
+#: src/views/certificate/components/DNSIssueCertificate.vue:120
+msgid "Enter your domain"
+msgstr "도메인을 입력하세요"
+
 #: src/language/constants.ts:22
 #: src/language/constants.ts:22
 msgid "Environment variables cleaned"
 msgid "Environment variables cleaned"
 msgstr "환경 변수가 정리되었습니다"
 msgstr "환경 변수가 정리되었습니다"
@@ -1754,7 +1784,7 @@ msgstr "외부 Docker 컨테이너"
 msgid "External Notify"
 msgid "External Notify"
 msgstr "외부 알림"
 msgstr "외부 알림"
 
 
-#: src/views/site/site_edit/components/Cert/ObtainCertLive.vue:80
+#: src/views/site/site_edit/components/Cert/ObtainCertLive.vue:81
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
 msgstr "인증서 획득 실패"
 msgstr "인증서 획득 실패"
 
 
@@ -2275,7 +2305,7 @@ msgid "Import"
 msgstr "가져오기"
 msgstr "가져오기"
 
 
 #: src/routes/modules/certificates.ts:46
 #: src/routes/modules/certificates.ts:46
-#: src/views/certificate/CertificateEditor.vue:85
+#: src/views/certificate/CertificateEditor.vue:83
 msgid "Import Certificate"
 msgid "Import Certificate"
 msgstr "인증서 가져오기"
 msgstr "인증서 가져오기"
 
 
@@ -2416,12 +2446,12 @@ msgid "IP"
 msgstr "IP"
 msgstr "IP"
 
 
 #: src/views/certificate/CertificateList/Certificate.vue:37
 #: src/views/certificate/CertificateList/Certificate.vue:37
-msgid "Issue wildcard certificate"
-msgstr "와일드카드 인증서 발급"
+msgid "Issue certificate"
+msgstr "인증서 발급"
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:57
-msgid "Issue Wildcard Certificate"
-msgstr "와일드카드 인증서 발급"
+#: src/views/certificate/components/DNSIssueCertificate.vue:95
+msgid "Issue Certificate"
+msgstr "인증서 발급"
 
 
 #: src/language/constants.ts:20
 #: src/language/constants.ts:20
 msgid "Issued certificate successfully"
 msgid "Issued certificate successfully"
@@ -2502,8 +2532,8 @@ msgstr "수정하지 않으려면 비워 두세요"
 msgid "Leave blank if you don't need this."
 msgid "Leave blank if you don't need this."
 msgstr "필요하지 않으면 비워 두세요."
 msgstr "필요하지 않으면 비워 두세요."
 
 
-#: src/views/certificate/CertificateEditor.vue:223
-#: src/views/certificate/CertificateEditor.vue:237
+#: src/views/certificate/CertificateEditor.vue:221
+#: src/views/certificate/CertificateEditor.vue:235
 msgid "Leave blank will not change anything"
 msgid "Leave blank will not change anything"
 msgstr "비워 두면 아무것도 변경되지 않습니다"
 msgstr "비워 두면 아무것도 변경되지 않습니다"
 
 
@@ -2590,7 +2620,7 @@ msgstr "위치"
 msgid "Locations"
 msgid "Locations"
 msgstr "위치들"
 msgstr "위치들"
 
 
-#: src/views/certificate/CertificateEditor.vue:247
+#: src/views/certificate/CertificateEditor.vue:245
 msgid "Log"
 msgid "Log"
 msgstr "로그"
 msgstr "로그"
 
 
@@ -2797,7 +2827,7 @@ msgid "Modify"
 msgstr "수정"
 msgstr "수정"
 
 
 #: src/routes/modules/certificates.ts:36
 #: src/routes/modules/certificates.ts:36
-#: src/views/certificate/CertificateEditor.vue:85
+#: src/views/certificate/CertificateEditor.vue:83
 msgid "Modify Certificate"
 msgid "Modify Certificate"
 msgstr "인증서 수정"
 msgstr "인증서 수정"
 
 
@@ -2832,7 +2862,7 @@ msgstr "여러 줄 지시문"
 #: src/components/NgxConfigEditor/NgxUpstream.vue:199
 #: src/components/NgxConfigEditor/NgxUpstream.vue:199
 #: src/views/backup/AutoBackup/AutoBackup.vue:11
 #: src/views/backup/AutoBackup/AutoBackup.vue:11
 #: src/views/certificate/ACMEUser.vue:11
 #: src/views/certificate/ACMEUser.vue:11
-#: src/views/certificate/CertificateEditor.vue:162
+#: src/views/certificate/CertificateEditor.vue:160
 #: src/views/certificate/CertificateList/certColumns.tsx:9
 #: src/views/certificate/CertificateList/certColumns.tsx:9
 #: src/views/certificate/DNSCredential.vue:9
 #: src/views/certificate/DNSCredential.vue:9
 #: src/views/config/components/ConfigRightPanel/Basic.vue:34
 #: src/views/config/components/ConfigRightPanel/Basic.vue:34
@@ -2892,7 +2922,7 @@ msgstr "새 경로"
 msgid "New version released"
 msgid "New version released"
 msgstr "새 버전 출시"
 msgstr "새 버전 출시"
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:89
+#: src/views/certificate/components/DNSIssueCertificate.vue:181
 #: src/views/install/components/InstallView.vue:96
 #: src/views/install/components/InstallView.vue:96
 #: src/views/site/site_add/SiteAdd.vue:132
 #: src/views/site/site_add/SiteAdd.vue:132
 #: src/views/site/site_edit/components/Cert/ObtainCert.vue:214
 #: src/views/site/site_edit/components/Cert/ObtainCert.vue:214
@@ -3467,6 +3497,10 @@ msgstr "생성하려는 패스키의 이름을 입력하고 아래의 확인 버
 msgid "Please enter a valid port range"
 msgid "Please enter a valid port range"
 msgstr "유효한 포트 범위를 입력하세요"
 msgstr "유효한 포트 범위를 입력하세요"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:74
+msgid "Please enter at least one domain"
+msgstr "최소 하나의 도메인을 입력해 주세요"
+
 #: src/components/TwoFA/Authorization.vue:85
 #: src/components/TwoFA/Authorization.vue:85
 msgid "Please enter the OTP code:"
 msgid "Please enter the OTP code:"
 msgstr "OTP 코드를 입력해 주세요:"
 msgstr "OTP 코드를 입력해 주세요:"
@@ -3792,6 +3826,7 @@ msgstr "리로딩 중"
 msgid "Reloading nginx"
 msgid "Reloading nginx"
 msgstr "Nginx 리로딩 중"
 msgstr "Nginx 리로딩 중"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:144
 #: src/views/preference/tabs/AuthSettings.vue:137
 #: src/views/preference/tabs/AuthSettings.vue:137
 msgid "Remove"
 msgid "Remove"
 msgstr "제거"
 msgstr "제거"
@@ -3874,8 +3909,8 @@ msgstr "이름 변경 성공"
 msgid "Renamed successfully"
 msgid "Renamed successfully"
 msgstr "이름 변경 성공"
 msgstr "이름 변경 성공"
 
 
-#: src/views/certificate/components/RenewCert.vue:46
-#: src/views/certificate/components/RenewCert.vue:53
+#: src/views/certificate/components/RenewCert.vue:48
+#: src/views/certificate/components/RenewCert.vue:55
 msgid "Renew Certificate"
 msgid "Renew Certificate"
 msgstr "인증서 갱신"
 msgstr "인증서 갱신"
 
 
@@ -3887,8 +3922,8 @@ msgstr "인증서 갱신 오류"
 msgid "Renew Certificate Success"
 msgid "Renew Certificate Success"
 msgstr "인증서 갱신 성공"
 msgstr "인증서 갱신 성공"
 
 
-#: src/views/certificate/components/RenewCert.vue:28
-#: src/views/certificate/components/WildcardCertificate.vue:46
+#: src/views/certificate/components/DNSIssueCertificate.vue:84
+#: src/views/certificate/components/RenewCert.vue:30
 msgid "Renew successfully"
 msgid "Renew successfully"
 msgstr "성공적으로 갱신됨"
 msgstr "성공적으로 갱신됨"
 
 
@@ -4144,7 +4179,7 @@ msgstr "토요일"
 
 
 #: src/components/ChatGPT/ChatMessage.vue:215
 #: src/components/ChatGPT/ChatMessage.vue:215
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:129
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:129
-#: src/language/curd.ts:18 src/views/certificate/CertificateEditor.vue:266
+#: src/language/curd.ts:18 src/views/certificate/CertificateEditor.vue:264
 #: src/views/config/components/ConfigLeftPanel.vue:282
 #: src/views/config/components/ConfigLeftPanel.vue:282
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/preference/components/AuthSettings/Passkey.vue:130
 #: src/views/preference/components/AuthSettings/Passkey.vue:130
@@ -4199,7 +4234,7 @@ msgstr "스트림 %{name}을(를) %{node}에 저장하지 못했습니다"
 msgid "Save stream %{name} to %{node} successfully"
 msgid "Save stream %{name} to %{node} successfully"
 msgstr "스트림 %{name}을(를) %{node}에 성공적으로 저장했습니다"
 msgstr "스트림 %{name}을(를) %{node}에 성공적으로 저장했습니다"
 
 
-#: src/language/curd.ts:35 src/views/certificate/CertificateEditor.vue:49
+#: src/language/curd.ts:35 src/views/certificate/store.ts:13
 #: src/views/preference/store/index.ts:118
 #: src/views/preference/store/index.ts:118
 msgid "Save successfully"
 msgid "Save successfully"
 msgstr "성공적으로 저장되었습니다"
 msgstr "성공적으로 저장되었습니다"
@@ -4307,6 +4342,10 @@ msgstr "보내기"
 msgid "Server"
 msgid "Server"
 msgstr "서버"
 msgstr "서버"
 
 
+#: src/views/certificate/CertificateEditor.vue:55
+msgid "Server error"
+msgstr "서버 오류"
+
 #: src/views/dashboard/ServerAnalytic.vue:175
 #: src/views/dashboard/ServerAnalytic.vue:175
 msgid "Server Info"
 msgid "Server Info"
 msgstr "서버 정보"
 msgstr "서버 정보"
@@ -4441,7 +4480,7 @@ msgstr "캐시 로더 반복 사이의 대기 시간"
 msgid "Sleep time between cache manager iterations"
 msgid "Sleep time between cache manager iterations"
 msgstr "캐시 관리자 반복 간 대기 시간"
 msgstr "캐시 관리자 반복 간 대기 시간"
 
 
-#: src/views/certificate/CertificateEditor.vue:213
+#: src/views/certificate/CertificateEditor.vue:211
 msgid "SSL Certificate Content"
 msgid "SSL Certificate Content"
 msgstr "SSL 인증서 내용"
 msgstr "SSL 인증서 내용"
 
 
@@ -4453,15 +4492,15 @@ msgstr "SSL 인증서 파일은 Nginx 구성 디렉터리 아래에 있어야 
 msgid "SSL certificate file not found"
 msgid "SSL certificate file not found"
 msgstr "SSL 인증서 파일을 찾을 수 없음"
 msgstr "SSL 인증서 파일을 찾을 수 없음"
 
 
-#: src/views/certificate/CertificateEditor.vue:227
+#: src/views/certificate/CertificateEditor.vue:225
 msgid "SSL Certificate Key Content"
 msgid "SSL Certificate Key Content"
 msgstr "SSL 인증서키 콘텐츠"
 msgstr "SSL 인증서키 콘텐츠"
 
 
-#: src/views/certificate/CertificateEditor.vue:192
+#: src/views/certificate/CertificateEditor.vue:190
 msgid "SSL Certificate Key Path"
 msgid "SSL Certificate Key Path"
 msgstr "SSL 인증서 키 경로"
 msgstr "SSL 인증서 키 경로"
 
 
-#: src/views/certificate/CertificateEditor.vue:177
+#: src/views/certificate/CertificateEditor.vue:175
 #: src/views/preference/tabs/ServerSettings.vue:37
 #: src/views/preference/tabs/ServerSettings.vue:37
 msgid "SSL Certificate Path"
 msgid "SSL Certificate Path"
 msgstr "SSL 인증서 경로"
 msgstr "SSL 인증서 경로"
@@ -4694,7 +4733,7 @@ msgstr "동기화 노드"
 msgid "Sync strategy"
 msgid "Sync strategy"
 msgstr "동기화 전략"
 msgstr "동기화 전략"
 
 
-#: src/views/certificate/CertificateEditor.vue:206
+#: src/views/certificate/CertificateEditor.vue:204
 msgid "Sync to"
 msgid "Sync to"
 msgstr "동기화 대상"
 msgstr "동기화 대상"
 
 
@@ -4765,11 +4804,11 @@ msgid ""
 "dashes, colons, and dots."
 "dashes, colons, and dots."
 msgstr "ICP 번호는 문자, 유니코드, 숫자, 하이픈, 대시, 콜론 및 점만 포함해야 합니다."
 msgstr "ICP 번호는 문자, 유니코드, 숫자, 하이픈, 대시, 콜론 및 점만 포함해야 합니다."
 
 
-#: src/views/certificate/CertificateEditor.vue:216
+#: src/views/certificate/CertificateEditor.vue:214
 msgid "The input is not a SSL Certificate"
 msgid "The input is not a SSL Certificate"
 msgstr "입력이 SSL 인증서가 아닙니다"
 msgstr "입력이 SSL 인증서가 아닙니다"
 
 
-#: src/views/certificate/CertificateEditor.vue:230
+#: src/views/certificate/CertificateEditor.vue:228
 msgid "The input is not a SSL Certificate Key"
 msgid "The input is not a SSL Certificate Key"
 msgstr "입력한 내용이 SSL 인증서 키가 아닙니다"
 msgstr "입력한 내용이 SSL 인증서 키가 아닙니다"
 
 
@@ -4800,11 +4839,11 @@ msgstr "노드 이름에는 문자, 유니코드, 숫자, 하이픈, 대시, 콜
 msgid "The parameter of server_name is required"
 msgid "The parameter of server_name is required"
 msgstr "server_name 매개변수가 필요합니다"
 msgstr "server_name 매개변수가 필요합니다"
 
 
-#: src/views/certificate/CertificateEditor.vue:181
+#: src/views/certificate/CertificateEditor.vue:179
 msgid "The path exists, but the file is not a certificate"
 msgid "The path exists, but the file is not a certificate"
 msgstr "경로는 존재하지만, 파일이 인증서가 아닙니다"
 msgstr "경로는 존재하지만, 파일이 인증서가 아닙니다"
 
 
-#: src/views/certificate/CertificateEditor.vue:196
+#: src/views/certificate/CertificateEditor.vue:194
 msgid "The path exists, but the file is not a private key"
 msgid "The path exists, but the file is not a private key"
 msgstr "경로는 존재하지만 파일은 개인 키가 아닙니다"
 msgstr "경로는 존재하지만 파일은 개인 키가 아닙니다"
 
 
@@ -4860,17 +4899,17 @@ msgstr ""
 "이 코드들은 비밀번호와 두 번째 요소를 잃어버린 경우 계정에 접근할 수 있는 최후의 수단입니다. 이 코드들을 찾을 수 없다면 계정에 "
 "이 코드들은 비밀번호와 두 번째 요소를 잃어버린 경우 계정에 접근할 수 있는 최후의 수단입니다. 이 코드들을 찾을 수 없다면 계정에 "
 "대한 접근 권한을 잃게 됩니다."
 "대한 접근 권한을 잃게 됩니다."
 
 
-#: src/views/certificate/CertificateEditor.vue:102
+#: src/views/certificate/CertificateEditor.vue:100
 msgid "This Auto Cert item is invalid, please remove it."
 msgid "This Auto Cert item is invalid, please remove it."
 msgstr "이 자동 인증 항목이 유효하지 않습니다. 제거해주세요."
 msgstr "이 자동 인증 항목이 유효하지 않습니다. 제거해주세요."
 
 
-#: src/views/certificate/CertificateEditor.vue:92
+#: src/views/certificate/CertificateEditor.vue:90
 msgid "This certificate is managed by Nginx UI"
 msgid "This certificate is managed by Nginx UI"
 msgstr "이 인증서는 Nginx UI에서 관리됩니다"
 msgstr "이 인증서는 Nginx UI에서 관리됩니다"
 
 
-#: src/views/certificate/CertificateEditor.vue:165
-#: src/views/certificate/CertificateEditor.vue:179
-#: src/views/certificate/CertificateEditor.vue:194
+#: src/views/certificate/CertificateEditor.vue:163
+#: src/views/certificate/CertificateEditor.vue:177
+#: src/views/certificate/CertificateEditor.vue:192
 msgid "This field is required"
 msgid "This field is required"
 msgstr "이 필드는 필수입니다"
 msgstr "이 필드는 필수입니다"
 
 
@@ -5315,6 +5354,10 @@ msgstr "새로운 복구 코드를 생성할 때는 반드시 새 코드를 다
 msgid "Whether to use a temporary path when writing temporary files"
 msgid "Whether to use a temporary path when writing temporary files"
 msgstr "임시 파일을 작성할 때 임시 경로를 사용할지 여부"
 msgstr "임시 파일을 작성할 때 임시 경로를 사용할지 여부"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:107
+msgid "Wildcard Certificate"
+msgstr "와일드카드 인증서"
+
 #: src/views/dashboard/components/ParamsOpt/PerformanceConfig.vue:48
 #: src/views/dashboard/components/ParamsOpt/PerformanceConfig.vue:48
 msgid "Worker Connections"
 msgid "Worker Connections"
 msgstr "작업자 연결"
 msgstr "작업자 연결"
@@ -5616,9 +5659,6 @@ msgstr "귀하의 패스키"
 #~ msgid "Incorrect username or password"
 #~ msgid "Incorrect username or password"
 #~ msgstr "사용자 이름 또는 비밀번호가 올바르지 않습니다"
 #~ msgstr "사용자 이름 또는 비밀번호가 올바르지 않습니다"
 
 
-#~ msgid "Server error"
-#~ msgstr "서버 오류"
-
 #, fuzzy
 #, fuzzy
 #~ msgid ""
 #~ msgid ""
 #~ "Rename %{orig_path} to %{new_path} on %{env_name} failed, please upgrade "
 #~ "Rename %{orig_path} to %{new_path} on %{env_name} failed, please upgrade "

+ 77 - 36
app/src/language/messages.pot

@@ -170,6 +170,10 @@ msgstr ""
 msgid "Add Directive Below"
 msgid "Add Directive Below"
 msgstr ""
 msgstr ""
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:151
+msgid "Add Domain"
+msgstr ""
+
 #: src/components/NgxConfigEditor/LocationEditor.vue:131
 #: src/components/NgxConfigEditor/LocationEditor.vue:131
 #: src/components/NgxConfigEditor/LocationEditor.vue:158
 #: src/components/NgxConfigEditor/LocationEditor.vue:158
 msgid "Add Location"
 msgid "Add Location"
@@ -218,6 +222,10 @@ msgstr ""
 msgid "All Recovery Codes Have Been Used"
 msgid "All Recovery Codes Have Been Used"
 msgstr ""
 msgstr ""
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:156
+msgid "All selected subdomains must belong to the same DNS Provider, otherwise the certificate application will fail."
+msgstr ""
+
 #: src/views/preference/tabs/OpenAISettings.vue:32
 #: src/views/preference/tabs/OpenAISettings.vue:32
 msgid "API Base Url"
 msgid "API Base Url"
 msgstr ""
 msgstr ""
@@ -380,7 +388,7 @@ msgstr ""
 msgid "Auto-renewal enabled for %{name}"
 msgid "Auto-renewal enabled for %{name}"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/components/RenewCert.vue:49
+#: src/views/certificate/components/RenewCert.vue:51
 #: src/views/site/site_edit/components/Cert/IssueCert.vue:84
 #: src/views/site/site_edit/components/Cert/IssueCert.vue:84
 msgid "AutoCert is running, please wait..."
 msgid "AutoCert is running, please wait..."
 msgstr ""
 msgstr ""
@@ -393,7 +401,7 @@ msgstr ""
 msgid "Automatic Restart"
 msgid "Automatic Restart"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/CertificateEditor.vue:259
+#: src/views/certificate/CertificateEditor.vue:257
 #: src/views/config/components/ConfigLeftPanel.vue:273
 #: src/views/config/components/ConfigLeftPanel.vue:273
 #: src/views/config/ConfigList.vue:112
 #: src/views/config/ConfigList.vue:112
 #: src/views/config/ConfigList.vue:195
 #: src/views/config/ConfigList.vue:195
@@ -684,13 +692,17 @@ msgstr ""
 msgid "Certificate revoked successfully"
 msgid "Certificate revoked successfully"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/CertificateEditor.vue:128
+#: src/views/certificate/CertificateEditor.vue:126
 #: src/views/site/site_edit/components/Cert/Cert.vue:58
 #: src/views/site/site_edit/components/Cert/Cert.vue:58
 msgid "Certificate Status"
 msgid "Certificate Status"
 msgid_plural "Certificates Status"
 msgid_plural "Certificates Status"
 msgstr[0] ""
 msgstr[0] ""
 msgstr[1] ""
 msgstr[1] ""
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:104
+msgid "Certificate Type"
+msgstr ""
+
 #: src/routes/modules/certificates.ts:11
 #: src/routes/modules/certificates.ts:11
 #: src/views/certificate/CertificateList/Certificate.vue:19
 #: src/views/certificate/CertificateList/Certificate.vue:19
 msgid "Certificates"
 msgid "Certificates"
@@ -1110,6 +1122,14 @@ msgstr ""
 msgid "Custom Directory"
 msgid "Custom Directory"
 msgstr ""
 msgstr ""
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:126
+msgid "Custom Domains"
+msgstr ""
+
+#: src/views/certificate/components/DNSIssueCertificate.vue:110
+msgid "Custom Domains Certificate"
+msgstr ""
+
 #: src/views/preference/tabs/NodeSettings.vue:19
 #: src/views/preference/tabs/NodeSettings.vue:19
 msgid "Customize the name of local node to be displayed in the environment indicator."
 msgid "Customize the name of local node to be displayed in the environment indicator."
 msgstr ""
 msgstr ""
@@ -1423,11 +1443,11 @@ msgid_plural "Documents"
 msgstr[0] ""
 msgstr[0] ""
 msgstr[1] ""
 msgstr[1] ""
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:66
+#: src/views/certificate/components/DNSIssueCertificate.vue:116
 msgid "Domain"
 msgid "Domain"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/CertificateEditor.vue:112
+#: src/views/certificate/CertificateEditor.vue:110
 msgid "Domains list is empty, try to reopen Auto Cert for %{config}"
 msgid "Domains list is empty, try to reopen Auto Cert for %{config}"
 msgstr ""
 msgstr ""
 
 
@@ -1626,6 +1646,14 @@ msgstr ""
 msgid "End"
 msgid "End"
 msgstr ""
 msgstr ""
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:135
+msgid "Enter domain name"
+msgstr ""
+
+#: src/views/certificate/components/DNSIssueCertificate.vue:120
+msgid "Enter your domain"
+msgstr ""
+
 #: src/language/constants.ts:22
 #: src/language/constants.ts:22
 msgid "Environment variables cleaned"
 msgid "Environment variables cleaned"
 msgstr ""
 msgstr ""
@@ -1701,7 +1729,7 @@ msgstr ""
 msgid "External Notify"
 msgid "External Notify"
 msgstr ""
 msgstr ""
 
 
-#: src/views/site/site_edit/components/Cert/ObtainCertLive.vue:80
+#: src/views/site/site_edit/components/Cert/ObtainCertLive.vue:81
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
 msgstr ""
 msgstr ""
 
 
@@ -2215,7 +2243,7 @@ msgid "Import"
 msgstr ""
 msgstr ""
 
 
 #: src/routes/modules/certificates.ts:46
 #: src/routes/modules/certificates.ts:46
-#: src/views/certificate/CertificateEditor.vue:85
+#: src/views/certificate/CertificateEditor.vue:83
 msgid "Import Certificate"
 msgid "Import Certificate"
 msgstr ""
 msgstr ""
 
 
@@ -2353,11 +2381,11 @@ msgid "IP"
 msgstr ""
 msgstr ""
 
 
 #: src/views/certificate/CertificateList/Certificate.vue:37
 #: src/views/certificate/CertificateList/Certificate.vue:37
-msgid "Issue wildcard certificate"
+msgid "Issue certificate"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:57
-msgid "Issue Wildcard Certificate"
+#: src/views/certificate/components/DNSIssueCertificate.vue:95
+msgid "Issue Certificate"
 msgstr ""
 msgstr ""
 
 
 #: src/language/constants.ts:20
 #: src/language/constants.ts:20
@@ -2437,8 +2465,8 @@ msgstr ""
 msgid "Leave blank if you don't need this."
 msgid "Leave blank if you don't need this."
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/CertificateEditor.vue:223
-#: src/views/certificate/CertificateEditor.vue:237
+#: src/views/certificate/CertificateEditor.vue:221
+#: src/views/certificate/CertificateEditor.vue:235
 msgid "Leave blank will not change anything"
 msgid "Leave blank will not change anything"
 msgstr ""
 msgstr ""
 
 
@@ -2525,7 +2553,7 @@ msgstr ""
 msgid "Locations"
 msgid "Locations"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/CertificateEditor.vue:247
+#: src/views/certificate/CertificateEditor.vue:245
 msgid "Log"
 msgid "Log"
 msgstr ""
 msgstr ""
 
 
@@ -2722,7 +2750,7 @@ msgid "Modify"
 msgstr ""
 msgstr ""
 
 
 #: src/routes/modules/certificates.ts:36
 #: src/routes/modules/certificates.ts:36
-#: src/views/certificate/CertificateEditor.vue:85
+#: src/views/certificate/CertificateEditor.vue:83
 msgid "Modify Certificate"
 msgid "Modify Certificate"
 msgstr ""
 msgstr ""
 
 
@@ -2757,7 +2785,7 @@ msgstr ""
 #: src/components/NgxConfigEditor/NgxUpstream.vue:199
 #: src/components/NgxConfigEditor/NgxUpstream.vue:199
 #: src/views/backup/AutoBackup/AutoBackup.vue:11
 #: src/views/backup/AutoBackup/AutoBackup.vue:11
 #: src/views/certificate/ACMEUser.vue:11
 #: src/views/certificate/ACMEUser.vue:11
-#: src/views/certificate/CertificateEditor.vue:162
+#: src/views/certificate/CertificateEditor.vue:160
 #: src/views/certificate/CertificateList/certColumns.tsx:9
 #: src/views/certificate/CertificateList/certColumns.tsx:9
 #: src/views/certificate/DNSCredential.vue:9
 #: src/views/certificate/DNSCredential.vue:9
 #: src/views/config/components/ConfigRightPanel/Basic.vue:34
 #: src/views/config/components/ConfigRightPanel/Basic.vue:34
@@ -2817,7 +2845,7 @@ msgstr ""
 msgid "New version released"
 msgid "New version released"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:89
+#: src/views/certificate/components/DNSIssueCertificate.vue:181
 #: src/views/install/components/InstallView.vue:96
 #: src/views/install/components/InstallView.vue:96
 #: src/views/site/site_add/SiteAdd.vue:132
 #: src/views/site/site_add/SiteAdd.vue:132
 #: src/views/site/site_edit/components/Cert/ObtainCert.vue:214
 #: src/views/site/site_edit/components/Cert/ObtainCert.vue:214
@@ -3388,6 +3416,10 @@ msgstr ""
 msgid "Please enter a valid port range"
 msgid "Please enter a valid port range"
 msgstr ""
 msgstr ""
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:74
+msgid "Please enter at least one domain"
+msgstr ""
+
 #: src/components/TwoFA/Authorization.vue:85
 #: src/components/TwoFA/Authorization.vue:85
 msgid "Please enter the OTP code:"
 msgid "Please enter the OTP code:"
 msgstr ""
 msgstr ""
@@ -3705,6 +3737,7 @@ msgstr ""
 msgid "Reloading nginx"
 msgid "Reloading nginx"
 msgstr ""
 msgstr ""
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:144
 #: src/views/preference/tabs/AuthSettings.vue:137
 #: src/views/preference/tabs/AuthSettings.vue:137
 msgid "Remove"
 msgid "Remove"
 msgstr ""
 msgstr ""
@@ -3789,8 +3822,8 @@ msgstr ""
 msgid "Renamed successfully"
 msgid "Renamed successfully"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/components/RenewCert.vue:46
-#: src/views/certificate/components/RenewCert.vue:53
+#: src/views/certificate/components/RenewCert.vue:48
+#: src/views/certificate/components/RenewCert.vue:55
 msgid "Renew Certificate"
 msgid "Renew Certificate"
 msgstr ""
 msgstr ""
 
 
@@ -3802,8 +3835,8 @@ msgstr ""
 msgid "Renew Certificate Success"
 msgid "Renew Certificate Success"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/components/RenewCert.vue:28
-#: src/views/certificate/components/WildcardCertificate.vue:46
+#: src/views/certificate/components/DNSIssueCertificate.vue:84
+#: src/views/certificate/components/RenewCert.vue:30
 msgid "Renew successfully"
 msgid "Renew successfully"
 msgstr ""
 msgstr ""
 
 
@@ -4054,7 +4087,7 @@ msgstr ""
 #: src/components/ChatGPT/ChatMessage.vue:215
 #: src/components/ChatGPT/ChatMessage.vue:215
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:129
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:129
 #: src/language/curd.ts:18
 #: src/language/curd.ts:18
-#: src/views/certificate/CertificateEditor.vue:266
+#: src/views/certificate/CertificateEditor.vue:264
 #: src/views/config/components/ConfigLeftPanel.vue:282
 #: src/views/config/components/ConfigLeftPanel.vue:282
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/preference/components/AuthSettings/Passkey.vue:130
 #: src/views/preference/components/AuthSettings/Passkey.vue:130
@@ -4110,7 +4143,7 @@ msgid "Save stream %{name} to %{node} successfully"
 msgstr ""
 msgstr ""
 
 
 #: src/language/curd.ts:35
 #: src/language/curd.ts:35
-#: src/views/certificate/CertificateEditor.vue:49
+#: src/views/certificate/store.ts:13
 #: src/views/preference/store/index.ts:118
 #: src/views/preference/store/index.ts:118
 msgid "Save successfully"
 msgid "Save successfully"
 msgstr ""
 msgstr ""
@@ -4222,6 +4255,10 @@ msgstr ""
 msgid "Server"
 msgid "Server"
 msgstr ""
 msgstr ""
 
 
+#: src/views/certificate/CertificateEditor.vue:55
+msgid "Server error"
+msgstr ""
+
 #: src/views/dashboard/ServerAnalytic.vue:175
 #: src/views/dashboard/ServerAnalytic.vue:175
 msgid "Server Info"
 msgid "Server Info"
 msgstr ""
 msgstr ""
@@ -4346,7 +4383,7 @@ msgstr ""
 msgid "Sleep time between cache manager iterations"
 msgid "Sleep time between cache manager iterations"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/CertificateEditor.vue:213
+#: src/views/certificate/CertificateEditor.vue:211
 msgid "SSL Certificate Content"
 msgid "SSL Certificate Content"
 msgstr ""
 msgstr ""
 
 
@@ -4358,15 +4395,15 @@ msgstr ""
 msgid "SSL certificate file not found"
 msgid "SSL certificate file not found"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/CertificateEditor.vue:227
+#: src/views/certificate/CertificateEditor.vue:225
 msgid "SSL Certificate Key Content"
 msgid "SSL Certificate Key Content"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/CertificateEditor.vue:192
+#: src/views/certificate/CertificateEditor.vue:190
 msgid "SSL Certificate Key Path"
 msgid "SSL Certificate Key Path"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/CertificateEditor.vue:177
+#: src/views/certificate/CertificateEditor.vue:175
 #: src/views/preference/tabs/ServerSettings.vue:37
 #: src/views/preference/tabs/ServerSettings.vue:37
 msgid "SSL Certificate Path"
 msgid "SSL Certificate Path"
 msgstr ""
 msgstr ""
@@ -4592,7 +4629,7 @@ msgstr ""
 msgid "Sync strategy"
 msgid "Sync strategy"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/CertificateEditor.vue:206
+#: src/views/certificate/CertificateEditor.vue:204
 msgid "Sync to"
 msgid "Sync to"
 msgstr ""
 msgstr ""
 
 
@@ -4659,11 +4696,11 @@ msgstr ""
 msgid "The ICP Number should only contain letters, unicode, numbers, hyphens, dashes, colons, and dots."
 msgid "The ICP Number should only contain letters, unicode, numbers, hyphens, dashes, colons, and dots."
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/CertificateEditor.vue:216
+#: src/views/certificate/CertificateEditor.vue:214
 msgid "The input is not a SSL Certificate"
 msgid "The input is not a SSL Certificate"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/CertificateEditor.vue:230
+#: src/views/certificate/CertificateEditor.vue:228
 msgid "The input is not a SSL Certificate Key"
 msgid "The input is not a SSL Certificate Key"
 msgstr ""
 msgstr ""
 
 
@@ -4688,11 +4725,11 @@ msgstr ""
 msgid "The parameter of server_name is required"
 msgid "The parameter of server_name is required"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/CertificateEditor.vue:181
+#: src/views/certificate/CertificateEditor.vue:179
 msgid "The path exists, but the file is not a certificate"
 msgid "The path exists, but the file is not a certificate"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/CertificateEditor.vue:196
+#: src/views/certificate/CertificateEditor.vue:194
 msgid "The path exists, but the file is not a private key"
 msgid "The path exists, but the file is not a private key"
 msgstr ""
 msgstr ""
 
 
@@ -4734,17 +4771,17 @@ msgstr ""
 msgid "These codes are the last resort for accessing your account in case you lose your password and second factors. If you cannot find these codes, you will lose access to your account."
 msgid "These codes are the last resort for accessing your account in case you lose your password and second factors. If you cannot find these codes, you will lose access to your account."
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/CertificateEditor.vue:102
+#: src/views/certificate/CertificateEditor.vue:100
 msgid "This Auto Cert item is invalid, please remove it."
 msgid "This Auto Cert item is invalid, please remove it."
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/CertificateEditor.vue:92
+#: src/views/certificate/CertificateEditor.vue:90
 msgid "This certificate is managed by Nginx UI"
 msgid "This certificate is managed by Nginx UI"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/CertificateEditor.vue:165
-#: src/views/certificate/CertificateEditor.vue:179
-#: src/views/certificate/CertificateEditor.vue:194
+#: src/views/certificate/CertificateEditor.vue:163
+#: src/views/certificate/CertificateEditor.vue:177
+#: src/views/certificate/CertificateEditor.vue:192
 msgid "This field is required"
 msgid "This field is required"
 msgstr ""
 msgstr ""
 
 
@@ -5149,6 +5186,10 @@ msgstr ""
 msgid "Whether to use a temporary path when writing temporary files"
 msgid "Whether to use a temporary path when writing temporary files"
 msgstr ""
 msgstr ""
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:107
+msgid "Wildcard Certificate"
+msgstr ""
+
 #: src/views/dashboard/components/ParamsOpt/PerformanceConfig.vue:48
 #: src/views/dashboard/components/ParamsOpt/PerformanceConfig.vue:48
 msgid "Worker Connections"
 msgid "Worker Connections"
 msgstr ""
 msgstr ""

+ 84 - 42
app/src/language/pt_PT/app.po

@@ -181,6 +181,10 @@ msgstr "Adicionar Configuração"
 msgid "Add Directive Below"
 msgid "Add Directive Below"
 msgstr "Adicionar Directiva Abaixo"
 msgstr "Adicionar Directiva Abaixo"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:151
+msgid "Add Domain"
+msgstr "Adicionar domínio"
+
 #: src/components/NgxConfigEditor/LocationEditor.vue:131
 #: src/components/NgxConfigEditor/LocationEditor.vue:131
 #: src/components/NgxConfigEditor/LocationEditor.vue:158
 #: src/components/NgxConfigEditor/LocationEditor.vue:158
 msgid "Add Location"
 msgid "Add Location"
@@ -230,6 +234,14 @@ msgstr "Todos"
 msgid "All Recovery Codes Have Been Used"
 msgid "All Recovery Codes Have Been Used"
 msgstr "Todos os Códigos de Recuperação Foram Utilizados"
 msgstr "Todos os Códigos de Recuperação Foram Utilizados"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:156
+msgid ""
+"All selected subdomains must belong to the same DNS Provider, otherwise the "
+"certificate application will fail."
+msgstr ""
+"Todos os subdomínios selecionados devem pertencer ao mesmo Fornecedor de "
+"DNS, caso contrário, o pedido de certificado falhará."
+
 #: src/views/preference/tabs/OpenAISettings.vue:32
 #: src/views/preference/tabs/OpenAISettings.vue:32
 msgid "API Base Url"
 msgid "API Base Url"
 msgstr "Url Base da API"
 msgstr "Url Base da API"
@@ -256,7 +268,7 @@ msgstr "Aplicação"
 
 
 #: src/views/system/Upgrade.vue:195
 #: src/views/system/Upgrade.vue:195
 msgid "Arch"
 msgid "Arch"
-msgstr "\"Arquitetura\""
+msgstr "Arquitetura"
 
 
 #: src/views/preference/tabs/AuthSettings.vue:130
 #: src/views/preference/tabs/AuthSettings.vue:130
 msgid "Are you sure to delete this banned IP immediately?"
 msgid "Are you sure to delete this banned IP immediately?"
@@ -395,7 +407,7 @@ msgstr "Renovação automatica desactivada para %{name}"
 msgid "Auto-renewal enabled for %{name}"
 msgid "Auto-renewal enabled for %{name}"
 msgstr "Renovação automática activada para %{name}"
 msgstr "Renovação automática activada para %{name}"
 
 
-#: src/views/certificate/components/RenewCert.vue:49
+#: src/views/certificate/components/RenewCert.vue:51
 #: src/views/site/site_edit/components/Cert/IssueCert.vue:84
 #: src/views/site/site_edit/components/Cert/IssueCert.vue:84
 msgid "AutoCert is running, please wait..."
 msgid "AutoCert is running, please wait..."
 msgstr "O AutoCert está em execução, aguarde..."
 msgstr "O AutoCert está em execução, aguarde..."
@@ -408,7 +420,7 @@ msgstr "\"AutoCert está em execução...\""
 msgid "Automatic Restart"
 msgid "Automatic Restart"
 msgstr "Reinício Automático"
 msgstr "Reinício Automático"
 
 
-#: src/views/certificate/CertificateEditor.vue:259
+#: src/views/certificate/CertificateEditor.vue:257
 #: src/views/config/components/ConfigLeftPanel.vue:273
 #: src/views/config/components/ConfigLeftPanel.vue:273
 #: src/views/config/ConfigList.vue:112 src/views/config/ConfigList.vue:195
 #: src/views/config/ConfigList.vue:112 src/views/config/ConfigList.vue:195
 #: src/views/nginx_log/NginxLog.vue:174
 #: src/views/nginx_log/NginxLog.vue:174
@@ -709,13 +721,17 @@ msgstr "Certificado renovado com sucesso"
 msgid "Certificate revoked successfully"
 msgid "Certificate revoked successfully"
 msgstr "Certificado revogado com sucesso"
 msgstr "Certificado revogado com sucesso"
 
 
-#: src/views/certificate/CertificateEditor.vue:128
+#: src/views/certificate/CertificateEditor.vue:126
 #: src/views/site/site_edit/components/Cert/Cert.vue:58
 #: src/views/site/site_edit/components/Cert/Cert.vue:58
 msgid "Certificate Status"
 msgid "Certificate Status"
 msgid_plural "Certificates Status"
 msgid_plural "Certificates Status"
 msgstr[0] "Estado do Certificado"
 msgstr[0] "Estado do Certificado"
 msgstr[1] "Estado dos Certificados"
 msgstr[1] "Estado dos Certificados"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:104
+msgid "Certificate Type"
+msgstr "Tipo de certificado"
+
 #: src/routes/modules/certificates.ts:11
 #: src/routes/modules/certificates.ts:11
 #: src/views/certificate/CertificateList/Certificate.vue:19
 #: src/views/certificate/CertificateList/Certificate.vue:19
 msgid "Certificates"
 msgid "Certificates"
@@ -1206,6 +1222,14 @@ msgstr "Expressão cron personalizada"
 msgid "Custom Directory"
 msgid "Custom Directory"
 msgstr "Diretório personalizado"
 msgstr "Diretório personalizado"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:126
+msgid "Custom Domains"
+msgstr "Domínios personalizados"
+
+#: src/views/certificate/components/DNSIssueCertificate.vue:110
+msgid "Custom Domains Certificate"
+msgstr "Certificado de Domínios Personalizados"
+
 #: src/views/preference/tabs/NodeSettings.vue:19
 #: src/views/preference/tabs/NodeSettings.vue:19
 msgid ""
 msgid ""
 "Customize the name of local node to be displayed in the environment "
 "Customize the name of local node to be displayed in the environment "
@@ -1515,11 +1539,11 @@ msgid "Document"
 msgid_plural "Documents"
 msgid_plural "Documents"
 msgstr[0] "Documento"
 msgstr[0] "Documento"
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:66
+#: src/views/certificate/components/DNSIssueCertificate.vue:116
 msgid "Domain"
 msgid "Domain"
 msgstr "Domínio"
 msgstr "Domínio"
 
 
-#: src/views/certificate/CertificateEditor.vue:112
+#: src/views/certificate/CertificateEditor.vue:110
 msgid "Domains list is empty, try to reopen Auto Cert for %{config}"
 msgid "Domains list is empty, try to reopen Auto Cert for %{config}"
 msgstr "A lista de domínios está vazia, tente reabrir o Auto Cert para %{config}"
 msgstr "A lista de domínios está vazia, tente reabrir o Auto Cert para %{config}"
 
 
@@ -1722,6 +1746,14 @@ msgstr "Encriptar website com Let's Encrypt"
 msgid "End"
 msgid "End"
 msgstr "Fim"
 msgstr "Fim"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:135
+msgid "Enter domain name"
+msgstr "Inserir nome de domínio"
+
+#: src/views/certificate/components/DNSIssueCertificate.vue:120
+msgid "Enter your domain"
+msgstr "Insira o seu domínio"
+
 #: src/language/constants.ts:22
 #: src/language/constants.ts:22
 msgid "Environment variables cleaned"
 msgid "Environment variables cleaned"
 msgstr "Variáveis de ambiente limpas"
 msgstr "Variáveis de ambiente limpas"
@@ -1796,7 +1828,7 @@ msgstr "Contentor Docker externo"
 msgid "External Notify"
 msgid "External Notify"
 msgstr "Notificação Externa"
 msgstr "Notificação Externa"
 
 
-#: src/views/site/site_edit/components/Cert/ObtainCertLive.vue:80
+#: src/views/site/site_edit/components/Cert/ObtainCertLive.vue:81
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
 msgstr "Obtenção de Certificado Falhou"
 msgstr "Obtenção de Certificado Falhou"
 
 
@@ -2326,7 +2358,7 @@ msgid "Import"
 msgstr "Importar"
 msgstr "Importar"
 
 
 #: src/routes/modules/certificates.ts:46
 #: src/routes/modules/certificates.ts:46
-#: src/views/certificate/CertificateEditor.vue:85
+#: src/views/certificate/CertificateEditor.vue:83
 msgid "Import Certificate"
 msgid "Import Certificate"
 msgstr "Importar Certificados"
 msgstr "Importar Certificados"
 
 
@@ -2471,12 +2503,12 @@ msgid "IP"
 msgstr "IP"
 msgstr "IP"
 
 
 #: src/views/certificate/CertificateList/Certificate.vue:37
 #: src/views/certificate/CertificateList/Certificate.vue:37
-msgid "Issue wildcard certificate"
-msgstr "Emitir certificado wildcard"
+msgid "Issue certificate"
+msgstr "Emitir certificado"
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:57
-msgid "Issue Wildcard Certificate"
-msgstr "Emitir Certificado Wildcard"
+#: src/views/certificate/components/DNSIssueCertificate.vue:95
+msgid "Issue Certificate"
+msgstr "Emitir certificado"
 
 
 #: src/language/constants.ts:20
 #: src/language/constants.ts:20
 msgid "Issued certificate successfully"
 msgid "Issued certificate successfully"
@@ -2559,8 +2591,8 @@ msgstr "Deixar em branco se não quiser modificar"
 msgid "Leave blank if you don't need this."
 msgid "Leave blank if you don't need this."
 msgstr "Deixe em branco se não precisar disto."
 msgstr "Deixe em branco se não precisar disto."
 
 
-#: src/views/certificate/CertificateEditor.vue:223
-#: src/views/certificate/CertificateEditor.vue:237
+#: src/views/certificate/CertificateEditor.vue:221
+#: src/views/certificate/CertificateEditor.vue:235
 msgid "Leave blank will not change anything"
 msgid "Leave blank will not change anything"
 msgstr "Deixar em branco não vai mudar nada"
 msgstr "Deixar em branco não vai mudar nada"
 
 
@@ -2647,7 +2679,7 @@ msgstr "Localização"
 msgid "Locations"
 msgid "Locations"
 msgstr "Localizações"
 msgstr "Localizações"
 
 
-#: src/views/certificate/CertificateEditor.vue:247
+#: src/views/certificate/CertificateEditor.vue:245
 msgid "Log"
 msgid "Log"
 msgstr "Log"
 msgstr "Log"
 
 
@@ -2861,7 +2893,7 @@ msgid "Modify"
 msgstr "Modificar"
 msgstr "Modificar"
 
 
 #: src/routes/modules/certificates.ts:36
 #: src/routes/modules/certificates.ts:36
-#: src/views/certificate/CertificateEditor.vue:85
+#: src/views/certificate/CertificateEditor.vue:83
 msgid "Modify Certificate"
 msgid "Modify Certificate"
 msgstr "Modificar Certificado"
 msgstr "Modificar Certificado"
 
 
@@ -2896,7 +2928,7 @@ msgstr "Diretiva Multilinha"
 #: src/components/NgxConfigEditor/NgxUpstream.vue:199
 #: src/components/NgxConfigEditor/NgxUpstream.vue:199
 #: src/views/backup/AutoBackup/AutoBackup.vue:11
 #: src/views/backup/AutoBackup/AutoBackup.vue:11
 #: src/views/certificate/ACMEUser.vue:11
 #: src/views/certificate/ACMEUser.vue:11
-#: src/views/certificate/CertificateEditor.vue:162
+#: src/views/certificate/CertificateEditor.vue:160
 #: src/views/certificate/CertificateList/certColumns.tsx:9
 #: src/views/certificate/CertificateList/certColumns.tsx:9
 #: src/views/certificate/DNSCredential.vue:9
 #: src/views/certificate/DNSCredential.vue:9
 #: src/views/config/components/ConfigRightPanel/Basic.vue:34
 #: src/views/config/components/ConfigRightPanel/Basic.vue:34
@@ -2956,7 +2988,7 @@ msgstr "Novo Caminho"
 msgid "New version released"
 msgid "New version released"
 msgstr "Nova versão lançada"
 msgstr "Nova versão lançada"
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:89
+#: src/views/certificate/components/DNSIssueCertificate.vue:181
 #: src/views/install/components/InstallView.vue:96
 #: src/views/install/components/InstallView.vue:96
 #: src/views/site/site_add/SiteAdd.vue:132
 #: src/views/site/site_add/SiteAdd.vue:132
 #: src/views/site/site_edit/components/Cert/ObtainCert.vue:214
 #: src/views/site/site_edit/components/Cert/ObtainCert.vue:214
@@ -3545,6 +3577,10 @@ msgstr ""
 msgid "Please enter a valid port range"
 msgid "Please enter a valid port range"
 msgstr "Por favor, insira um intervalo de portas válido"
 msgstr "Por favor, insira um intervalo de portas válido"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:74
+msgid "Please enter at least one domain"
+msgstr "Por favor, insira pelo menos um domínio"
+
 #: src/components/TwoFA/Authorization.vue:85
 #: src/components/TwoFA/Authorization.vue:85
 msgid "Please enter the OTP code:"
 msgid "Please enter the OTP code:"
 msgstr "Por favor, insira o código OTP:"
 msgstr "Por favor, insira o código OTP:"
@@ -3886,6 +3922,7 @@ msgstr "Recarregando"
 msgid "Reloading nginx"
 msgid "Reloading nginx"
 msgstr "Recarregando Nginx"
 msgstr "Recarregando Nginx"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:144
 #: src/views/preference/tabs/AuthSettings.vue:137
 #: src/views/preference/tabs/AuthSettings.vue:137
 msgid "Remove"
 msgid "Remove"
 msgstr "Remover"
 msgstr "Remover"
@@ -3970,8 +4007,8 @@ msgstr "Renomeado com sucesso"
 msgid "Renamed successfully"
 msgid "Renamed successfully"
 msgstr "Renomeado com sucesso"
 msgstr "Renomeado com sucesso"
 
 
-#: src/views/certificate/components/RenewCert.vue:46
-#: src/views/certificate/components/RenewCert.vue:53
+#: src/views/certificate/components/RenewCert.vue:48
+#: src/views/certificate/components/RenewCert.vue:55
 msgid "Renew Certificate"
 msgid "Renew Certificate"
 msgstr "Renovar Certificado"
 msgstr "Renovar Certificado"
 
 
@@ -3983,8 +4020,8 @@ msgstr "Erro ao Renovar Certificado"
 msgid "Renew Certificate Success"
 msgid "Renew Certificate Success"
 msgstr "Certificado Renovado com Sucesso"
 msgstr "Certificado Renovado com Sucesso"
 
 
-#: src/views/certificate/components/RenewCert.vue:28
-#: src/views/certificate/components/WildcardCertificate.vue:46
+#: src/views/certificate/components/DNSIssueCertificate.vue:84
+#: src/views/certificate/components/RenewCert.vue:30
 msgid "Renew successfully"
 msgid "Renew successfully"
 msgstr "Renovado com Sucesso"
 msgstr "Renovado com Sucesso"
 
 
@@ -4243,7 +4280,7 @@ msgstr "Sábado"
 
 
 #: src/components/ChatGPT/ChatMessage.vue:215
 #: src/components/ChatGPT/ChatMessage.vue:215
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:129
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:129
-#: src/language/curd.ts:18 src/views/certificate/CertificateEditor.vue:266
+#: src/language/curd.ts:18 src/views/certificate/CertificateEditor.vue:264
 #: src/views/config/components/ConfigLeftPanel.vue:282
 #: src/views/config/components/ConfigLeftPanel.vue:282
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/preference/components/AuthSettings/Passkey.vue:130
 #: src/views/preference/components/AuthSettings/Passkey.vue:130
@@ -4298,7 +4335,7 @@ msgstr "Falha ao guardar o fluxo %{name} em %{node}"
 msgid "Save stream %{name} to %{node} successfully"
 msgid "Save stream %{name} to %{node} successfully"
 msgstr "Fluxo %{name} guardado em %{node} com sucesso"
 msgstr "Fluxo %{name} guardado em %{node} com sucesso"
 
 
-#: src/language/curd.ts:35 src/views/certificate/CertificateEditor.vue:49
+#: src/language/curd.ts:35 src/views/certificate/store.ts:13
 #: src/views/preference/store/index.ts:118
 #: src/views/preference/store/index.ts:118
 msgid "Save successfully"
 msgid "Save successfully"
 msgstr "Salvo com sucesso"
 msgstr "Salvo com sucesso"
@@ -4410,6 +4447,10 @@ msgstr "Enviar"
 msgid "Server"
 msgid "Server"
 msgstr "Servidor"
 msgstr "Servidor"
 
 
+#: src/views/certificate/CertificateEditor.vue:55
+msgid "Server error"
+msgstr "Erro do servidor"
+
 #: src/views/dashboard/ServerAnalytic.vue:175
 #: src/views/dashboard/ServerAnalytic.vue:175
 msgid "Server Info"
 msgid "Server Info"
 msgstr "Informação do Servidor"
 msgstr "Informação do Servidor"
@@ -4546,7 +4587,7 @@ msgstr "Tempo de espera entre iterações do carregador de cache"
 msgid "Sleep time between cache manager iterations"
 msgid "Sleep time between cache manager iterations"
 msgstr "Tempo de espera entre iterações do gestor de cache"
 msgstr "Tempo de espera entre iterações do gestor de cache"
 
 
-#: src/views/certificate/CertificateEditor.vue:213
+#: src/views/certificate/CertificateEditor.vue:211
 msgid "SSL Certificate Content"
 msgid "SSL Certificate Content"
 msgstr "Conteúdo do Certificado SSL"
 msgstr "Conteúdo do Certificado SSL"
 
 
@@ -4560,15 +4601,15 @@ msgstr ""
 msgid "SSL certificate file not found"
 msgid "SSL certificate file not found"
 msgstr "Ficheiro de certificado SSL não encontrado"
 msgstr "Ficheiro de certificado SSL não encontrado"
 
 
-#: src/views/certificate/CertificateEditor.vue:227
+#: src/views/certificate/CertificateEditor.vue:225
 msgid "SSL Certificate Key Content"
 msgid "SSL Certificate Key Content"
 msgstr "Conteúdo da Chave do Certificado SSL"
 msgstr "Conteúdo da Chave do Certificado SSL"
 
 
-#: src/views/certificate/CertificateEditor.vue:192
+#: src/views/certificate/CertificateEditor.vue:190
 msgid "SSL Certificate Key Path"
 msgid "SSL Certificate Key Path"
 msgstr "Caminho para a Chave do Certificado SSL"
 msgstr "Caminho para a Chave do Certificado SSL"
 
 
-#: src/views/certificate/CertificateEditor.vue:177
+#: src/views/certificate/CertificateEditor.vue:175
 #: src/views/preference/tabs/ServerSettings.vue:37
 #: src/views/preference/tabs/ServerSettings.vue:37
 msgid "SSL Certificate Path"
 msgid "SSL Certificate Path"
 msgstr "Caminho para o Certificado SSL"
 msgstr "Caminho para o Certificado SSL"
@@ -4807,7 +4848,7 @@ msgstr "Nós de sincronização"
 msgid "Sync strategy"
 msgid "Sync strategy"
 msgstr "Estratégia de sincronização"
 msgstr "Estratégia de sincronização"
 
 
-#: src/views/certificate/CertificateEditor.vue:206
+#: src/views/certificate/CertificateEditor.vue:204
 msgid "Sync to"
 msgid "Sync to"
 msgstr "Sincronizar para"
 msgstr "Sincronizar para"
 
 
@@ -4883,11 +4924,11 @@ msgstr ""
 "O número ICP deve conter apenas letras, unicode, números, hífens, traços, "
 "O número ICP deve conter apenas letras, unicode, números, hífens, traços, "
 "dois pontos e pontos."
 "dois pontos e pontos."
 
 
-#: src/views/certificate/CertificateEditor.vue:216
+#: src/views/certificate/CertificateEditor.vue:214
 msgid "The input is not a SSL Certificate"
 msgid "The input is not a SSL Certificate"
 msgstr "A valor introduzido não é um certificado SSL"
 msgstr "A valor introduzido não é um certificado SSL"
 
 
-#: src/views/certificate/CertificateEditor.vue:230
+#: src/views/certificate/CertificateEditor.vue:228
 msgid "The input is not a SSL Certificate Key"
 msgid "The input is not a SSL Certificate Key"
 msgstr "O valor introduzido não é uma Chave de Certificado SSL"
 msgstr "O valor introduzido não é uma Chave de Certificado SSL"
 
 
@@ -4926,11 +4967,11 @@ msgstr ""
 msgid "The parameter of server_name is required"
 msgid "The parameter of server_name is required"
 msgstr "O parâmetro de server_name é obrigatório"
 msgstr "O parâmetro de server_name é obrigatório"
 
 
-#: src/views/certificate/CertificateEditor.vue:181
+#: src/views/certificate/CertificateEditor.vue:179
 msgid "The path exists, but the file is not a certificate"
 msgid "The path exists, but the file is not a certificate"
 msgstr "O caminho existe, mas o ficheiro não é um certificado"
 msgstr "O caminho existe, mas o ficheiro não é um certificado"
 
 
-#: src/views/certificate/CertificateEditor.vue:196
+#: src/views/certificate/CertificateEditor.vue:194
 msgid "The path exists, but the file is not a private key"
 msgid "The path exists, but the file is not a private key"
 msgstr "O caminho existe, mas o ficheiro não é uma chave privada"
 msgstr "O caminho existe, mas o ficheiro não é uma chave privada"
 
 
@@ -4992,17 +5033,17 @@ msgstr ""
 "palavra-passe e os segundos fatores. Se não conseguir encontrar estes "
 "palavra-passe e os segundos fatores. Se não conseguir encontrar estes "
 "códigos, perderá o acesso à sua conta."
 "códigos, perderá o acesso à sua conta."
 
 
-#: src/views/certificate/CertificateEditor.vue:102
+#: src/views/certificate/CertificateEditor.vue:100
 msgid "This Auto Cert item is invalid, please remove it."
 msgid "This Auto Cert item is invalid, please remove it."
 msgstr "Este item Auto Cert é inválido, por favor remova-o."
 msgstr "Este item Auto Cert é inválido, por favor remova-o."
 
 
-#: src/views/certificate/CertificateEditor.vue:92
+#: src/views/certificate/CertificateEditor.vue:90
 msgid "This certificate is managed by Nginx UI"
 msgid "This certificate is managed by Nginx UI"
 msgstr "Este certificado é gerido pelo Nginx UI"
 msgstr "Este certificado é gerido pelo Nginx UI"
 
 
-#: src/views/certificate/CertificateEditor.vue:165
-#: src/views/certificate/CertificateEditor.vue:179
-#: src/views/certificate/CertificateEditor.vue:194
+#: src/views/certificate/CertificateEditor.vue:163
+#: src/views/certificate/CertificateEditor.vue:177
+#: src/views/certificate/CertificateEditor.vue:192
 msgid "This field is required"
 msgid "This field is required"
 msgstr "Este campo é mantatório"
 msgstr "Este campo é mantatório"
 
 
@@ -5481,6 +5522,10 @@ msgstr ""
 msgid "Whether to use a temporary path when writing temporary files"
 msgid "Whether to use a temporary path when writing temporary files"
 msgstr "Se deve usar um caminho temporário ao escrever ficheiros temporários"
 msgstr "Se deve usar um caminho temporário ao escrever ficheiros temporários"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:107
+msgid "Wildcard Certificate"
+msgstr "Certificado curinga"
+
 #: src/views/dashboard/components/ParamsOpt/PerformanceConfig.vue:48
 #: src/views/dashboard/components/ParamsOpt/PerformanceConfig.vue:48
 msgid "Worker Connections"
 msgid "Worker Connections"
 msgstr "Conexões de trabalhador"
 msgstr "Conexões de trabalhador"
@@ -5740,9 +5785,6 @@ msgstr "As suas chaves de acesso"
 #~ "Erro ao mudar o nome de %{orig_path} para %{new_path} no %{env_name}, por "
 #~ "Erro ao mudar o nome de %{orig_path} para %{new_path} no %{env_name}, por "
 #~ "favor actualize a versão do Nginx UI para a mais recente"
 #~ "favor actualize a versão do Nginx UI para a mais recente"
 
 
-#~ msgid "Server error"
-#~ msgstr "Erro do servidor"
-
 #~ msgid "Server Name"
 #~ msgid "Server Name"
 #~ msgstr "Nome do Servidor"
 #~ msgstr "Nome do Servidor"
 
 

+ 84 - 42
app/src/language/ru_RU/app.po

@@ -185,6 +185,10 @@ msgstr "Добавить конфигурацию"
 msgid "Add Directive Below"
 msgid "Add Directive Below"
 msgstr "Добавить директиву ниже"
 msgstr "Добавить директиву ниже"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:151
+msgid "Add Domain"
+msgstr "Добавить домен"
+
 #: src/components/NgxConfigEditor/LocationEditor.vue:131
 #: src/components/NgxConfigEditor/LocationEditor.vue:131
 #: src/components/NgxConfigEditor/LocationEditor.vue:158
 #: src/components/NgxConfigEditor/LocationEditor.vue:158
 msgid "Add Location"
 msgid "Add Location"
@@ -232,6 +236,14 @@ msgstr "Все"
 msgid "All Recovery Codes Have Been Used"
 msgid "All Recovery Codes Have Been Used"
 msgstr "Все коды восстановления были использованы"
 msgstr "Все коды восстановления были использованы"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:156
+msgid ""
+"All selected subdomains must belong to the same DNS Provider, otherwise the "
+"certificate application will fail."
+msgstr ""
+"Все выбранные поддомены должны принадлежать одному и тому же "
+"DNS-провайдеру, иначе запрос сертификата завершится неудачей."
+
 #: src/views/preference/tabs/OpenAISettings.vue:32
 #: src/views/preference/tabs/OpenAISettings.vue:32
 msgid "API Base Url"
 msgid "API Base Url"
 msgstr "Базовый URL API"
 msgstr "Базовый URL API"
@@ -258,7 +270,7 @@ msgstr "Приложение"
 
 
 #: src/views/system/Upgrade.vue:195
 #: src/views/system/Upgrade.vue:195
 msgid "Arch"
 msgid "Arch"
-msgstr "\"Архитектура\""
+msgstr "Архитектура"
 
 
 #: src/views/preference/tabs/AuthSettings.vue:130
 #: src/views/preference/tabs/AuthSettings.vue:130
 msgid "Are you sure to delete this banned IP immediately?"
 msgid "Are you sure to delete this banned IP immediately?"
@@ -397,7 +409,7 @@ msgstr "Автообновление отключено для %{name}"
 msgid "Auto-renewal enabled for %{name}"
 msgid "Auto-renewal enabled for %{name}"
 msgstr "Автообновление включено для %{name}"
 msgstr "Автообновление включено для %{name}"
 
 
-#: src/views/certificate/components/RenewCert.vue:49
+#: src/views/certificate/components/RenewCert.vue:51
 #: src/views/site/site_edit/components/Cert/IssueCert.vue:84
 #: src/views/site/site_edit/components/Cert/IssueCert.vue:84
 msgid "AutoCert is running, please wait..."
 msgid "AutoCert is running, please wait..."
 msgstr "AutoCert выполняется, пожалуйста, подождите..."
 msgstr "AutoCert выполняется, пожалуйста, подождите..."
@@ -410,7 +422,7 @@ msgstr "\"AutoCert выполняется...\""
 msgid "Automatic Restart"
 msgid "Automatic Restart"
 msgstr "\"Автоматическая перезагрузка\""
 msgstr "\"Автоматическая перезагрузка\""
 
 
-#: src/views/certificate/CertificateEditor.vue:259
+#: src/views/certificate/CertificateEditor.vue:257
 #: src/views/config/components/ConfigLeftPanel.vue:273
 #: src/views/config/components/ConfigLeftPanel.vue:273
 #: src/views/config/ConfigList.vue:112 src/views/config/ConfigList.vue:195
 #: src/views/config/ConfigList.vue:112 src/views/config/ConfigList.vue:195
 #: src/views/nginx_log/NginxLog.vue:174
 #: src/views/nginx_log/NginxLog.vue:174
@@ -715,13 +727,17 @@ msgstr "Сертификат успешно продлен"
 msgid "Certificate revoked successfully"
 msgid "Certificate revoked successfully"
 msgstr "Сертификат успешно отозван"
 msgstr "Сертификат успешно отозван"
 
 
-#: src/views/certificate/CertificateEditor.vue:128
+#: src/views/certificate/CertificateEditor.vue:126
 #: src/views/site/site_edit/components/Cert/Cert.vue:58
 #: src/views/site/site_edit/components/Cert/Cert.vue:58
 msgid "Certificate Status"
 msgid "Certificate Status"
 msgid_plural "Certificates Status"
 msgid_plural "Certificates Status"
 msgstr[0] "Статус сертификата"
 msgstr[0] "Статус сертификата"
 msgstr[1] "Статус сертификатов"
 msgstr[1] "Статус сертификатов"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:104
+msgid "Certificate Type"
+msgstr "Тип сертификата"
+
 #: src/routes/modules/certificates.ts:11
 #: src/routes/modules/certificates.ts:11
 #: src/views/certificate/CertificateList/Certificate.vue:19
 #: src/views/certificate/CertificateList/Certificate.vue:19
 msgid "Certificates"
 msgid "Certificates"
@@ -1211,6 +1227,14 @@ msgstr "Пользовательское cron-выражение"
 msgid "Custom Directory"
 msgid "Custom Directory"
 msgstr "Пользовательская директория"
 msgstr "Пользовательская директория"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:126
+msgid "Custom Domains"
+msgstr "Пользовательские домены"
+
+#: src/views/certificate/components/DNSIssueCertificate.vue:110
+msgid "Custom Domains Certificate"
+msgstr "Сертификат для пользовательских доменов"
+
 #: src/views/preference/tabs/NodeSettings.vue:19
 #: src/views/preference/tabs/NodeSettings.vue:19
 msgid ""
 msgid ""
 "Customize the name of local node to be displayed in the environment "
 "Customize the name of local node to be displayed in the environment "
@@ -1518,11 +1542,11 @@ msgid "Document"
 msgid_plural "Documents"
 msgid_plural "Documents"
 msgstr[0] "Документ"
 msgstr[0] "Документ"
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:66
+#: src/views/certificate/components/DNSIssueCertificate.vue:116
 msgid "Domain"
 msgid "Domain"
 msgstr "Домен"
 msgstr "Домен"
 
 
-#: src/views/certificate/CertificateEditor.vue:112
+#: src/views/certificate/CertificateEditor.vue:110
 msgid "Domains list is empty, try to reopen Auto Cert for %{config}"
 msgid "Domains list is empty, try to reopen Auto Cert for %{config}"
 msgstr "Список доменов пуст, попробуйте заново создать авто-сертификат для %{config}"
 msgstr "Список доменов пуст, попробуйте заново создать авто-сертификат для %{config}"
 
 
@@ -1725,6 +1749,14 @@ msgstr "Использовать для сайта Let's Encrypt"
 msgid "End"
 msgid "End"
 msgstr "Конец"
 msgstr "Конец"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:135
+msgid "Enter domain name"
+msgstr "Введите имя домена"
+
+#: src/views/certificate/components/DNSIssueCertificate.vue:120
+msgid "Enter your domain"
+msgstr "Введите ваш домен"
+
 #: src/language/constants.ts:22
 #: src/language/constants.ts:22
 msgid "Environment variables cleaned"
 msgid "Environment variables cleaned"
 msgstr "Переменные окружения очищены"
 msgstr "Переменные окружения очищены"
@@ -1799,7 +1831,7 @@ msgstr "Внешний контейнер Docker"
 msgid "External Notify"
 msgid "External Notify"
 msgstr "Внешнее уведомление"
 msgstr "Внешнее уведомление"
 
 
-#: src/views/site/site_edit/components/Cert/ObtainCertLive.vue:80
+#: src/views/site/site_edit/components/Cert/ObtainCertLive.vue:81
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
 msgstr "Не удалось получить сертификат"
 msgstr "Не удалось получить сертификат"
 
 
@@ -2327,7 +2359,7 @@ msgid "Import"
 msgstr "Импорт"
 msgstr "Импорт"
 
 
 #: src/routes/modules/certificates.ts:46
 #: src/routes/modules/certificates.ts:46
-#: src/views/certificate/CertificateEditor.vue:85
+#: src/views/certificate/CertificateEditor.vue:83
 msgid "Import Certificate"
 msgid "Import Certificate"
 msgstr "Импортировать сертификат"
 msgstr "Импортировать сертификат"
 
 
@@ -2472,12 +2504,12 @@ msgid "IP"
 msgstr "IP"
 msgstr "IP"
 
 
 #: src/views/certificate/CertificateList/Certificate.vue:37
 #: src/views/certificate/CertificateList/Certificate.vue:37
-msgid "Issue wildcard certificate"
-msgstr "Выпустить wildcard-сертификат"
+msgid "Issue certificate"
+msgstr "Выдать сертификат"
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:57
-msgid "Issue Wildcard Certificate"
-msgstr "Выпустить Wildcard сертификат"
+#: src/views/certificate/components/DNSIssueCertificate.vue:95
+msgid "Issue Certificate"
+msgstr "Выпустить сертификат"
 
 
 #: src/language/constants.ts:20
 #: src/language/constants.ts:20
 msgid "Issued certificate successfully"
 msgid "Issued certificate successfully"
@@ -2560,8 +2592,8 @@ msgstr "Оставьте пустым, если не хотите изменят
 msgid "Leave blank if you don't need this."
 msgid "Leave blank if you don't need this."
 msgstr "Оставьте пустым без изменений."
 msgstr "Оставьте пустым без изменений."
 
 
-#: src/views/certificate/CertificateEditor.vue:223
-#: src/views/certificate/CertificateEditor.vue:237
+#: src/views/certificate/CertificateEditor.vue:221
+#: src/views/certificate/CertificateEditor.vue:235
 msgid "Leave blank will not change anything"
 msgid "Leave blank will not change anything"
 msgstr "Если оставить пустым, ничего не изменится"
 msgstr "Если оставить пустым, ничего не изменится"
 
 
@@ -2648,7 +2680,7 @@ msgstr "Локация"
 msgid "Locations"
 msgid "Locations"
 msgstr "Локации"
 msgstr "Локации"
 
 
-#: src/views/certificate/CertificateEditor.vue:247
+#: src/views/certificate/CertificateEditor.vue:245
 msgid "Log"
 msgid "Log"
 msgstr "Журнал"
 msgstr "Журнал"
 
 
@@ -2862,7 +2894,7 @@ msgid "Modify"
 msgstr "Изменить"
 msgstr "Изменить"
 
 
 #: src/routes/modules/certificates.ts:36
 #: src/routes/modules/certificates.ts:36
-#: src/views/certificate/CertificateEditor.vue:85
+#: src/views/certificate/CertificateEditor.vue:83
 msgid "Modify Certificate"
 msgid "Modify Certificate"
 msgstr "Изменить сертификат"
 msgstr "Изменить сертификат"
 
 
@@ -2897,7 +2929,7 @@ msgstr "Многострочная директива"
 #: src/components/NgxConfigEditor/NgxUpstream.vue:199
 #: src/components/NgxConfigEditor/NgxUpstream.vue:199
 #: src/views/backup/AutoBackup/AutoBackup.vue:11
 #: src/views/backup/AutoBackup/AutoBackup.vue:11
 #: src/views/certificate/ACMEUser.vue:11
 #: src/views/certificate/ACMEUser.vue:11
-#: src/views/certificate/CertificateEditor.vue:162
+#: src/views/certificate/CertificateEditor.vue:160
 #: src/views/certificate/CertificateList/certColumns.tsx:9
 #: src/views/certificate/CertificateList/certColumns.tsx:9
 #: src/views/certificate/DNSCredential.vue:9
 #: src/views/certificate/DNSCredential.vue:9
 #: src/views/config/components/ConfigRightPanel/Basic.vue:34
 #: src/views/config/components/ConfigRightPanel/Basic.vue:34
@@ -2957,7 +2989,7 @@ msgstr "Новый путь"
 msgid "New version released"
 msgid "New version released"
 msgstr "Вышла новая версия"
 msgstr "Вышла новая версия"
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:89
+#: src/views/certificate/components/DNSIssueCertificate.vue:181
 #: src/views/install/components/InstallView.vue:96
 #: src/views/install/components/InstallView.vue:96
 #: src/views/site/site_add/SiteAdd.vue:132
 #: src/views/site/site_add/SiteAdd.vue:132
 #: src/views/site/site_edit/components/Cert/ObtainCert.vue:214
 #: src/views/site/site_edit/components/Cert/ObtainCert.vue:214
@@ -3546,6 +3578,10 @@ msgstr ""
 msgid "Please enter a valid port range"
 msgid "Please enter a valid port range"
 msgstr "Пожалуйста, введите допустимый диапазон портов"
 msgstr "Пожалуйста, введите допустимый диапазон портов"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:74
+msgid "Please enter at least one domain"
+msgstr "Пожалуйста, введите хотя бы один домен"
+
 #: src/components/TwoFA/Authorization.vue:85
 #: src/components/TwoFA/Authorization.vue:85
 msgid "Please enter the OTP code:"
 msgid "Please enter the OTP code:"
 msgstr "Пожалуйста, введите код OTP:"
 msgstr "Пожалуйста, введите код OTP:"
@@ -3892,6 +3928,7 @@ msgstr "Перезагружается"
 msgid "Reloading nginx"
 msgid "Reloading nginx"
 msgstr "Перезагружается nginx"
 msgstr "Перезагружается nginx"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:144
 #: src/views/preference/tabs/AuthSettings.vue:137
 #: src/views/preference/tabs/AuthSettings.vue:137
 msgid "Remove"
 msgid "Remove"
 msgstr "Удалить"
 msgstr "Удалить"
@@ -3974,8 +4011,8 @@ msgstr "Переименовано успешно"
 msgid "Renamed successfully"
 msgid "Renamed successfully"
 msgstr "Успешно переименовано"
 msgstr "Успешно переименовано"
 
 
-#: src/views/certificate/components/RenewCert.vue:46
-#: src/views/certificate/components/RenewCert.vue:53
+#: src/views/certificate/components/RenewCert.vue:48
+#: src/views/certificate/components/RenewCert.vue:55
 msgid "Renew Certificate"
 msgid "Renew Certificate"
 msgstr "Обновить сертификат"
 msgstr "Обновить сертификат"
 
 
@@ -3987,8 +4024,8 @@ msgstr "Ошибка обновления сертификата"
 msgid "Renew Certificate Success"
 msgid "Renew Certificate Success"
 msgstr "Успешное обновление сертификата"
 msgstr "Успешное обновление сертификата"
 
 
-#: src/views/certificate/components/RenewCert.vue:28
-#: src/views/certificate/components/WildcardCertificate.vue:46
+#: src/views/certificate/components/DNSIssueCertificate.vue:84
+#: src/views/certificate/components/RenewCert.vue:30
 msgid "Renew successfully"
 msgid "Renew successfully"
 msgstr "Успешно обновлено"
 msgstr "Успешно обновлено"
 
 
@@ -4247,7 +4284,7 @@ msgstr "Суббота"
 
 
 #: src/components/ChatGPT/ChatMessage.vue:215
 #: src/components/ChatGPT/ChatMessage.vue:215
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:129
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:129
-#: src/language/curd.ts:18 src/views/certificate/CertificateEditor.vue:266
+#: src/language/curd.ts:18 src/views/certificate/CertificateEditor.vue:264
 #: src/views/config/components/ConfigLeftPanel.vue:282
 #: src/views/config/components/ConfigLeftPanel.vue:282
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/preference/components/AuthSettings/Passkey.vue:130
 #: src/views/preference/components/AuthSettings/Passkey.vue:130
@@ -4302,7 +4339,7 @@ msgstr "Не удалось сохранить поток %{name} на %{node}"
 msgid "Save stream %{name} to %{node} successfully"
 msgid "Save stream %{name} to %{node} successfully"
 msgstr "Поток %{name} успешно сохранён на %{node}"
 msgstr "Поток %{name} успешно сохранён на %{node}"
 
 
-#: src/language/curd.ts:35 src/views/certificate/CertificateEditor.vue:49
+#: src/language/curd.ts:35 src/views/certificate/store.ts:13
 #: src/views/preference/store/index.ts:118
 #: src/views/preference/store/index.ts:118
 msgid "Save successfully"
 msgid "Save successfully"
 msgstr "Сохранено успешно"
 msgstr "Сохранено успешно"
@@ -4412,6 +4449,10 @@ msgstr "Отправлено"
 msgid "Server"
 msgid "Server"
 msgstr "Сервер"
 msgstr "Сервер"
 
 
+#: src/views/certificate/CertificateEditor.vue:55
+msgid "Server error"
+msgstr "Ошибка сервера"
+
 #: src/views/dashboard/ServerAnalytic.vue:175
 #: src/views/dashboard/ServerAnalytic.vue:175
 msgid "Server Info"
 msgid "Server Info"
 msgstr "Информация о сервере"
 msgstr "Информация о сервере"
@@ -4548,7 +4589,7 @@ msgstr "Время ожидания между итерациями загруз
 msgid "Sleep time between cache manager iterations"
 msgid "Sleep time between cache manager iterations"
 msgstr "Время ожидания между итерациями менеджера кеша"
 msgstr "Время ожидания между итерациями менеджера кеша"
 
 
-#: src/views/certificate/CertificateEditor.vue:213
+#: src/views/certificate/CertificateEditor.vue:211
 msgid "SSL Certificate Content"
 msgid "SSL Certificate Content"
 msgstr "Содержимое SSL-сертификата"
 msgstr "Содержимое SSL-сертификата"
 
 
@@ -4560,15 +4601,15 @@ msgstr "Файл SSL-сертификата должен находиться в
 msgid "SSL certificate file not found"
 msgid "SSL certificate file not found"
 msgstr "Файл SSL-сертификата не найден"
 msgstr "Файл SSL-сертификата не найден"
 
 
-#: src/views/certificate/CertificateEditor.vue:227
+#: src/views/certificate/CertificateEditor.vue:225
 msgid "SSL Certificate Key Content"
 msgid "SSL Certificate Key Content"
 msgstr "Содержимое ключа SSL-сертификата"
 msgstr "Содержимое ключа SSL-сертификата"
 
 
-#: src/views/certificate/CertificateEditor.vue:192
+#: src/views/certificate/CertificateEditor.vue:190
 msgid "SSL Certificate Key Path"
 msgid "SSL Certificate Key Path"
 msgstr "Путь к ключу SSL-сертификата"
 msgstr "Путь к ключу SSL-сертификата"
 
 
-#: src/views/certificate/CertificateEditor.vue:177
+#: src/views/certificate/CertificateEditor.vue:175
 #: src/views/preference/tabs/ServerSettings.vue:37
 #: src/views/preference/tabs/ServerSettings.vue:37
 msgid "SSL Certificate Path"
 msgid "SSL Certificate Path"
 msgstr "Путь к SSL сертификату"
 msgstr "Путь к SSL сертификату"
@@ -4805,7 +4846,7 @@ msgstr "Синхронизированные узлы"
 msgid "Sync strategy"
 msgid "Sync strategy"
 msgstr "Стратегия синхронизации"
 msgstr "Стратегия синхронизации"
 
 
-#: src/views/certificate/CertificateEditor.vue:206
+#: src/views/certificate/CertificateEditor.vue:204
 msgid "Sync to"
 msgid "Sync to"
 msgstr "Синхронизировать с"
 msgstr "Синхронизировать с"
 
 
@@ -4881,11 +4922,11 @@ msgstr ""
 "Номер ICP должен содержать только буквы, юникод, цифры, дефисы, тире, "
 "Номер ICP должен содержать только буквы, юникод, цифры, дефисы, тире, "
 "двоеточия и точки."
 "двоеточия и точки."
 
 
-#: src/views/certificate/CertificateEditor.vue:216
+#: src/views/certificate/CertificateEditor.vue:214
 msgid "The input is not a SSL Certificate"
 msgid "The input is not a SSL Certificate"
 msgstr "Входные данные не являются SSL-сертификатом"
 msgstr "Входные данные не являются SSL-сертификатом"
 
 
-#: src/views/certificate/CertificateEditor.vue:230
+#: src/views/certificate/CertificateEditor.vue:228
 msgid "The input is not a SSL Certificate Key"
 msgid "The input is not a SSL Certificate Key"
 msgstr "Введенные данные не являются ключом SSL сертификата"
 msgstr "Введенные данные не являются ключом SSL сертификата"
 
 
@@ -4924,11 +4965,11 @@ msgstr ""
 msgid "The parameter of server_name is required"
 msgid "The parameter of server_name is required"
 msgstr "Параметр server_name обязателен"
 msgstr "Параметр server_name обязателен"
 
 
-#: src/views/certificate/CertificateEditor.vue:181
+#: src/views/certificate/CertificateEditor.vue:179
 msgid "The path exists, but the file is not a certificate"
 msgid "The path exists, but the file is not a certificate"
 msgstr "Путь существует, но файл не является сертификатом"
 msgstr "Путь существует, но файл не является сертификатом"
 
 
-#: src/views/certificate/CertificateEditor.vue:196
+#: src/views/certificate/CertificateEditor.vue:194
 msgid "The path exists, but the file is not a private key"
 msgid "The path exists, but the file is not a private key"
 msgstr "Путь существует, но файл не является приватным ключом"
 msgstr "Путь существует, но файл не является приватным ключом"
 
 
@@ -4990,17 +5031,17 @@ msgstr ""
 "вы потеряете пароль и вторые факторы. Если вы не сможете найти эти коды, вы "
 "вы потеряете пароль и вторые факторы. Если вы не сможете найти эти коды, вы "
 "потеряете доступ к своему аккаунту."
 "потеряете доступ к своему аккаунту."
 
 
-#: src/views/certificate/CertificateEditor.vue:102
+#: src/views/certificate/CertificateEditor.vue:100
 msgid "This Auto Cert item is invalid, please remove it."
 msgid "This Auto Cert item is invalid, please remove it."
 msgstr "Этот элемент автосертификата недействителен, удалите его.."
 msgstr "Этот элемент автосертификата недействителен, удалите его.."
 
 
-#: src/views/certificate/CertificateEditor.vue:92
+#: src/views/certificate/CertificateEditor.vue:90
 msgid "This certificate is managed by Nginx UI"
 msgid "This certificate is managed by Nginx UI"
 msgstr "Этот сертификат под управлением Nginx UI"
 msgstr "Этот сертификат под управлением Nginx UI"
 
 
-#: src/views/certificate/CertificateEditor.vue:165
-#: src/views/certificate/CertificateEditor.vue:179
-#: src/views/certificate/CertificateEditor.vue:194
+#: src/views/certificate/CertificateEditor.vue:163
+#: src/views/certificate/CertificateEditor.vue:177
+#: src/views/certificate/CertificateEditor.vue:192
 msgid "This field is required"
 msgid "This field is required"
 msgstr "Это поле обязательно для заполнения"
 msgstr "Это поле обязательно для заполнения"
 
 
@@ -5480,6 +5521,10 @@ msgstr ""
 msgid "Whether to use a temporary path when writing temporary files"
 msgid "Whether to use a temporary path when writing temporary files"
 msgstr "Использовать ли временный путь при записи временных файлов"
 msgstr "Использовать ли временный путь при записи временных файлов"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:107
+msgid "Wildcard Certificate"
+msgstr "Сертификат с подстановочным знаком"
+
 #: src/views/dashboard/components/ParamsOpt/PerformanceConfig.vue:48
 #: src/views/dashboard/components/ParamsOpt/PerformanceConfig.vue:48
 msgid "Worker Connections"
 msgid "Worker Connections"
 msgstr "Рабочие соединения"
 msgstr "Рабочие соединения"
@@ -5808,9 +5853,6 @@ msgstr "Ваши ключи доступа"
 #~ msgid "Recovery Code:"
 #~ msgid "Recovery Code:"
 #~ msgstr "Код восстановления:"
 #~ msgstr "Код восстановления:"
 
 
-#~ msgid "Server error"
-#~ msgstr "Ошибка сервера"
-
 #~ msgid "The recovery code is only displayed once, please save it in a safe place."
 #~ msgid "The recovery code is only displayed once, please save it in a safe place."
 #~ msgstr ""
 #~ msgstr ""
 #~ "Код восстановления отображается только один раз, пожалуйста, сохраните его "
 #~ "Код восстановления отображается только один раз, пожалуйста, сохраните его "

+ 84 - 43
app/src/language/tr_TR/app.po

@@ -181,6 +181,10 @@ msgstr "Yapılandırma Ekle"
 msgid "Add Directive Below"
 msgid "Add Directive Below"
 msgstr "Direktifi Aşağıya Ekleyin"
 msgstr "Direktifi Aşağıya Ekleyin"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:151
+msgid "Add Domain"
+msgstr "Alan Adı Ekle"
+
 #: src/components/NgxConfigEditor/LocationEditor.vue:131
 #: src/components/NgxConfigEditor/LocationEditor.vue:131
 #: src/components/NgxConfigEditor/LocationEditor.vue:158
 #: src/components/NgxConfigEditor/LocationEditor.vue:158
 msgid "Add Location"
 msgid "Add Location"
@@ -228,6 +232,14 @@ msgstr "Tümü"
 msgid "All Recovery Codes Have Been Used"
 msgid "All Recovery Codes Have Been Used"
 msgstr "Tüm Kurtarma Kodları Kullanıldı"
 msgstr "Tüm Kurtarma Kodları Kullanıldı"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:156
+msgid ""
+"All selected subdomains must belong to the same DNS Provider, otherwise the "
+"certificate application will fail."
+msgstr ""
+"Seçilen tüm alt alan adları aynı DNS Sağlayıcısına ait olmalıdır, aksi "
+"takdirde sertifika başvurusu başarısız olur."
+
 #: src/views/preference/tabs/OpenAISettings.vue:32
 #: src/views/preference/tabs/OpenAISettings.vue:32
 msgid "API Base Url"
 msgid "API Base Url"
 msgstr "API Temel Bağlantı Adresi"
 msgstr "API Temel Bağlantı Adresi"
@@ -254,7 +266,7 @@ msgstr "Uygulama"
 
 
 #: src/views/system/Upgrade.vue:195
 #: src/views/system/Upgrade.vue:195
 msgid "Arch"
 msgid "Arch"
-msgstr "\"Mimari\""
+msgstr "Mimari"
 
 
 #: src/views/preference/tabs/AuthSettings.vue:130
 #: src/views/preference/tabs/AuthSettings.vue:130
 msgid "Are you sure to delete this banned IP immediately?"
 msgid "Are you sure to delete this banned IP immediately?"
@@ -393,7 +405,7 @@ msgstr "Otomatik yenileme %{name} için devre dışı"
 msgid "Auto-renewal enabled for %{name}"
 msgid "Auto-renewal enabled for %{name}"
 msgstr "Otomatik yenileme %{name} için etkinleştirildi"
 msgstr "Otomatik yenileme %{name} için etkinleştirildi"
 
 
-#: src/views/certificate/components/RenewCert.vue:49
+#: src/views/certificate/components/RenewCert.vue:51
 #: src/views/site/site_edit/components/Cert/IssueCert.vue:84
 #: src/views/site/site_edit/components/Cert/IssueCert.vue:84
 msgid "AutoCert is running, please wait..."
 msgid "AutoCert is running, please wait..."
 msgstr "AutoCert çalışıyor, lütfen bekleyin..."
 msgstr "AutoCert çalışıyor, lütfen bekleyin..."
@@ -406,7 +418,7 @@ msgstr "\"AutoCert çalışıyor...\""
 msgid "Automatic Restart"
 msgid "Automatic Restart"
 msgstr "\"Otomatik Yeniden Başlatma\""
 msgstr "\"Otomatik Yeniden Başlatma\""
 
 
-#: src/views/certificate/CertificateEditor.vue:259
+#: src/views/certificate/CertificateEditor.vue:257
 #: src/views/config/components/ConfigLeftPanel.vue:273
 #: src/views/config/components/ConfigLeftPanel.vue:273
 #: src/views/config/ConfigList.vue:112 src/views/config/ConfigList.vue:195
 #: src/views/config/ConfigList.vue:112 src/views/config/ConfigList.vue:195
 #: src/views/nginx_log/NginxLog.vue:174
 #: src/views/nginx_log/NginxLog.vue:174
@@ -701,13 +713,17 @@ msgstr "Sertifika başarıyla yenilendi"
 msgid "Certificate revoked successfully"
 msgid "Certificate revoked successfully"
 msgstr "Sertifika başarıyla iptal edildi"
 msgstr "Sertifika başarıyla iptal edildi"
 
 
-#: src/views/certificate/CertificateEditor.vue:128
+#: src/views/certificate/CertificateEditor.vue:126
 #: src/views/site/site_edit/components/Cert/Cert.vue:58
 #: src/views/site/site_edit/components/Cert/Cert.vue:58
 msgid "Certificate Status"
 msgid "Certificate Status"
 msgid_plural "Certificates Status"
 msgid_plural "Certificates Status"
 msgstr[0] "Sertifika Durumu"
 msgstr[0] "Sertifika Durumu"
 msgstr[1] "Sertifikaların Durumu"
 msgstr[1] "Sertifikaların Durumu"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:104
+msgid "Certificate Type"
+msgstr "Sertifika Türü"
+
 #: src/routes/modules/certificates.ts:11
 #: src/routes/modules/certificates.ts:11
 #: src/views/certificate/CertificateList/Certificate.vue:19
 #: src/views/certificate/CertificateList/Certificate.vue:19
 msgid "Certificates"
 msgid "Certificates"
@@ -1199,6 +1215,14 @@ msgstr "Özel cron ifadesi"
 msgid "Custom Directory"
 msgid "Custom Directory"
 msgstr "Özel Dizin"
 msgstr "Özel Dizin"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:126
+msgid "Custom Domains"
+msgstr "Özel Alan Adları"
+
+#: src/views/certificate/components/DNSIssueCertificate.vue:110
+msgid "Custom Domains Certificate"
+msgstr "Özel Alan Adı Sertifikası"
+
 #: src/views/preference/tabs/NodeSettings.vue:19
 #: src/views/preference/tabs/NodeSettings.vue:19
 msgid ""
 msgid ""
 "Customize the name of local node to be displayed in the environment "
 "Customize the name of local node to be displayed in the environment "
@@ -1508,11 +1532,11 @@ msgid "Document"
 msgid_plural "Documents"
 msgid_plural "Documents"
 msgstr[0] "Belge"
 msgstr[0] "Belge"
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:66
+#: src/views/certificate/components/DNSIssueCertificate.vue:116
 msgid "Domain"
 msgid "Domain"
 msgstr "Alan Adı"
 msgstr "Alan Adı"
 
 
-#: src/views/certificate/CertificateEditor.vue:112
+#: src/views/certificate/CertificateEditor.vue:110
 msgid "Domains list is empty, try to reopen Auto Cert for %{config}"
 msgid "Domains list is empty, try to reopen Auto Cert for %{config}"
 msgstr ""
 msgstr ""
 "Alan adları listesi boş, %{config} için Otomatik Sertifikayı yeniden açmayı "
 "Alan adları listesi boş, %{config} için Otomatik Sertifikayı yeniden açmayı "
@@ -1717,6 +1741,14 @@ msgstr "Let's Encrypt ile web sitesini şifreleyin"
 msgid "End"
 msgid "End"
 msgstr "Son"
 msgstr "Son"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:135
+msgid "Enter domain name"
+msgstr "Alan adını girin"
+
+#: src/views/certificate/components/DNSIssueCertificate.vue:120
+msgid "Enter your domain"
+msgstr "Alan adınızı girin"
+
 #: src/language/constants.ts:22
 #: src/language/constants.ts:22
 msgid "Environment variables cleaned"
 msgid "Environment variables cleaned"
 msgstr "Ortam değişkenleri temizlendi"
 msgstr "Ortam değişkenleri temizlendi"
@@ -1791,7 +1823,7 @@ msgstr "Harici Docker Konteyneri"
 msgid "External Notify"
 msgid "External Notify"
 msgstr "Harici Bildirim"
 msgstr "Harici Bildirim"
 
 
-#: src/views/site/site_edit/components/Cert/ObtainCertLive.vue:80
+#: src/views/site/site_edit/components/Cert/ObtainCertLive.vue:81
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
 msgstr "Sertifika alınamadı"
 msgstr "Sertifika alınamadı"
 
 
@@ -2323,7 +2355,7 @@ msgid "Import"
 msgstr "İçe Aktar"
 msgstr "İçe Aktar"
 
 
 #: src/routes/modules/certificates.ts:46
 #: src/routes/modules/certificates.ts:46
-#: src/views/certificate/CertificateEditor.vue:85
+#: src/views/certificate/CertificateEditor.vue:83
 msgid "Import Certificate"
 msgid "Import Certificate"
 msgstr "Sertifika İçe Aktar"
 msgstr "Sertifika İçe Aktar"
 
 
@@ -2468,12 +2500,12 @@ msgid "IP"
 msgstr "IP"
 msgstr "IP"
 
 
 #: src/views/certificate/CertificateList/Certificate.vue:37
 #: src/views/certificate/CertificateList/Certificate.vue:37
-msgid "Issue wildcard certificate"
-msgstr "Wildcard sertifikası düzenle"
+msgid "Issue certificate"
+msgstr "Sertifika ver"
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:57
-msgid "Issue Wildcard Certificate"
-msgstr "Wildcard Sertifikası Yayınlama"
+#: src/views/certificate/components/DNSIssueCertificate.vue:95
+msgid "Issue Certificate"
+msgstr "Sertifika Düzenle"
 
 
 #: src/language/constants.ts:20
 #: src/language/constants.ts:20
 msgid "Issued certificate successfully"
 msgid "Issued certificate successfully"
@@ -2556,8 +2588,8 @@ msgstr "Değiştirmek istemiyorsanız boş bırakın"
 msgid "Leave blank if you don't need this."
 msgid "Leave blank if you don't need this."
 msgstr "Buna ihtiyacınız yoksa boş bırakın."
 msgstr "Buna ihtiyacınız yoksa boş bırakın."
 
 
-#: src/views/certificate/CertificateEditor.vue:223
-#: src/views/certificate/CertificateEditor.vue:237
+#: src/views/certificate/CertificateEditor.vue:221
+#: src/views/certificate/CertificateEditor.vue:235
 msgid "Leave blank will not change anything"
 msgid "Leave blank will not change anything"
 msgstr "Boş bırakmak hiçbir şeyi değiştirmeyecektir"
 msgstr "Boş bırakmak hiçbir şeyi değiştirmeyecektir"
 
 
@@ -2644,7 +2676,7 @@ msgstr "Konum"
 msgid "Locations"
 msgid "Locations"
 msgstr "Konumlar"
 msgstr "Konumlar"
 
 
-#: src/views/certificate/CertificateEditor.vue:247
+#: src/views/certificate/CertificateEditor.vue:245
 msgid "Log"
 msgid "Log"
 msgstr "Günlük"
 msgstr "Günlük"
 
 
@@ -2857,7 +2889,7 @@ msgid "Modify"
 msgstr "Değiştir"
 msgstr "Değiştir"
 
 
 #: src/routes/modules/certificates.ts:36
 #: src/routes/modules/certificates.ts:36
-#: src/views/certificate/CertificateEditor.vue:85
+#: src/views/certificate/CertificateEditor.vue:83
 msgid "Modify Certificate"
 msgid "Modify Certificate"
 msgstr "Sertifikayı Düzenle"
 msgstr "Sertifikayı Düzenle"
 
 
@@ -2892,7 +2924,7 @@ msgstr "Çok Satırlı Yönergeler"
 #: src/components/NgxConfigEditor/NgxUpstream.vue:199
 #: src/components/NgxConfigEditor/NgxUpstream.vue:199
 #: src/views/backup/AutoBackup/AutoBackup.vue:11
 #: src/views/backup/AutoBackup/AutoBackup.vue:11
 #: src/views/certificate/ACMEUser.vue:11
 #: src/views/certificate/ACMEUser.vue:11
-#: src/views/certificate/CertificateEditor.vue:162
+#: src/views/certificate/CertificateEditor.vue:160
 #: src/views/certificate/CertificateList/certColumns.tsx:9
 #: src/views/certificate/CertificateList/certColumns.tsx:9
 #: src/views/certificate/DNSCredential.vue:9
 #: src/views/certificate/DNSCredential.vue:9
 #: src/views/config/components/ConfigRightPanel/Basic.vue:34
 #: src/views/config/components/ConfigRightPanel/Basic.vue:34
@@ -2952,7 +2984,7 @@ msgstr "Yeni Yol"
 msgid "New version released"
 msgid "New version released"
 msgstr "Yeni sürüm yayınlandı"
 msgstr "Yeni sürüm yayınlandı"
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:89
+#: src/views/certificate/components/DNSIssueCertificate.vue:181
 #: src/views/install/components/InstallView.vue:96
 #: src/views/install/components/InstallView.vue:96
 #: src/views/site/site_add/SiteAdd.vue:132
 #: src/views/site/site_add/SiteAdd.vue:132
 #: src/views/site/site_edit/components/Cert/ObtainCert.vue:214
 #: src/views/site/site_edit/components/Cert/ObtainCert.vue:214
@@ -3540,6 +3572,10 @@ msgstr ""
 msgid "Please enter a valid port range"
 msgid "Please enter a valid port range"
 msgstr "Lütfen geçerli bir port aralığı girin"
 msgstr "Lütfen geçerli bir port aralığı girin"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:74
+msgid "Please enter at least one domain"
+msgstr "Lütfen en az bir alan adı girin"
+
 #: src/components/TwoFA/Authorization.vue:85
 #: src/components/TwoFA/Authorization.vue:85
 msgid "Please enter the OTP code:"
 msgid "Please enter the OTP code:"
 msgstr "Lütfen OTP kodunu girin:"
 msgstr "Lütfen OTP kodunu girin:"
@@ -3882,6 +3918,7 @@ msgstr "Yeniden Yükleniyor"
 msgid "Reloading nginx"
 msgid "Reloading nginx"
 msgstr "nginx yeniden yükleniyor"
 msgstr "nginx yeniden yükleniyor"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:144
 #: src/views/preference/tabs/AuthSettings.vue:137
 #: src/views/preference/tabs/AuthSettings.vue:137
 msgid "Remove"
 msgid "Remove"
 msgstr "Kaldır"
 msgstr "Kaldır"
@@ -3974,8 +4011,8 @@ msgstr "Başarıyla yeniden adlandırıldı"
 msgid "Renamed successfully"
 msgid "Renamed successfully"
 msgstr "Başarıyla yeniden adlandırıldı"
 msgstr "Başarıyla yeniden adlandırıldı"
 
 
-#: src/views/certificate/components/RenewCert.vue:46
-#: src/views/certificate/components/RenewCert.vue:53
+#: src/views/certificate/components/RenewCert.vue:48
+#: src/views/certificate/components/RenewCert.vue:55
 msgid "Renew Certificate"
 msgid "Renew Certificate"
 msgstr "Sertifikayı Yenile"
 msgstr "Sertifikayı Yenile"
 
 
@@ -3987,8 +4024,8 @@ msgstr "Sertifika Yenileme Hatası"
 msgid "Renew Certificate Success"
 msgid "Renew Certificate Success"
 msgstr "Sertifika Yenileme Başarılı"
 msgstr "Sertifika Yenileme Başarılı"
 
 
-#: src/views/certificate/components/RenewCert.vue:28
-#: src/views/certificate/components/WildcardCertificate.vue:46
+#: src/views/certificate/components/DNSIssueCertificate.vue:84
+#: src/views/certificate/components/RenewCert.vue:30
 msgid "Renew successfully"
 msgid "Renew successfully"
 msgstr "Başarıyla yenilendi"
 msgstr "Başarıyla yenilendi"
 
 
@@ -4246,7 +4283,7 @@ msgstr "Cumartesi"
 
 
 #: src/components/ChatGPT/ChatMessage.vue:215
 #: src/components/ChatGPT/ChatMessage.vue:215
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:129
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:129
-#: src/language/curd.ts:18 src/views/certificate/CertificateEditor.vue:266
+#: src/language/curd.ts:18 src/views/certificate/CertificateEditor.vue:264
 #: src/views/config/components/ConfigLeftPanel.vue:282
 #: src/views/config/components/ConfigLeftPanel.vue:282
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/preference/components/AuthSettings/Passkey.vue:130
 #: src/views/preference/components/AuthSettings/Passkey.vue:130
@@ -4301,7 +4338,7 @@ msgstr "Akış %{name}, %{node} üzerine kaydedilemedi"
 msgid "Save stream %{name} to %{node} successfully"
 msgid "Save stream %{name} to %{node} successfully"
 msgstr "Akış %{name}, %{node} üzerine başarıyla kaydedildi"
 msgstr "Akış %{name}, %{node} üzerine başarıyla kaydedildi"
 
 
-#: src/language/curd.ts:35 src/views/certificate/CertificateEditor.vue:49
+#: src/language/curd.ts:35 src/views/certificate/store.ts:13
 #: src/views/preference/store/index.ts:118
 #: src/views/preference/store/index.ts:118
 msgid "Save successfully"
 msgid "Save successfully"
 msgstr "Başarıyla kaydedildi"
 msgstr "Başarıyla kaydedildi"
@@ -4409,6 +4446,10 @@ msgstr "Gönder"
 msgid "Server"
 msgid "Server"
 msgstr "Sunucu"
 msgstr "Sunucu"
 
 
+#: src/views/certificate/CertificateEditor.vue:55
+msgid "Server error"
+msgstr "Sunucu hatası"
+
 #: src/views/dashboard/ServerAnalytic.vue:175
 #: src/views/dashboard/ServerAnalytic.vue:175
 msgid "Server Info"
 msgid "Server Info"
 msgstr "Sunucu Bilgisi"
 msgstr "Sunucu Bilgisi"
@@ -4545,7 +4586,7 @@ msgstr "Önbellek yükleyici tekrarları arasındaki bekleme süresi"
 msgid "Sleep time between cache manager iterations"
 msgid "Sleep time between cache manager iterations"
 msgstr "Önbellek yöneticisi yinelemeleri arasındaki bekleme süresi"
 msgstr "Önbellek yöneticisi yinelemeleri arasındaki bekleme süresi"
 
 
-#: src/views/certificate/CertificateEditor.vue:213
+#: src/views/certificate/CertificateEditor.vue:211
 msgid "SSL Certificate Content"
 msgid "SSL Certificate Content"
 msgstr "SSL Sertifika İçeriği"
 msgstr "SSL Sertifika İçeriği"
 
 
@@ -4557,15 +4598,15 @@ msgstr "SSL sertifika dosyası Nginx yapılandırma dizini altında olmalıdır:
 msgid "SSL certificate file not found"
 msgid "SSL certificate file not found"
 msgstr "SSL sertifika dosyası bulunamadı"
 msgstr "SSL sertifika dosyası bulunamadı"
 
 
-#: src/views/certificate/CertificateEditor.vue:227
+#: src/views/certificate/CertificateEditor.vue:225
 msgid "SSL Certificate Key Content"
 msgid "SSL Certificate Key Content"
 msgstr "SSL Sertifika Anahtarı İçeriği"
 msgstr "SSL Sertifika Anahtarı İçeriği"
 
 
-#: src/views/certificate/CertificateEditor.vue:192
+#: src/views/certificate/CertificateEditor.vue:190
 msgid "SSL Certificate Key Path"
 msgid "SSL Certificate Key Path"
 msgstr "SSL Sertifika Anahtar Yolu"
 msgstr "SSL Sertifika Anahtar Yolu"
 
 
-#: src/views/certificate/CertificateEditor.vue:177
+#: src/views/certificate/CertificateEditor.vue:175
 #: src/views/preference/tabs/ServerSettings.vue:37
 #: src/views/preference/tabs/ServerSettings.vue:37
 msgid "SSL Certificate Path"
 msgid "SSL Certificate Path"
 msgstr "SSL Sertifika Yolu"
 msgstr "SSL Sertifika Yolu"
@@ -4804,7 +4845,7 @@ msgstr "Senkronizasyon Düğümleri"
 msgid "Sync strategy"
 msgid "Sync strategy"
 msgstr "Senkronizasyon stratejisi"
 msgstr "Senkronizasyon stratejisi"
 
 
-#: src/views/certificate/CertificateEditor.vue:206
+#: src/views/certificate/CertificateEditor.vue:204
 msgid "Sync to"
 msgid "Sync to"
 msgstr "Senkronize Et"
 msgstr "Senkronize Et"
 
 
@@ -4880,11 +4921,11 @@ msgstr ""
 "ICP Numarası yalnızca harfler, unicode, sayılar, kısa çizgiler, uzun "
 "ICP Numarası yalnızca harfler, unicode, sayılar, kısa çizgiler, uzun "
 "çizgiler, iki nokta üst üste ve noktalar içermelidir."
 "çizgiler, iki nokta üst üste ve noktalar içermelidir."
 
 
-#: src/views/certificate/CertificateEditor.vue:216
+#: src/views/certificate/CertificateEditor.vue:214
 msgid "The input is not a SSL Certificate"
 msgid "The input is not a SSL Certificate"
 msgstr "Girdi bir SSL Sertifikası değil"
 msgstr "Girdi bir SSL Sertifikası değil"
 
 
-#: src/views/certificate/CertificateEditor.vue:230
+#: src/views/certificate/CertificateEditor.vue:228
 msgid "The input is not a SSL Certificate Key"
 msgid "The input is not a SSL Certificate Key"
 msgstr "Girdi bir SSL Sertifika Anahtarı değil"
 msgstr "Girdi bir SSL Sertifika Anahtarı değil"
 
 
@@ -4923,11 +4964,11 @@ msgstr ""
 msgid "The parameter of server_name is required"
 msgid "The parameter of server_name is required"
 msgstr "server_name parametresi gereklidir"
 msgstr "server_name parametresi gereklidir"
 
 
-#: src/views/certificate/CertificateEditor.vue:181
+#: src/views/certificate/CertificateEditor.vue:179
 msgid "The path exists, but the file is not a certificate"
 msgid "The path exists, but the file is not a certificate"
 msgstr "Yol mevcut, ancak dosya bir sertifika değil"
 msgstr "Yol mevcut, ancak dosya bir sertifika değil"
 
 
-#: src/views/certificate/CertificateEditor.vue:196
+#: src/views/certificate/CertificateEditor.vue:194
 msgid "The path exists, but the file is not a private key"
 msgid "The path exists, but the file is not a private key"
 msgstr "Yol mevcut, ancak dosya bir özel anahtar değil"
 msgstr "Yol mevcut, ancak dosya bir özel anahtar değil"
 
 
@@ -4989,17 +5030,17 @@ msgstr ""
 "hesabınıza erişmek için son çaredir. Bu kodları bulamazsanız, hesabınıza "
 "hesabınıza erişmek için son çaredir. Bu kodları bulamazsanız, hesabınıza "
 "erişimi kaybedersiniz."
 "erişimi kaybedersiniz."
 
 
-#: src/views/certificate/CertificateEditor.vue:102
+#: src/views/certificate/CertificateEditor.vue:100
 msgid "This Auto Cert item is invalid, please remove it."
 msgid "This Auto Cert item is invalid, please remove it."
 msgstr "Bu Otomatik Sertifika öğesi geçersiz, lütfen kaldırın."
 msgstr "Bu Otomatik Sertifika öğesi geçersiz, lütfen kaldırın."
 
 
-#: src/views/certificate/CertificateEditor.vue:92
+#: src/views/certificate/CertificateEditor.vue:90
 msgid "This certificate is managed by Nginx UI"
 msgid "This certificate is managed by Nginx UI"
 msgstr "Bu sertifika Nginx UI tarafından yönetilmektedir"
 msgstr "Bu sertifika Nginx UI tarafından yönetilmektedir"
 
 
-#: src/views/certificate/CertificateEditor.vue:165
-#: src/views/certificate/CertificateEditor.vue:179
-#: src/views/certificate/CertificateEditor.vue:194
+#: src/views/certificate/CertificateEditor.vue:163
+#: src/views/certificate/CertificateEditor.vue:177
+#: src/views/certificate/CertificateEditor.vue:192
 msgid "This field is required"
 msgid "This field is required"
 msgstr "Bu alan zorunludur"
 msgstr "Bu alan zorunludur"
 
 
@@ -5479,6 +5520,10 @@ msgstr ""
 msgid "Whether to use a temporary path when writing temporary files"
 msgid "Whether to use a temporary path when writing temporary files"
 msgstr "Geçici dosyalar yazılırken geçici bir yol kullanılıp kullanılmayacağı"
 msgstr "Geçici dosyalar yazılırken geçici bir yol kullanılıp kullanılmayacağı"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:107
+msgid "Wildcard Certificate"
+msgstr "Wildcard Sertifikası"
+
 #: src/views/dashboard/components/ParamsOpt/PerformanceConfig.vue:48
 #: src/views/dashboard/components/ParamsOpt/PerformanceConfig.vue:48
 msgid "Worker Connections"
 msgid "Worker Connections"
 msgstr "Çalışan Bağlantıları"
 msgstr "Çalışan Bağlantıları"
@@ -5815,10 +5860,6 @@ msgstr "Geçiş Anahtarlarınız"
 #~ msgid "Recovery Code:"
 #~ msgid "Recovery Code:"
 #~ msgstr "Kurtarma Kodu:"
 #~ msgstr "Kurtarma Kodu:"
 
 
-#, fuzzy
-#~ msgid "Server error"
-#~ msgstr "Server hatası"
-
 #, fuzzy
 #, fuzzy
 #~ msgid "The recovery code is only displayed once, please save it in a safe place."
 #~ msgid "The recovery code is only displayed once, please save it in a safe place."
 #~ msgstr ""
 #~ msgstr ""

+ 84 - 39
app/src/language/uk_UA/app.po

@@ -185,6 +185,10 @@ msgstr "Додати конфігурацію"
 msgid "Add Directive Below"
 msgid "Add Directive Below"
 msgstr "Додайте директиву нижче"
 msgstr "Додайте директиву нижче"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:151
+msgid "Add Domain"
+msgstr "Додати домен"
+
 #: src/components/NgxConfigEditor/LocationEditor.vue:131
 #: src/components/NgxConfigEditor/LocationEditor.vue:131
 #: src/components/NgxConfigEditor/LocationEditor.vue:158
 #: src/components/NgxConfigEditor/LocationEditor.vue:158
 msgid "Add Location"
 msgid "Add Location"
@@ -232,6 +236,14 @@ msgstr "Усі"
 msgid "All Recovery Codes Have Been Used"
 msgid "All Recovery Codes Have Been Used"
 msgstr "Усі коди відновлення використано"
 msgstr "Усі коди відновлення використано"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:156
+msgid ""
+"All selected subdomains must belong to the same DNS Provider, otherwise the "
+"certificate application will fail."
+msgstr ""
+"Усі вибрані піддомени повинні належати до одного й того самого "
+"DNS-провайдера, інакше запит на сертифікат не буде успішним."
+
 #: src/views/preference/tabs/OpenAISettings.vue:32
 #: src/views/preference/tabs/OpenAISettings.vue:32
 msgid "API Base Url"
 msgid "API Base Url"
 msgstr "Базова URL-адреса API"
 msgstr "Базова URL-адреса API"
@@ -258,7 +270,7 @@ msgstr "Додаток"
 
 
 #: src/views/system/Upgrade.vue:195
 #: src/views/system/Upgrade.vue:195
 msgid "Arch"
 msgid "Arch"
-msgstr "\"Архітектура\""
+msgstr "Архітектура"
 
 
 #: src/views/preference/tabs/AuthSettings.vue:130
 #: src/views/preference/tabs/AuthSettings.vue:130
 msgid "Are you sure to delete this banned IP immediately?"
 msgid "Are you sure to delete this banned IP immediately?"
@@ -397,7 +409,7 @@ msgstr "Автоматичне відновлення вимкнено на %{na
 msgid "Auto-renewal enabled for %{name}"
 msgid "Auto-renewal enabled for %{name}"
 msgstr "Автоматичне відновлення увімкнено для %{name}"
 msgstr "Автоматичне відновлення увімкнено для %{name}"
 
 
-#: src/views/certificate/components/RenewCert.vue:49
+#: src/views/certificate/components/RenewCert.vue:51
 #: src/views/site/site_edit/components/Cert/IssueCert.vue:84
 #: src/views/site/site_edit/components/Cert/IssueCert.vue:84
 msgid "AutoCert is running, please wait..."
 msgid "AutoCert is running, please wait..."
 msgstr "AutoCert виконується, будь ласка, зачекайте..."
 msgstr "AutoCert виконується, будь ласка, зачекайте..."
@@ -410,7 +422,7 @@ msgstr "\"AutoCert виконується...\""
 msgid "Automatic Restart"
 msgid "Automatic Restart"
 msgstr "\"Автоматичний перезапуск\""
 msgstr "\"Автоматичний перезапуск\""
 
 
-#: src/views/certificate/CertificateEditor.vue:259
+#: src/views/certificate/CertificateEditor.vue:257
 #: src/views/config/components/ConfigLeftPanel.vue:273
 #: src/views/config/components/ConfigLeftPanel.vue:273
 #: src/views/config/ConfigList.vue:112 src/views/config/ConfigList.vue:195
 #: src/views/config/ConfigList.vue:112 src/views/config/ConfigList.vue:195
 #: src/views/nginx_log/NginxLog.vue:174
 #: src/views/nginx_log/NginxLog.vue:174
@@ -712,12 +724,16 @@ msgstr "Сертифікат успішно поновлено"
 msgid "Certificate revoked successfully"
 msgid "Certificate revoked successfully"
 msgstr "Сертифікат успішно відкликано"
 msgstr "Сертифікат успішно відкликано"
 
 
-#: src/views/certificate/CertificateEditor.vue:128
+#: src/views/certificate/CertificateEditor.vue:126
 #: src/views/site/site_edit/components/Cert/Cert.vue:58
 #: src/views/site/site_edit/components/Cert/Cert.vue:58
 msgid "Certificate Status"
 msgid "Certificate Status"
 msgid_plural "Certificates Status"
 msgid_plural "Certificates Status"
 msgstr[0] "Стан сертифіката"
 msgstr[0] "Стан сертифіката"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:104
+msgid "Certificate Type"
+msgstr "Тип сертифіката"
+
 #: src/routes/modules/certificates.ts:11
 #: src/routes/modules/certificates.ts:11
 #: src/views/certificate/CertificateList/Certificate.vue:19
 #: src/views/certificate/CertificateList/Certificate.vue:19
 msgid "Certificates"
 msgid "Certificates"
@@ -1241,6 +1257,14 @@ msgstr "Спеціальний cron вираз"
 msgid "Custom Directory"
 msgid "Custom Directory"
 msgstr "Спеціальний каталог"
 msgstr "Спеціальний каталог"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:126
+msgid "Custom Domains"
+msgstr "Користувацькі домени"
+
+#: src/views/certificate/components/DNSIssueCertificate.vue:110
+msgid "Custom Domains Certificate"
+msgstr "Сертифікат користувацьких доменів"
+
 #: src/views/preference/tabs/NodeSettings.vue:19
 #: src/views/preference/tabs/NodeSettings.vue:19
 msgid ""
 msgid ""
 "Customize the name of local node to be displayed in the environment "
 "Customize the name of local node to be displayed in the environment "
@@ -1584,11 +1608,11 @@ msgid "Document"
 msgid_plural "Documents"
 msgid_plural "Documents"
 msgstr[0] "Документ"
 msgstr[0] "Документ"
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:66
+#: src/views/certificate/components/DNSIssueCertificate.vue:116
 msgid "Domain"
 msgid "Domain"
 msgstr "Домен"
 msgstr "Домен"
 
 
-#: src/views/certificate/CertificateEditor.vue:112
+#: src/views/certificate/CertificateEditor.vue:110
 msgid "Domains list is empty, try to reopen Auto Cert for %{config}"
 msgid "Domains list is empty, try to reopen Auto Cert for %{config}"
 msgstr "Список доменів порожній, спробуйте знову відкрити Auto Cert для %{config}"
 msgstr "Список доменів порожній, спробуйте знову відкрити Auto Cert для %{config}"
 
 
@@ -1791,6 +1815,14 @@ msgstr "Зашифрувати вебсайт за допомогою Let's Encr
 msgid "End"
 msgid "End"
 msgstr "Кінець"
 msgstr "Кінець"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:135
+msgid "Enter domain name"
+msgstr "Введіть ім’я домену"
+
+#: src/views/certificate/components/DNSIssueCertificate.vue:120
+msgid "Enter your domain"
+msgstr "Введіть ваш домен"
+
 #: src/language/constants.ts:22
 #: src/language/constants.ts:22
 msgid "Environment variables cleaned"
 msgid "Environment variables cleaned"
 msgstr "Змінні середовища очищено"
 msgstr "Змінні середовища очищено"
@@ -1865,7 +1897,7 @@ msgstr "Зовнішній контейнер Docker"
 msgid "External Notify"
 msgid "External Notify"
 msgstr "Зовнішнє сповіщення"
 msgstr "Зовнішнє сповіщення"
 
 
-#: src/views/site/site_edit/components/Cert/ObtainCertLive.vue:80
+#: src/views/site/site_edit/components/Cert/ObtainCertLive.vue:81
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
 msgstr "Не вдалося отримати сертифікат"
 msgstr "Не вдалося отримати сертифікат"
 
 
@@ -2393,7 +2425,7 @@ msgid "Import"
 msgstr "Імпорт"
 msgstr "Імпорт"
 
 
 #: src/routes/modules/certificates.ts:46
 #: src/routes/modules/certificates.ts:46
-#: src/views/certificate/CertificateEditor.vue:85
+#: src/views/certificate/CertificateEditor.vue:83
 msgid "Import Certificate"
 msgid "Import Certificate"
 msgstr "Імпортувати сертифікат"
 msgstr "Імпортувати сертифікат"
 
 
@@ -2538,12 +2570,12 @@ msgid "IP"
 msgstr "IP"
 msgstr "IP"
 
 
 #: src/views/certificate/CertificateList/Certificate.vue:37
 #: src/views/certificate/CertificateList/Certificate.vue:37
-msgid "Issue wildcard certificate"
-msgstr "Видати сертифікат з маскою"
+msgid "Issue certificate"
+msgstr "Видати сертифікат"
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:57
-msgid "Issue Wildcard Certificate"
-msgstr "Видати сертифікат зі шаблоном"
+#: src/views/certificate/components/DNSIssueCertificate.vue:95
+msgid "Issue Certificate"
+msgstr "Видати сертифікат"
 
 
 #: src/language/constants.ts:20
 #: src/language/constants.ts:20
 msgid "Issued certificate successfully"
 msgid "Issued certificate successfully"
@@ -2626,8 +2658,8 @@ msgstr "Залиште порожнім, якщо не хочете змінюв
 msgid "Leave blank if you don't need this."
 msgid "Leave blank if you don't need this."
 msgstr "Залиште порожнім, якщо вам це не потрібно."
 msgstr "Залиште порожнім, якщо вам це не потрібно."
 
 
-#: src/views/certificate/CertificateEditor.vue:223
-#: src/views/certificate/CertificateEditor.vue:237
+#: src/views/certificate/CertificateEditor.vue:221
+#: src/views/certificate/CertificateEditor.vue:235
 msgid "Leave blank will not change anything"
 msgid "Leave blank will not change anything"
 msgstr "Залишити порожнім — нічого не зміниться"
 msgstr "Залишити порожнім — нічого не зміниться"
 
 
@@ -2714,7 +2746,7 @@ msgstr "Розташування"
 msgid "Locations"
 msgid "Locations"
 msgstr "Розташування"
 msgstr "Розташування"
 
 
-#: src/views/certificate/CertificateEditor.vue:247
+#: src/views/certificate/CertificateEditor.vue:245
 msgid "Log"
 msgid "Log"
 msgstr "Журнал"
 msgstr "Журнал"
 
 
@@ -2928,7 +2960,7 @@ msgid "Modify"
 msgstr "Змінити"
 msgstr "Змінити"
 
 
 #: src/routes/modules/certificates.ts:36
 #: src/routes/modules/certificates.ts:36
-#: src/views/certificate/CertificateEditor.vue:85
+#: src/views/certificate/CertificateEditor.vue:83
 msgid "Modify Certificate"
 msgid "Modify Certificate"
 msgstr "Редагувати сертифікат"
 msgstr "Редагувати сертифікат"
 
 
@@ -2963,7 +2995,7 @@ msgstr "Багаторядкова директива"
 #: src/components/NgxConfigEditor/NgxUpstream.vue:199
 #: src/components/NgxConfigEditor/NgxUpstream.vue:199
 #: src/views/backup/AutoBackup/AutoBackup.vue:11
 #: src/views/backup/AutoBackup/AutoBackup.vue:11
 #: src/views/certificate/ACMEUser.vue:11
 #: src/views/certificate/ACMEUser.vue:11
-#: src/views/certificate/CertificateEditor.vue:162
+#: src/views/certificate/CertificateEditor.vue:160
 #: src/views/certificate/CertificateList/certColumns.tsx:9
 #: src/views/certificate/CertificateList/certColumns.tsx:9
 #: src/views/certificate/DNSCredential.vue:9
 #: src/views/certificate/DNSCredential.vue:9
 #: src/views/config/components/ConfigRightPanel/Basic.vue:34
 #: src/views/config/components/ConfigRightPanel/Basic.vue:34
@@ -3023,7 +3055,7 @@ msgstr "Новий шлях"
 msgid "New version released"
 msgid "New version released"
 msgstr "Випущено нову версію"
 msgstr "Випущено нову версію"
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:89
+#: src/views/certificate/components/DNSIssueCertificate.vue:181
 #: src/views/install/components/InstallView.vue:96
 #: src/views/install/components/InstallView.vue:96
 #: src/views/site/site_add/SiteAdd.vue:132
 #: src/views/site/site_add/SiteAdd.vue:132
 #: src/views/site/site_edit/components/Cert/ObtainCert.vue:214
 #: src/views/site/site_edit/components/Cert/ObtainCert.vue:214
@@ -3612,6 +3644,10 @@ msgstr ""
 msgid "Please enter a valid port range"
 msgid "Please enter a valid port range"
 msgstr "Будь ласка, введіть дійсний діапазон портів"
 msgstr "Будь ласка, введіть дійсний діапазон портів"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:74
+msgid "Please enter at least one domain"
+msgstr "Будь ласка, введіть хоча б один домен"
+
 #: src/components/TwoFA/Authorization.vue:85
 #: src/components/TwoFA/Authorization.vue:85
 msgid "Please enter the OTP code:"
 msgid "Please enter the OTP code:"
 msgstr "Будь ласка, введіть OTP-код:"
 msgstr "Будь ласка, введіть OTP-код:"
@@ -3957,6 +3993,7 @@ msgstr "Перезавантаження"
 msgid "Reloading nginx"
 msgid "Reloading nginx"
 msgstr "Перезавантаження nginx"
 msgstr "Перезавантаження nginx"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:144
 #: src/views/preference/tabs/AuthSettings.vue:137
 #: src/views/preference/tabs/AuthSettings.vue:137
 msgid "Remove"
 msgid "Remove"
 msgstr "Видалити"
 msgstr "Видалити"
@@ -4039,8 +4076,8 @@ msgstr "Успішно перейменовано"
 msgid "Renamed successfully"
 msgid "Renamed successfully"
 msgstr "Успішно перейменовано"
 msgstr "Успішно перейменовано"
 
 
-#: src/views/certificate/components/RenewCert.vue:46
-#: src/views/certificate/components/RenewCert.vue:53
+#: src/views/certificate/components/RenewCert.vue:48
+#: src/views/certificate/components/RenewCert.vue:55
 msgid "Renew Certificate"
 msgid "Renew Certificate"
 msgstr "Оновити сертифікат"
 msgstr "Оновити сертифікат"
 
 
@@ -4052,8 +4089,8 @@ msgstr "Помилка поновлення сертифіката"
 msgid "Renew Certificate Success"
 msgid "Renew Certificate Success"
 msgstr "Успішне поновлення сертифіката"
 msgstr "Успішне поновлення сертифіката"
 
 
-#: src/views/certificate/components/RenewCert.vue:28
-#: src/views/certificate/components/WildcardCertificate.vue:46
+#: src/views/certificate/components/DNSIssueCertificate.vue:84
+#: src/views/certificate/components/RenewCert.vue:30
 msgid "Renew successfully"
 msgid "Renew successfully"
 msgstr "Оновлення успішне"
 msgstr "Оновлення успішне"
 
 
@@ -4314,7 +4351,7 @@ msgstr "Субота"
 
 
 #: src/components/ChatGPT/ChatMessage.vue:215
 #: src/components/ChatGPT/ChatMessage.vue:215
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:129
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:129
-#: src/language/curd.ts:18 src/views/certificate/CertificateEditor.vue:266
+#: src/language/curd.ts:18 src/views/certificate/CertificateEditor.vue:264
 #: src/views/config/components/ConfigLeftPanel.vue:282
 #: src/views/config/components/ConfigLeftPanel.vue:282
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/preference/components/AuthSettings/Passkey.vue:130
 #: src/views/preference/components/AuthSettings/Passkey.vue:130
@@ -4369,7 +4406,7 @@ msgstr "Не вдалося зберегти потік %{name} на %{node}"
 msgid "Save stream %{name} to %{node} successfully"
 msgid "Save stream %{name} to %{node} successfully"
 msgstr "Потік %{name} успішно збережено на %{node}"
 msgstr "Потік %{name} успішно збережено на %{node}"
 
 
-#: src/language/curd.ts:35 src/views/certificate/CertificateEditor.vue:49
+#: src/language/curd.ts:35 src/views/certificate/store.ts:13
 #: src/views/preference/store/index.ts:118
 #: src/views/preference/store/index.ts:118
 msgid "Save successfully"
 msgid "Save successfully"
 msgstr "Успішно збережено"
 msgstr "Успішно збережено"
@@ -4479,6 +4516,10 @@ msgstr "Надіслати"
 msgid "Server"
 msgid "Server"
 msgstr "Сервер"
 msgstr "Сервер"
 
 
+#: src/views/certificate/CertificateEditor.vue:55
+msgid "Server error"
+msgstr "Помилка сервера"
+
 #: src/views/dashboard/ServerAnalytic.vue:175
 #: src/views/dashboard/ServerAnalytic.vue:175
 msgid "Server Info"
 msgid "Server Info"
 msgstr "Інформація про сервер"
 msgstr "Інформація про сервер"
@@ -4617,7 +4658,7 @@ msgstr "Час очікування між ітераціями завантаж
 msgid "Sleep time between cache manager iterations"
 msgid "Sleep time between cache manager iterations"
 msgstr "Час очікування між ітераціями менеджера кешу"
 msgstr "Час очікування між ітераціями менеджера кешу"
 
 
-#: src/views/certificate/CertificateEditor.vue:213
+#: src/views/certificate/CertificateEditor.vue:211
 msgid "SSL Certificate Content"
 msgid "SSL Certificate Content"
 msgstr "Вміст SSL-сертифіката"
 msgstr "Вміст SSL-сертифіката"
 
 
@@ -4629,15 +4670,15 @@ msgstr "Файл SSL-сертифіката повинен знаходитис
 msgid "SSL certificate file not found"
 msgid "SSL certificate file not found"
 msgstr "Файл SSL-сертифіката не знайдено"
 msgstr "Файл SSL-сертифіката не знайдено"
 
 
-#: src/views/certificate/CertificateEditor.vue:227
+#: src/views/certificate/CertificateEditor.vue:225
 msgid "SSL Certificate Key Content"
 msgid "SSL Certificate Key Content"
 msgstr "Вміст ключа SSL-сертифіката"
 msgstr "Вміст ключа SSL-сертифіката"
 
 
-#: src/views/certificate/CertificateEditor.vue:192
+#: src/views/certificate/CertificateEditor.vue:190
 msgid "SSL Certificate Key Path"
 msgid "SSL Certificate Key Path"
 msgstr "Шлях до ключа SSL-сертифіката"
 msgstr "Шлях до ключа SSL-сертифіката"
 
 
-#: src/views/certificate/CertificateEditor.vue:177
+#: src/views/certificate/CertificateEditor.vue:175
 #: src/views/preference/tabs/ServerSettings.vue:37
 #: src/views/preference/tabs/ServerSettings.vue:37
 msgid "SSL Certificate Path"
 msgid "SSL Certificate Path"
 msgstr "Шлях до SSL-сертифікату"
 msgstr "Шлях до SSL-сертифікату"
@@ -4874,7 +4915,7 @@ msgstr "Синхронізовані вузли"
 msgid "Sync strategy"
 msgid "Sync strategy"
 msgstr "Стратегія синхронізації"
 msgstr "Стратегія синхронізації"
 
 
-#: src/views/certificate/CertificateEditor.vue:206
+#: src/views/certificate/CertificateEditor.vue:204
 msgid "Sync to"
 msgid "Sync to"
 msgstr "Синхронізувати з"
 msgstr "Синхронізувати з"
 
 
@@ -4950,11 +4991,11 @@ msgstr ""
 "Номер ICP повинен містити лише літери, unicode, цифри, дефіси, тире, "
 "Номер ICP повинен містити лише літери, unicode, цифри, дефіси, тире, "
 "двокрапки та крапки."
 "двокрапки та крапки."
 
 
-#: src/views/certificate/CertificateEditor.vue:216
+#: src/views/certificate/CertificateEditor.vue:214
 msgid "The input is not a SSL Certificate"
 msgid "The input is not a SSL Certificate"
 msgstr "Введені дані не є SSL-сертифікатом"
 msgstr "Введені дані не є SSL-сертифікатом"
 
 
-#: src/views/certificate/CertificateEditor.vue:230
+#: src/views/certificate/CertificateEditor.vue:228
 msgid "The input is not a SSL Certificate Key"
 msgid "The input is not a SSL Certificate Key"
 msgstr "Введений текст не є ключем SSL-сертифіката"
 msgstr "Введений текст не є ключем SSL-сертифіката"
 
 
@@ -4993,11 +5034,11 @@ msgstr ""
 msgid "The parameter of server_name is required"
 msgid "The parameter of server_name is required"
 msgstr "Параметр server_name є обов'язковим"
 msgstr "Параметр server_name є обов'язковим"
 
 
-#: src/views/certificate/CertificateEditor.vue:181
+#: src/views/certificate/CertificateEditor.vue:179
 msgid "The path exists, but the file is not a certificate"
 msgid "The path exists, but the file is not a certificate"
 msgstr "Шлях існує, але файл не є сертифікатом"
 msgstr "Шлях існує, але файл не є сертифікатом"
 
 
-#: src/views/certificate/CertificateEditor.vue:196
+#: src/views/certificate/CertificateEditor.vue:194
 msgid "The path exists, but the file is not a private key"
 msgid "The path exists, but the file is not a private key"
 msgstr "Шлях існує, але файл не є приватним ключем"
 msgstr "Шлях існує, але файл не є приватним ключем"
 
 
@@ -5059,19 +5100,19 @@ msgstr ""
 "втрати пароля та других факторів. Якщо ви не зможете знайти ці коди, ви "
 "втрати пароля та других факторів. Якщо ви не зможете знайти ці коди, ви "
 "втратите доступ до свого облікового запису."
 "втратите доступ до свого облікового запису."
 
 
-#: src/views/certificate/CertificateEditor.vue:102
+#: src/views/certificate/CertificateEditor.vue:100
 msgid "This Auto Cert item is invalid, please remove it."
 msgid "This Auto Cert item is invalid, please remove it."
 msgstr ""
 msgstr ""
 "Цей елемент автоматичного сертифікату є недійсним, будь ласка, видаліть "
 "Цей елемент автоматичного сертифікату є недійсним, будь ласка, видаліть "
 "його."
 "його."
 
 
-#: src/views/certificate/CertificateEditor.vue:92
+#: src/views/certificate/CertificateEditor.vue:90
 msgid "This certificate is managed by Nginx UI"
 msgid "This certificate is managed by Nginx UI"
 msgstr "Цей сертифікат керується Nginx UI"
 msgstr "Цей сертифікат керується Nginx UI"
 
 
-#: src/views/certificate/CertificateEditor.vue:165
-#: src/views/certificate/CertificateEditor.vue:179
-#: src/views/certificate/CertificateEditor.vue:194
+#: src/views/certificate/CertificateEditor.vue:163
+#: src/views/certificate/CertificateEditor.vue:177
+#: src/views/certificate/CertificateEditor.vue:192
 msgid "This field is required"
 msgid "This field is required"
 msgstr "Це поле обов'язкове"
 msgstr "Це поле обов'язкове"
 
 
@@ -5548,6 +5589,10 @@ msgstr ""
 msgid "Whether to use a temporary path when writing temporary files"
 msgid "Whether to use a temporary path when writing temporary files"
 msgstr "Чи використовувати тимчасовий шлях під час запису тимчасових файлів"
 msgstr "Чи використовувати тимчасовий шлях під час запису тимчасових файлів"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:107
+msgid "Wildcard Certificate"
+msgstr "Сертифікат зі знаком підстановки"
+
 #: src/views/dashboard/components/ParamsOpt/PerformanceConfig.vue:48
 #: src/views/dashboard/components/ParamsOpt/PerformanceConfig.vue:48
 msgid "Worker Connections"
 msgid "Worker Connections"
 msgstr "Робочі з’єднання"
 msgstr "Робочі з’єднання"

+ 84 - 42
app/src/language/vi_VN/app.po

@@ -176,6 +176,10 @@ msgstr "Thêm cấu hình"
 msgid "Add Directive Below"
 msgid "Add Directive Below"
 msgstr "Thêm Directive"
 msgstr "Thêm Directive"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:151
+msgid "Add Domain"
+msgstr "Thêm tên miền"
+
 #: src/components/NgxConfigEditor/LocationEditor.vue:131
 #: src/components/NgxConfigEditor/LocationEditor.vue:131
 #: src/components/NgxConfigEditor/LocationEditor.vue:158
 #: src/components/NgxConfigEditor/LocationEditor.vue:158
 msgid "Add Location"
 msgid "Add Location"
@@ -223,6 +227,14 @@ msgstr "Tất cả"
 msgid "All Recovery Codes Have Been Used"
 msgid "All Recovery Codes Have Been Used"
 msgstr "Tất cả mã khôi phục đã được sử dụng"
 msgstr "Tất cả mã khôi phục đã được sử dụng"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:156
+msgid ""
+"All selected subdomains must belong to the same DNS Provider, otherwise the "
+"certificate application will fail."
+msgstr ""
+"Tất cả các tên miền phụ được chọn phải thuộc cùng một Nhà cung cấp DNS, nếu "
+"không, việc xin cấp chứng chỉ sẽ thất bại."
+
 #: src/views/preference/tabs/OpenAISettings.vue:32
 #: src/views/preference/tabs/OpenAISettings.vue:32
 msgid "API Base Url"
 msgid "API Base Url"
 msgstr "URL Cơ sở API"
 msgstr "URL Cơ sở API"
@@ -249,7 +261,7 @@ msgstr "Ứng dụng"
 
 
 #: src/views/system/Upgrade.vue:195
 #: src/views/system/Upgrade.vue:195
 msgid "Arch"
 msgid "Arch"
-msgstr "\"Kiến trúc\""
+msgstr "Kiến trúc"
 
 
 #: src/views/preference/tabs/AuthSettings.vue:130
 #: src/views/preference/tabs/AuthSettings.vue:130
 msgid "Are you sure to delete this banned IP immediately?"
 msgid "Are you sure to delete this banned IP immediately?"
@@ -384,7 +396,7 @@ msgstr "Đã tắt tự động gia hạn SSL cho %{name}"
 msgid "Auto-renewal enabled for %{name}"
 msgid "Auto-renewal enabled for %{name}"
 msgstr "Đã bật tự động gia hạn SSL cho %{name}"
 msgstr "Đã bật tự động gia hạn SSL cho %{name}"
 
 
-#: src/views/certificate/components/RenewCert.vue:49
+#: src/views/certificate/components/RenewCert.vue:51
 #: src/views/site/site_edit/components/Cert/IssueCert.vue:84
 #: src/views/site/site_edit/components/Cert/IssueCert.vue:84
 msgid "AutoCert is running, please wait..."
 msgid "AutoCert is running, please wait..."
 msgstr "AutoCert đang chạy, vui lòng chờ..."
 msgstr "AutoCert đang chạy, vui lòng chờ..."
@@ -397,7 +409,7 @@ msgstr "\"AutoCert đang chạy...\""
 msgid "Automatic Restart"
 msgid "Automatic Restart"
 msgstr "\"Khởi động lại Tự động\""
 msgstr "\"Khởi động lại Tự động\""
 
 
-#: src/views/certificate/CertificateEditor.vue:259
+#: src/views/certificate/CertificateEditor.vue:257
 #: src/views/config/components/ConfigLeftPanel.vue:273
 #: src/views/config/components/ConfigLeftPanel.vue:273
 #: src/views/config/ConfigList.vue:112 src/views/config/ConfigList.vue:195
 #: src/views/config/ConfigList.vue:112 src/views/config/ConfigList.vue:195
 #: src/views/nginx_log/NginxLog.vue:174
 #: src/views/nginx_log/NginxLog.vue:174
@@ -692,12 +704,16 @@ msgstr "Gia hạn chứng chỉ thành công"
 msgid "Certificate revoked successfully"
 msgid "Certificate revoked successfully"
 msgstr "Hủy chứng chỉ thành công"
 msgstr "Hủy chứng chỉ thành công"
 
 
-#: src/views/certificate/CertificateEditor.vue:128
+#: src/views/certificate/CertificateEditor.vue:126
 #: src/views/site/site_edit/components/Cert/Cert.vue:58
 #: src/views/site/site_edit/components/Cert/Cert.vue:58
 msgid "Certificate Status"
 msgid "Certificate Status"
 msgid_plural "Certificates Status"
 msgid_plural "Certificates Status"
 msgstr[0] "Trạng thái chứng chỉ"
 msgstr[0] "Trạng thái chứng chỉ"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:104
+msgid "Certificate Type"
+msgstr "Loại chứng chỉ"
+
 #: src/routes/modules/certificates.ts:11
 #: src/routes/modules/certificates.ts:11
 #: src/views/certificate/CertificateList/Certificate.vue:19
 #: src/views/certificate/CertificateList/Certificate.vue:19
 msgid "Certificates"
 msgid "Certificates"
@@ -1181,6 +1197,14 @@ msgstr "Biểu thức cron tùy chỉnh"
 msgid "Custom Directory"
 msgid "Custom Directory"
 msgstr "Thư mục tùy chỉnh"
 msgstr "Thư mục tùy chỉnh"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:126
+msgid "Custom Domains"
+msgstr "Tên miền tùy chỉnh"
+
+#: src/views/certificate/components/DNSIssueCertificate.vue:110
+msgid "Custom Domains Certificate"
+msgstr "Chứng chỉ Tên miền Tùy chỉnh"
+
 #: src/views/preference/tabs/NodeSettings.vue:19
 #: src/views/preference/tabs/NodeSettings.vue:19
 msgid ""
 msgid ""
 "Customize the name of local node to be displayed in the environment "
 "Customize the name of local node to be displayed in the environment "
@@ -1488,11 +1512,11 @@ msgid "Document"
 msgid_plural "Documents"
 msgid_plural "Documents"
 msgstr[0] "Tài liệu"
 msgstr[0] "Tài liệu"
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:66
+#: src/views/certificate/components/DNSIssueCertificate.vue:116
 msgid "Domain"
 msgid "Domain"
 msgstr "Tên miền"
 msgstr "Tên miền"
 
 
-#: src/views/certificate/CertificateEditor.vue:112
+#: src/views/certificate/CertificateEditor.vue:110
 msgid "Domains list is empty, try to reopen Auto Cert for %{config}"
 msgid "Domains list is empty, try to reopen Auto Cert for %{config}"
 msgstr ""
 msgstr ""
 "Danh sách tên miền rỗng, hãy thử mở lại chức năng Tạo chứng chỉ tự động cho "
 "Danh sách tên miền rỗng, hãy thử mở lại chức năng Tạo chứng chỉ tự động cho "
@@ -1696,6 +1720,14 @@ msgstr "Bảo mật trang web với Let's Encrypt"
 msgid "End"
 msgid "End"
 msgstr "Kết thúc"
 msgstr "Kết thúc"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:135
+msgid "Enter domain name"
+msgstr "Nhập tên miền"
+
+#: src/views/certificate/components/DNSIssueCertificate.vue:120
+msgid "Enter your domain"
+msgstr "Nhập tên miền của bạn"
+
 #: src/language/constants.ts:22
 #: src/language/constants.ts:22
 msgid "Environment variables cleaned"
 msgid "Environment variables cleaned"
 msgstr "Đã dọn dẹp biến môi trường"
 msgstr "Đã dọn dẹp biến môi trường"
@@ -1770,7 +1802,7 @@ msgstr "Container Docker bên ngoài"
 msgid "External Notify"
 msgid "External Notify"
 msgstr "Thông báo bên ngoài"
 msgstr "Thông báo bên ngoài"
 
 
-#: src/views/site/site_edit/components/Cert/ObtainCertLive.vue:80
+#: src/views/site/site_edit/components/Cert/ObtainCertLive.vue:81
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
 msgstr "Không thể lấy chứng chỉ"
 msgstr "Không thể lấy chứng chỉ"
 
 
@@ -2297,7 +2329,7 @@ msgid "Import"
 msgstr "Nhập"
 msgstr "Nhập"
 
 
 #: src/routes/modules/certificates.ts:46
 #: src/routes/modules/certificates.ts:46
-#: src/views/certificate/CertificateEditor.vue:85
+#: src/views/certificate/CertificateEditor.vue:83
 msgid "Import Certificate"
 msgid "Import Certificate"
 msgstr "Nhập chứng chỉ"
 msgstr "Nhập chứng chỉ"
 
 
@@ -2442,12 +2474,12 @@ msgid "IP"
 msgstr "IP"
 msgstr "IP"
 
 
 #: src/views/certificate/CertificateList/Certificate.vue:37
 #: src/views/certificate/CertificateList/Certificate.vue:37
-msgid "Issue wildcard certificate"
-msgstr "Phát hành chứng chỉ đại diện"
+msgid "Issue certificate"
+msgstr "Cấp chứng chỉ"
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:57
-msgid "Issue Wildcard Certificate"
-msgstr "Cấp chứng chỉ đại diện"
+#: src/views/certificate/components/DNSIssueCertificate.vue:95
+msgid "Issue Certificate"
+msgstr "Cấp chứng chỉ"
 
 
 #: src/language/constants.ts:20
 #: src/language/constants.ts:20
 msgid "Issued certificate successfully"
 msgid "Issued certificate successfully"
@@ -2530,8 +2562,8 @@ msgstr "Để trống nếu không muốn thay đổi"
 msgid "Leave blank if you don't need this."
 msgid "Leave blank if you don't need this."
 msgstr "Để trống nếu bạn không cần cái này."
 msgstr "Để trống nếu bạn không cần cái này."
 
 
-#: src/views/certificate/CertificateEditor.vue:223
-#: src/views/certificate/CertificateEditor.vue:237
+#: src/views/certificate/CertificateEditor.vue:221
+#: src/views/certificate/CertificateEditor.vue:235
 msgid "Leave blank will not change anything"
 msgid "Leave blank will not change anything"
 msgstr "Để trống sẽ không thay đổi bất cứ điều gì"
 msgstr "Để trống sẽ không thay đổi bất cứ điều gì"
 
 
@@ -2618,7 +2650,7 @@ msgstr "Location"
 msgid "Locations"
 msgid "Locations"
 msgstr "Locations"
 msgstr "Locations"
 
 
-#: src/views/certificate/CertificateEditor.vue:247
+#: src/views/certificate/CertificateEditor.vue:245
 msgid "Log"
 msgid "Log"
 msgstr "Nhật ký"
 msgstr "Nhật ký"
 
 
@@ -2832,7 +2864,7 @@ msgid "Modify"
 msgstr "Sửa đổi"
 msgstr "Sửa đổi"
 
 
 #: src/routes/modules/certificates.ts:36
 #: src/routes/modules/certificates.ts:36
-#: src/views/certificate/CertificateEditor.vue:85
+#: src/views/certificate/CertificateEditor.vue:83
 msgid "Modify Certificate"
 msgid "Modify Certificate"
 msgstr "Sửa đổi chứng chỉ"
 msgstr "Sửa đổi chứng chỉ"
 
 
@@ -2867,7 +2899,7 @@ msgstr "Chỉ thị nhiều dòng"
 #: src/components/NgxConfigEditor/NgxUpstream.vue:199
 #: src/components/NgxConfigEditor/NgxUpstream.vue:199
 #: src/views/backup/AutoBackup/AutoBackup.vue:11
 #: src/views/backup/AutoBackup/AutoBackup.vue:11
 #: src/views/certificate/ACMEUser.vue:11
 #: src/views/certificate/ACMEUser.vue:11
-#: src/views/certificate/CertificateEditor.vue:162
+#: src/views/certificate/CertificateEditor.vue:160
 #: src/views/certificate/CertificateList/certColumns.tsx:9
 #: src/views/certificate/CertificateList/certColumns.tsx:9
 #: src/views/certificate/DNSCredential.vue:9
 #: src/views/certificate/DNSCredential.vue:9
 #: src/views/config/components/ConfigRightPanel/Basic.vue:34
 #: src/views/config/components/ConfigRightPanel/Basic.vue:34
@@ -2927,7 +2959,7 @@ msgstr "Đường dẫn mới"
 msgid "New version released"
 msgid "New version released"
 msgstr "Đã có phiên bản mới"
 msgstr "Đã có phiên bản mới"
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:89
+#: src/views/certificate/components/DNSIssueCertificate.vue:181
 #: src/views/install/components/InstallView.vue:96
 #: src/views/install/components/InstallView.vue:96
 #: src/views/site/site_add/SiteAdd.vue:132
 #: src/views/site/site_add/SiteAdd.vue:132
 #: src/views/site/site_edit/components/Cert/ObtainCert.vue:214
 #: src/views/site/site_edit/components/Cert/ObtainCert.vue:214
@@ -3514,6 +3546,10 @@ msgstr ""
 msgid "Please enter a valid port range"
 msgid "Please enter a valid port range"
 msgstr "Vui lòng nhập một phạm vi cổng hợp lệ"
 msgstr "Vui lòng nhập một phạm vi cổng hợp lệ"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:74
+msgid "Please enter at least one domain"
+msgstr "Vui lòng nhập ít nhất một tên miền"
+
 #: src/components/TwoFA/Authorization.vue:85
 #: src/components/TwoFA/Authorization.vue:85
 msgid "Please enter the OTP code:"
 msgid "Please enter the OTP code:"
 msgstr "Vui lòng nhập mã OTP:"
 msgstr "Vui lòng nhập mã OTP:"
@@ -3847,6 +3883,7 @@ msgstr "Đang tải lại"
 msgid "Reloading nginx"
 msgid "Reloading nginx"
 msgstr "Tải lại nginx"
 msgstr "Tải lại nginx"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:144
 #: src/views/preference/tabs/AuthSettings.vue:137
 #: src/views/preference/tabs/AuthSettings.vue:137
 msgid "Remove"
 msgid "Remove"
 msgstr "Xóa"
 msgstr "Xóa"
@@ -3929,8 +3966,8 @@ msgstr "Đổi tên thành công"
 msgid "Renamed successfully"
 msgid "Renamed successfully"
 msgstr "Đổi tên thành công"
 msgstr "Đổi tên thành công"
 
 
-#: src/views/certificate/components/RenewCert.vue:46
-#: src/views/certificate/components/RenewCert.vue:53
+#: src/views/certificate/components/RenewCert.vue:48
+#: src/views/certificate/components/RenewCert.vue:55
 msgid "Renew Certificate"
 msgid "Renew Certificate"
 msgstr "Gia hạn chứng chỉ"
 msgstr "Gia hạn chứng chỉ"
 
 
@@ -3942,8 +3979,8 @@ msgstr "Lỗi gia hạn chứng chỉ"
 msgid "Renew Certificate Success"
 msgid "Renew Certificate Success"
 msgstr "Gia hạn chứng chỉ thành công"
 msgstr "Gia hạn chứng chỉ thành công"
 
 
-#: src/views/certificate/components/RenewCert.vue:28
-#: src/views/certificate/components/WildcardCertificate.vue:46
+#: src/views/certificate/components/DNSIssueCertificate.vue:84
+#: src/views/certificate/components/RenewCert.vue:30
 msgid "Renew successfully"
 msgid "Renew successfully"
 msgstr "Gia hạn thành công"
 msgstr "Gia hạn thành công"
 
 
@@ -4202,7 +4239,7 @@ msgstr "Thứ Bảy"
 
 
 #: src/components/ChatGPT/ChatMessage.vue:215
 #: src/components/ChatGPT/ChatMessage.vue:215
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:129
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:129
-#: src/language/curd.ts:18 src/views/certificate/CertificateEditor.vue:266
+#: src/language/curd.ts:18 src/views/certificate/CertificateEditor.vue:264
 #: src/views/config/components/ConfigLeftPanel.vue:282
 #: src/views/config/components/ConfigLeftPanel.vue:282
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/preference/components/AuthSettings/Passkey.vue:130
 #: src/views/preference/components/AuthSettings/Passkey.vue:130
@@ -4257,7 +4294,7 @@ msgstr "Lưu luồng %{name} vào %{node} thất bại"
 msgid "Save stream %{name} to %{node} successfully"
 msgid "Save stream %{name} to %{node} successfully"
 msgstr "Đã lưu luồng %{name} vào %{node} thành công"
 msgstr "Đã lưu luồng %{name} vào %{node} thành công"
 
 
-#: src/language/curd.ts:35 src/views/certificate/CertificateEditor.vue:49
+#: src/language/curd.ts:35 src/views/certificate/store.ts:13
 #: src/views/preference/store/index.ts:118
 #: src/views/preference/store/index.ts:118
 msgid "Save successfully"
 msgid "Save successfully"
 msgstr "Lưu thành công"
 msgstr "Lưu thành công"
@@ -4365,6 +4402,10 @@ msgstr "Gửi"
 msgid "Server"
 msgid "Server"
 msgstr "Máy chủ"
 msgstr "Máy chủ"
 
 
+#: src/views/certificate/CertificateEditor.vue:55
+msgid "Server error"
+msgstr "Lỗi máy chủ"
+
 #: src/views/dashboard/ServerAnalytic.vue:175
 #: src/views/dashboard/ServerAnalytic.vue:175
 msgid "Server Info"
 msgid "Server Info"
 msgstr "Thông tin máy chủ"
 msgstr "Thông tin máy chủ"
@@ -4501,7 +4542,7 @@ msgstr "Thời gian chờ giữa các lần lặp của bộ nạp bộ đệm"
 msgid "Sleep time between cache manager iterations"
 msgid "Sleep time between cache manager iterations"
 msgstr "Thời gian chờ giữa các lần lặp của trình quản lý bộ nhớ đệm"
 msgstr "Thời gian chờ giữa các lần lặp của trình quản lý bộ nhớ đệm"
 
 
-#: src/views/certificate/CertificateEditor.vue:213
+#: src/views/certificate/CertificateEditor.vue:211
 msgid "SSL Certificate Content"
 msgid "SSL Certificate Content"
 msgstr "Nội dung chứng chỉ SSL"
 msgstr "Nội dung chứng chỉ SSL"
 
 
@@ -4513,15 +4554,15 @@ msgstr "Tệp chứng chỉ SSL phải nằm trong thư mục cấu hình Nginx:
 msgid "SSL certificate file not found"
 msgid "SSL certificate file not found"
 msgstr "Không tìm thấy tệp chứng chỉ SSL"
 msgstr "Không tìm thấy tệp chứng chỉ SSL"
 
 
-#: src/views/certificate/CertificateEditor.vue:227
+#: src/views/certificate/CertificateEditor.vue:225
 msgid "SSL Certificate Key Content"
 msgid "SSL Certificate Key Content"
 msgstr "Nội dung khóa chứng chỉ SSL"
 msgstr "Nội dung khóa chứng chỉ SSL"
 
 
-#: src/views/certificate/CertificateEditor.vue:192
+#: src/views/certificate/CertificateEditor.vue:190
 msgid "SSL Certificate Key Path"
 msgid "SSL Certificate Key Path"
 msgstr "Đường dẫn khóa chứng chỉ SSL"
 msgstr "Đường dẫn khóa chứng chỉ SSL"
 
 
-#: src/views/certificate/CertificateEditor.vue:177
+#: src/views/certificate/CertificateEditor.vue:175
 #: src/views/preference/tabs/ServerSettings.vue:37
 #: src/views/preference/tabs/ServerSettings.vue:37
 msgid "SSL Certificate Path"
 msgid "SSL Certificate Path"
 msgstr "Đường dẫn chứng chỉ SSL"
 msgstr "Đường dẫn chứng chỉ SSL"
@@ -4758,7 +4799,7 @@ msgstr "Nút đồng bộ"
 msgid "Sync strategy"
 msgid "Sync strategy"
 msgstr "Chiến lược đồng bộ hóa"
 msgstr "Chiến lược đồng bộ hóa"
 
 
-#: src/views/certificate/CertificateEditor.vue:206
+#: src/views/certificate/CertificateEditor.vue:204
 msgid "Sync to"
 msgid "Sync to"
 msgstr "Đồng bộ tới"
 msgstr "Đồng bộ tới"
 
 
@@ -4834,11 +4875,11 @@ msgstr ""
 "Số ICP chỉ được chứa chữ cái, unicode, số, dấu gạch ngang, dấu gạch dài, "
 "Số ICP chỉ được chứa chữ cái, unicode, số, dấu gạch ngang, dấu gạch dài, "
 "dấu hai chấm và dấu chấm."
 "dấu hai chấm và dấu chấm."
 
 
-#: src/views/certificate/CertificateEditor.vue:216
+#: src/views/certificate/CertificateEditor.vue:214
 msgid "The input is not a SSL Certificate"
 msgid "The input is not a SSL Certificate"
 msgstr "Đầu vào không phải là Chứng chỉ SSL"
 msgstr "Đầu vào không phải là Chứng chỉ SSL"
 
 
-#: src/views/certificate/CertificateEditor.vue:230
+#: src/views/certificate/CertificateEditor.vue:228
 msgid "The input is not a SSL Certificate Key"
 msgid "The input is not a SSL Certificate Key"
 msgstr "Đầu vào không phải là Khóa Chứng chỉ SSL"
 msgstr "Đầu vào không phải là Khóa Chứng chỉ SSL"
 
 
@@ -4877,11 +4918,11 @@ msgstr ""
 msgid "The parameter of server_name is required"
 msgid "The parameter of server_name is required"
 msgstr "Tham số của server_name là bắt buộc"
 msgstr "Tham số của server_name là bắt buộc"
 
 
-#: src/views/certificate/CertificateEditor.vue:181
+#: src/views/certificate/CertificateEditor.vue:179
 msgid "The path exists, but the file is not a certificate"
 msgid "The path exists, but the file is not a certificate"
 msgstr "Đường dẫn tồn tại, nhưng tệp không phải là chứng chỉ"
 msgstr "Đường dẫn tồn tại, nhưng tệp không phải là chứng chỉ"
 
 
-#: src/views/certificate/CertificateEditor.vue:196
+#: src/views/certificate/CertificateEditor.vue:194
 msgid "The path exists, but the file is not a private key"
 msgid "The path exists, but the file is not a private key"
 msgstr "Đường dẫn tồn tại, nhưng tệp không phải là khóa riêng tư"
 msgstr "Đường dẫn tồn tại, nhưng tệp không phải là khóa riêng tư"
 
 
@@ -4943,17 +4984,17 @@ msgstr ""
 "trường hợp bạn mất mật khẩu và các yếu tố xác thực thứ hai. Nếu bạn không "
 "trường hợp bạn mất mật khẩu và các yếu tố xác thực thứ hai. Nếu bạn không "
 "thể tìm thấy những mã này, bạn sẽ mất quyền truy cập vào tài khoản."
 "thể tìm thấy những mã này, bạn sẽ mất quyền truy cập vào tài khoản."
 
 
-#: src/views/certificate/CertificateEditor.vue:102
+#: src/views/certificate/CertificateEditor.vue:100
 msgid "This Auto Cert item is invalid, please remove it."
 msgid "This Auto Cert item is invalid, please remove it."
 msgstr "Mục Chứng chỉ tự động này không hợp lệ, vui lòng xóa nó"
 msgstr "Mục Chứng chỉ tự động này không hợp lệ, vui lòng xóa nó"
 
 
-#: src/views/certificate/CertificateEditor.vue:92
+#: src/views/certificate/CertificateEditor.vue:90
 msgid "This certificate is managed by Nginx UI"
 msgid "This certificate is managed by Nginx UI"
 msgstr "Chứng chỉ này được quản lý bởi Nginx UI"
 msgstr "Chứng chỉ này được quản lý bởi Nginx UI"
 
 
-#: src/views/certificate/CertificateEditor.vue:165
-#: src/views/certificate/CertificateEditor.vue:179
-#: src/views/certificate/CertificateEditor.vue:194
+#: src/views/certificate/CertificateEditor.vue:163
+#: src/views/certificate/CertificateEditor.vue:177
+#: src/views/certificate/CertificateEditor.vue:192
 msgid "This field is required"
 msgid "This field is required"
 msgstr "Trường này là bắt buộc"
 msgstr "Trường này là bắt buộc"
 
 
@@ -5430,6 +5471,10 @@ msgstr "Khi bạn tạo mã khôi phục mới, bạn phải tải xuống hoặ
 msgid "Whether to use a temporary path when writing temporary files"
 msgid "Whether to use a temporary path when writing temporary files"
 msgstr "Có sử dụng đường dẫn tạm thời khi ghi các tập tin tạm thời hay không"
 msgstr "Có sử dụng đường dẫn tạm thời khi ghi các tập tin tạm thời hay không"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:107
+msgid "Wildcard Certificate"
+msgstr "Chứng Chỉ Wildcard"
+
 #: src/views/dashboard/components/ParamsOpt/PerformanceConfig.vue:48
 #: src/views/dashboard/components/ParamsOpt/PerformanceConfig.vue:48
 msgid "Worker Connections"
 msgid "Worker Connections"
 msgstr "Kết nối worker"
 msgstr "Kết nối worker"
@@ -5734,9 +5779,6 @@ msgstr "Khóa truy cập của bạn"
 #~ msgid "Incorrect username or password"
 #~ msgid "Incorrect username or password"
 #~ msgstr "Tên người dùng hoặc mật khẩu không chính xác"
 #~ msgstr "Tên người dùng hoặc mật khẩu không chính xác"
 
 
-#~ msgid "Server error"
-#~ msgstr "Lỗi máy chủ"
-
 #, fuzzy
 #, fuzzy
 #~ msgid ""
 #~ msgid ""
 #~ "Rename %{orig_path} to %{new_path} on %{env_name} failed, please upgrade "
 #~ "Rename %{orig_path} to %{new_path} on %{env_name} failed, please upgrade "

+ 82 - 45
app/src/language/zh_CN/app.po

@@ -180,6 +180,10 @@ msgstr "添加配置"
 msgid "Add Directive Below"
 msgid "Add Directive Below"
 msgstr "在下面添加指令"
 msgstr "在下面添加指令"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:151
+msgid "Add Domain"
+msgstr "添加域名"
+
 #: src/components/NgxConfigEditor/LocationEditor.vue:131
 #: src/components/NgxConfigEditor/LocationEditor.vue:131
 #: src/components/NgxConfigEditor/LocationEditor.vue:158
 #: src/components/NgxConfigEditor/LocationEditor.vue:158
 msgid "Add Location"
 msgid "Add Location"
@@ -227,6 +231,12 @@ msgstr "全部"
 msgid "All Recovery Codes Have Been Used"
 msgid "All Recovery Codes Have Been Used"
 msgstr "所有恢复代码已用完"
 msgstr "所有恢复代码已用完"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:156
+msgid ""
+"All selected subdomains must belong to the same DNS Provider, otherwise the "
+"certificate application will fail."
+msgstr "所有选定的子域名必须属于同一 DNS 提供商,否则证书申请将失败。"
+
 #: src/views/preference/tabs/OpenAISettings.vue:32
 #: src/views/preference/tabs/OpenAISettings.vue:32
 msgid "API Base Url"
 msgid "API Base Url"
 msgstr "API 地址"
 msgstr "API 地址"
@@ -253,7 +263,7 @@ msgstr "应用"
 
 
 #: src/views/system/Upgrade.vue:195
 #: src/views/system/Upgrade.vue:195
 msgid "Arch"
 msgid "Arch"
-msgstr "\"架构\""
+msgstr "架构"
 
 
 #: src/views/preference/tabs/AuthSettings.vue:130
 #: src/views/preference/tabs/AuthSettings.vue:130
 msgid "Are you sure to delete this banned IP immediately?"
 msgid "Are you sure to delete this banned IP immediately?"
@@ -388,7 +398,7 @@ msgstr "成功关闭 %{name} 自动续签"
 msgid "Auto-renewal enabled for %{name}"
 msgid "Auto-renewal enabled for %{name}"
 msgstr "成功启用 %{name} 自动续签"
 msgstr "成功启用 %{name} 自动续签"
 
 
-#: src/views/certificate/components/RenewCert.vue:49
+#: src/views/certificate/components/RenewCert.vue:51
 #: src/views/site/site_edit/components/Cert/IssueCert.vue:84
 #: src/views/site/site_edit/components/Cert/IssueCert.vue:84
 msgid "AutoCert is running, please wait..."
 msgid "AutoCert is running, please wait..."
 msgstr "AutoCert 正在运行,请稍候..."
 msgstr "AutoCert 正在运行,请稍候..."
@@ -401,7 +411,7 @@ msgstr "AutoCert 正在运行..."
 msgid "Automatic Restart"
 msgid "Automatic Restart"
 msgstr "\"自动重启\""
 msgstr "\"自动重启\""
 
 
-#: src/views/certificate/CertificateEditor.vue:259
+#: src/views/certificate/CertificateEditor.vue:257
 #: src/views/config/components/ConfigLeftPanel.vue:273
 #: src/views/config/components/ConfigLeftPanel.vue:273
 #: src/views/config/ConfigList.vue:112 src/views/config/ConfigList.vue:195
 #: src/views/config/ConfigList.vue:112 src/views/config/ConfigList.vue:195
 #: src/views/nginx_log/NginxLog.vue:174
 #: src/views/nginx_log/NginxLog.vue:174
@@ -692,12 +702,16 @@ msgstr "证书更新成功"
 msgid "Certificate revoked successfully"
 msgid "Certificate revoked successfully"
 msgstr "证书撤销成功"
 msgstr "证书撤销成功"
 
 
-#: src/views/certificate/CertificateEditor.vue:128
+#: src/views/certificate/CertificateEditor.vue:126
 #: src/views/site/site_edit/components/Cert/Cert.vue:58
 #: src/views/site/site_edit/components/Cert/Cert.vue:58
 msgid "Certificate Status"
 msgid "Certificate Status"
 msgid_plural "Certificates Status"
 msgid_plural "Certificates Status"
 msgstr[0] "证书状态"
 msgstr[0] "证书状态"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:104
+msgid "Certificate Type"
+msgstr "证书类型"
+
 #: src/routes/modules/certificates.ts:11
 #: src/routes/modules/certificates.ts:11
 #: src/views/certificate/CertificateList/Certificate.vue:19
 #: src/views/certificate/CertificateList/Certificate.vue:19
 msgid "Certificates"
 msgid "Certificates"
@@ -1161,6 +1175,14 @@ msgstr "自定义 cron 表达式"
 msgid "Custom Directory"
 msgid "Custom Directory"
 msgstr "自定义目录"
 msgstr "自定义目录"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:126
+msgid "Custom Domains"
+msgstr "自定义域名"
+
+#: src/views/certificate/components/DNSIssueCertificate.vue:110
+msgid "Custom Domains Certificate"
+msgstr "自定义域名证书"
+
 #: src/views/preference/tabs/NodeSettings.vue:19
 #: src/views/preference/tabs/NodeSettings.vue:19
 msgid ""
 msgid ""
 "Customize the name of local node to be displayed in the environment "
 "Customize the name of local node to be displayed in the environment "
@@ -1468,11 +1490,11 @@ msgid "Document"
 msgid_plural "Documents"
 msgid_plural "Documents"
 msgstr[0] "文档"
 msgstr[0] "文档"
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:66
+#: src/views/certificate/components/DNSIssueCertificate.vue:116
 msgid "Domain"
 msgid "Domain"
 msgstr "域名"
 msgstr "域名"
 
 
-#: src/views/certificate/CertificateEditor.vue:112
+#: src/views/certificate/CertificateEditor.vue:110
 msgid "Domains list is empty, try to reopen Auto Cert for %{config}"
 msgid "Domains list is empty, try to reopen Auto Cert for %{config}"
 msgstr "域名列表为空,请尝试为 %{config} 重新打开证书自动续期"
 msgstr "域名列表为空,请尝试为 %{config} 重新打开证书自动续期"
 
 
@@ -1672,6 +1694,14 @@ msgstr "用 Let's Encrypt 对网站进行加密"
 msgid "End"
 msgid "End"
 msgstr "结束"
 msgstr "结束"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:135
+msgid "Enter domain name"
+msgstr "输入域名"
+
+#: src/views/certificate/components/DNSIssueCertificate.vue:120
+msgid "Enter your domain"
+msgstr "输入您的域名"
+
 #: src/language/constants.ts:22
 #: src/language/constants.ts:22
 msgid "Environment variables cleaned"
 msgid "Environment variables cleaned"
 msgstr "环境变量已清理"
 msgstr "环境变量已清理"
@@ -1746,7 +1776,7 @@ msgstr "外部 Docker 容器"
 msgid "External Notify"
 msgid "External Notify"
 msgstr "外部通知"
 msgstr "外部通知"
 
 
-#: src/views/site/site_edit/components/Cert/ObtainCertLive.vue:80
+#: src/views/site/site_edit/components/Cert/ObtainCertLive.vue:81
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
 msgstr "获取证书失败"
 msgstr "获取证书失败"
 
 
@@ -2267,7 +2297,7 @@ msgid "Import"
 msgstr "导入"
 msgstr "导入"
 
 
 #: src/routes/modules/certificates.ts:46
 #: src/routes/modules/certificates.ts:46
-#: src/views/certificate/CertificateEditor.vue:85
+#: src/views/certificate/CertificateEditor.vue:83
 msgid "Import Certificate"
 msgid "Import Certificate"
 msgstr "导入证书"
 msgstr "导入证书"
 
 
@@ -2408,12 +2438,12 @@ msgid "IP"
 msgstr "IP"
 msgstr "IP"
 
 
 #: src/views/certificate/CertificateList/Certificate.vue:37
 #: src/views/certificate/CertificateList/Certificate.vue:37
-msgid "Issue wildcard certificate"
-msgstr "签发通配符证书"
+msgid "Issue certificate"
+msgstr "签发证书"
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:57
-msgid "Issue Wildcard Certificate"
-msgstr "颁发通配符证书"
+#: src/views/certificate/components/DNSIssueCertificate.vue:95
+msgid "Issue Certificate"
+msgstr "签发证书"
 
 
 #: src/language/constants.ts:20
 #: src/language/constants.ts:20
 msgid "Issued certificate successfully"
 msgid "Issued certificate successfully"
@@ -2494,8 +2524,8 @@ msgstr "如果不想修改,请留空"
 msgid "Leave blank if you don't need this."
 msgid "Leave blank if you don't need this."
 msgstr "如果不需要,请留空。"
 msgstr "如果不需要,请留空。"
 
 
-#: src/views/certificate/CertificateEditor.vue:223
-#: src/views/certificate/CertificateEditor.vue:237
+#: src/views/certificate/CertificateEditor.vue:221
+#: src/views/certificate/CertificateEditor.vue:235
 msgid "Leave blank will not change anything"
 msgid "Leave blank will not change anything"
 msgstr "留空不做任何更改"
 msgstr "留空不做任何更改"
 
 
@@ -2582,7 +2612,7 @@ msgstr "Location"
 msgid "Locations"
 msgid "Locations"
 msgstr "Locations"
 msgstr "Locations"
 
 
-#: src/views/certificate/CertificateEditor.vue:247
+#: src/views/certificate/CertificateEditor.vue:245
 msgid "Log"
 msgid "Log"
 msgstr "日志"
 msgstr "日志"
 
 
@@ -2789,7 +2819,7 @@ msgid "Modify"
 msgstr "修改"
 msgstr "修改"
 
 
 #: src/routes/modules/certificates.ts:36
 #: src/routes/modules/certificates.ts:36
-#: src/views/certificate/CertificateEditor.vue:85
+#: src/views/certificate/CertificateEditor.vue:83
 msgid "Modify Certificate"
 msgid "Modify Certificate"
 msgstr "修改证书"
 msgstr "修改证书"
 
 
@@ -2824,7 +2854,7 @@ msgstr "多行指令"
 #: src/components/NgxConfigEditor/NgxUpstream.vue:199
 #: src/components/NgxConfigEditor/NgxUpstream.vue:199
 #: src/views/backup/AutoBackup/AutoBackup.vue:11
 #: src/views/backup/AutoBackup/AutoBackup.vue:11
 #: src/views/certificate/ACMEUser.vue:11
 #: src/views/certificate/ACMEUser.vue:11
-#: src/views/certificate/CertificateEditor.vue:162
+#: src/views/certificate/CertificateEditor.vue:160
 #: src/views/certificate/CertificateList/certColumns.tsx:9
 #: src/views/certificate/CertificateList/certColumns.tsx:9
 #: src/views/certificate/DNSCredential.vue:9
 #: src/views/certificate/DNSCredential.vue:9
 #: src/views/config/components/ConfigRightPanel/Basic.vue:34
 #: src/views/config/components/ConfigRightPanel/Basic.vue:34
@@ -2884,7 +2914,7 @@ msgstr "新路径"
 msgid "New version released"
 msgid "New version released"
 msgstr "新版本发布"
 msgstr "新版本发布"
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:89
+#: src/views/certificate/components/DNSIssueCertificate.vue:181
 #: src/views/install/components/InstallView.vue:96
 #: src/views/install/components/InstallView.vue:96
 #: src/views/site/site_add/SiteAdd.vue:132
 #: src/views/site/site_add/SiteAdd.vue:132
 #: src/views/site/site_edit/components/Cert/ObtainCert.vue:214
 #: src/views/site/site_edit/components/Cert/ObtainCert.vue:214
@@ -3457,6 +3487,10 @@ msgstr "请为您要创建的 Passkey 输入一个名称,然后单击下面的
 msgid "Please enter a valid port range"
 msgid "Please enter a valid port range"
 msgstr "请输入有效的端口范围"
 msgstr "请输入有效的端口范围"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:74
+msgid "Please enter at least one domain"
+msgstr "请输入至少一个域名"
+
 #: src/components/TwoFA/Authorization.vue:85
 #: src/components/TwoFA/Authorization.vue:85
 msgid "Please enter the OTP code:"
 msgid "Please enter the OTP code:"
 msgstr "请输入 OTP:"
 msgstr "请输入 OTP:"
@@ -3782,6 +3816,7 @@ msgstr "重载中"
 msgid "Reloading nginx"
 msgid "Reloading nginx"
 msgstr "正在重载 Nginx"
 msgstr "正在重载 Nginx"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:144
 #: src/views/preference/tabs/AuthSettings.vue:137
 #: src/views/preference/tabs/AuthSettings.vue:137
 msgid "Remove"
 msgid "Remove"
 msgstr "删除"
 msgstr "删除"
@@ -3864,8 +3899,8 @@ msgstr "重命名成功"
 msgid "Renamed successfully"
 msgid "Renamed successfully"
 msgstr "重命名成功"
 msgstr "重命名成功"
 
 
-#: src/views/certificate/components/RenewCert.vue:46
-#: src/views/certificate/components/RenewCert.vue:53
+#: src/views/certificate/components/RenewCert.vue:48
+#: src/views/certificate/components/RenewCert.vue:55
 msgid "Renew Certificate"
 msgid "Renew Certificate"
 msgstr "更新证书"
 msgstr "更新证书"
 
 
@@ -3877,8 +3912,8 @@ msgstr "证书续期错误"
 msgid "Renew Certificate Success"
 msgid "Renew Certificate Success"
 msgstr "证书续期成功"
 msgstr "证书续期成功"
 
 
-#: src/views/certificate/components/RenewCert.vue:28
-#: src/views/certificate/components/WildcardCertificate.vue:46
+#: src/views/certificate/components/DNSIssueCertificate.vue:84
+#: src/views/certificate/components/RenewCert.vue:30
 msgid "Renew successfully"
 msgid "Renew successfully"
 msgstr "更新成功"
 msgstr "更新成功"
 
 
@@ -4132,7 +4167,7 @@ msgstr "星期六"
 
 
 #: src/components/ChatGPT/ChatMessage.vue:215
 #: src/components/ChatGPT/ChatMessage.vue:215
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:129
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:129
-#: src/language/curd.ts:18 src/views/certificate/CertificateEditor.vue:266
+#: src/language/curd.ts:18 src/views/certificate/CertificateEditor.vue:264
 #: src/views/config/components/ConfigLeftPanel.vue:282
 #: src/views/config/components/ConfigLeftPanel.vue:282
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/preference/components/AuthSettings/Passkey.vue:130
 #: src/views/preference/components/AuthSettings/Passkey.vue:130
@@ -4187,7 +4222,7 @@ msgstr "部署 %{name} 到 %{node} 失败"
 msgid "Save stream %{name} to %{node} successfully"
 msgid "Save stream %{name} to %{node} successfully"
 msgstr "成功将站点 %{name} 保存到 %{node} 中"
 msgstr "成功将站点 %{name} 保存到 %{node} 中"
 
 
-#: src/language/curd.ts:35 src/views/certificate/CertificateEditor.vue:49
+#: src/language/curd.ts:35 src/views/certificate/store.ts:13
 #: src/views/preference/store/index.ts:118
 #: src/views/preference/store/index.ts:118
 msgid "Save successfully"
 msgid "Save successfully"
 msgstr "保存成功"
 msgstr "保存成功"
@@ -4295,6 +4330,10 @@ msgstr "上传"
 msgid "Server"
 msgid "Server"
 msgstr "服务器"
 msgstr "服务器"
 
 
+#: src/views/certificate/CertificateEditor.vue:55
+msgid "Server error"
+msgstr "服务器错误"
+
 #: src/views/dashboard/ServerAnalytic.vue:175
 #: src/views/dashboard/ServerAnalytic.vue:175
 msgid "Server Info"
 msgid "Server Info"
 msgstr "服务器信息"
 msgstr "服务器信息"
@@ -4429,7 +4468,7 @@ msgstr "缓存加载器迭代之间的休眠时间"
 msgid "Sleep time between cache manager iterations"
 msgid "Sleep time between cache manager iterations"
 msgstr "缓存管理器迭代之间的休眠时间"
 msgstr "缓存管理器迭代之间的休眠时间"
 
 
-#: src/views/certificate/CertificateEditor.vue:213
+#: src/views/certificate/CertificateEditor.vue:211
 msgid "SSL Certificate Content"
 msgid "SSL Certificate Content"
 msgstr "SSL 证书内容"
 msgstr "SSL 证书内容"
 
 
@@ -4441,15 +4480,15 @@ msgstr "SSL 证书文件必须位于 Nginx 配置目录下:{0}"
 msgid "SSL certificate file not found"
 msgid "SSL certificate file not found"
 msgstr "未找到 SSL 证书文件"
 msgstr "未找到 SSL 证书文件"
 
 
-#: src/views/certificate/CertificateEditor.vue:227
+#: src/views/certificate/CertificateEditor.vue:225
 msgid "SSL Certificate Key Content"
 msgid "SSL Certificate Key Content"
 msgstr "SSL 证书密钥内容"
 msgstr "SSL 证书密钥内容"
 
 
-#: src/views/certificate/CertificateEditor.vue:192
+#: src/views/certificate/CertificateEditor.vue:190
 msgid "SSL Certificate Key Path"
 msgid "SSL Certificate Key Path"
 msgstr "SSL证书密钥路径"
 msgstr "SSL证书密钥路径"
 
 
-#: src/views/certificate/CertificateEditor.vue:177
+#: src/views/certificate/CertificateEditor.vue:175
 #: src/views/preference/tabs/ServerSettings.vue:37
 #: src/views/preference/tabs/ServerSettings.vue:37
 msgid "SSL Certificate Path"
 msgid "SSL Certificate Path"
 msgstr "SSL证书路径"
 msgstr "SSL证书路径"
@@ -4680,7 +4719,7 @@ msgstr "同步节点"
 msgid "Sync strategy"
 msgid "Sync strategy"
 msgstr "同步策略"
 msgstr "同步策略"
 
 
-#: src/views/certificate/CertificateEditor.vue:206
+#: src/views/certificate/CertificateEditor.vue:204
 msgid "Sync to"
 msgid "Sync to"
 msgstr "同步到"
 msgstr "同步到"
 
 
@@ -4751,11 +4790,11 @@ msgid ""
 "dashes, colons, and dots."
 "dashes, colons, and dots."
 msgstr "ICP 备案号只能包含字母、单码、数字、连字符、破折号、冒号和点。"
 msgstr "ICP 备案号只能包含字母、单码、数字、连字符、破折号、冒号和点。"
 
 
-#: src/views/certificate/CertificateEditor.vue:216
+#: src/views/certificate/CertificateEditor.vue:214
 msgid "The input is not a SSL Certificate"
 msgid "The input is not a SSL Certificate"
 msgstr "输入的内容不是 SSL 证书"
 msgstr "输入的内容不是 SSL 证书"
 
 
-#: src/views/certificate/CertificateEditor.vue:230
+#: src/views/certificate/CertificateEditor.vue:228
 msgid "The input is not a SSL Certificate Key"
 msgid "The input is not a SSL Certificate Key"
 msgstr "输入的内容不是 SSL 证书密钥"
 msgstr "输入的内容不是 SSL 证书密钥"
 
 
@@ -4786,11 +4825,11 @@ msgstr "节点名称只能包含字母、统一码、数字、连字符、破折
 msgid "The parameter of server_name is required"
 msgid "The parameter of server_name is required"
 msgstr "必须为 server_name 指令指明参数"
 msgstr "必须为 server_name 指令指明参数"
 
 
-#: src/views/certificate/CertificateEditor.vue:181
+#: src/views/certificate/CertificateEditor.vue:179
 msgid "The path exists, but the file is not a certificate"
 msgid "The path exists, but the file is not a certificate"
 msgstr "路径存在,但文件不是证书"
 msgstr "路径存在,但文件不是证书"
 
 
-#: src/views/certificate/CertificateEditor.vue:196
+#: src/views/certificate/CertificateEditor.vue:194
 msgid "The path exists, but the file is not a private key"
 msgid "The path exists, but the file is not a private key"
 msgstr "路径存在,但文件不是私钥"
 msgstr "路径存在,但文件不是私钥"
 
 
@@ -4842,17 +4881,17 @@ msgid ""
 "lose access to your account."
 "lose access to your account."
 msgstr "这些代码是在您丢失密码和双重身份验证方式时,访问账户的最后手段。如果找不到这些代码,您将无法再访问您的账户。"
 msgstr "这些代码是在您丢失密码和双重身份验证方式时,访问账户的最后手段。如果找不到这些代码,您将无法再访问您的账户。"
 
 
-#: src/views/certificate/CertificateEditor.vue:102
+#: src/views/certificate/CertificateEditor.vue:100
 msgid "This Auto Cert item is invalid, please remove it."
 msgid "This Auto Cert item is invalid, please remove it."
 msgstr "这个证书自动续期项目是无效的,请删除。"
 msgstr "这个证书自动续期项目是无效的,请删除。"
 
 
-#: src/views/certificate/CertificateEditor.vue:92
+#: src/views/certificate/CertificateEditor.vue:90
 msgid "This certificate is managed by Nginx UI"
 msgid "This certificate is managed by Nginx UI"
 msgstr "该证书由 Nginx UI 托管"
 msgstr "该证书由 Nginx UI 托管"
 
 
-#: src/views/certificate/CertificateEditor.vue:165
-#: src/views/certificate/CertificateEditor.vue:179
-#: src/views/certificate/CertificateEditor.vue:194
+#: src/views/certificate/CertificateEditor.vue:163
+#: src/views/certificate/CertificateEditor.vue:177
+#: src/views/certificate/CertificateEditor.vue:192
 msgid "This field is required"
 msgid "This field is required"
 msgstr "此字段必填"
 msgstr "此字段必填"
 
 
@@ -5293,6 +5332,10 @@ msgstr "当您生成新的恢复代码时,必须下载或打印新的代码。
 msgid "Whether to use a temporary path when writing temporary files"
 msgid "Whether to use a temporary path when writing temporary files"
 msgstr "写入临时文件时是否使用临时路径"
 msgstr "写入临时文件时是否使用临时路径"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:107
+msgid "Wildcard Certificate"
+msgstr "通配符证书"
+
 #: src/views/dashboard/components/ParamsOpt/PerformanceConfig.vue:48
 #: src/views/dashboard/components/ParamsOpt/PerformanceConfig.vue:48
 msgid "Worker Connections"
 msgid "Worker Connections"
 msgstr "工作进程连接数"
 msgstr "工作进程连接数"
@@ -5552,9 +5595,6 @@ msgstr "你的 Passkeys"
 #~ msgid "Do you want to disable this site?"
 #~ msgid "Do you want to disable this site?"
 #~ msgstr "你想停用这个网站吗?"
 #~ msgstr "你想停用这个网站吗?"
 
 
-#~ msgid "Enter Maintenance"
-#~ msgstr "进入维护"
-
 #~ msgid "URLs"
 #~ msgid "URLs"
 #~ msgstr "链接"
 #~ msgstr "链接"
 
 
@@ -5644,9 +5684,6 @@ msgstr "你的 Passkeys"
 #~ msgid "File"
 #~ msgid "File"
 #~ msgstr "文件"
 #~ msgstr "文件"
 
 
-#~ msgid "Server error"
-#~ msgstr "服务器错误"
-
 #~ msgid "Incorrect username or password"
 #~ msgid "Incorrect username or password"
 #~ msgstr "用户名或密码错误"
 #~ msgstr "用户名或密码错误"
 
 

+ 82 - 42
app/src/language/zh_TW/app.po

@@ -184,6 +184,10 @@ msgstr "新增設定"
 msgid "Add Directive Below"
 msgid "Add Directive Below"
 msgstr "在下方新增指令"
 msgstr "在下方新增指令"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:151
+msgid "Add Domain"
+msgstr "添加域名"
+
 #: src/components/NgxConfigEditor/LocationEditor.vue:131
 #: src/components/NgxConfigEditor/LocationEditor.vue:131
 #: src/components/NgxConfigEditor/LocationEditor.vue:158
 #: src/components/NgxConfigEditor/LocationEditor.vue:158
 msgid "Add Location"
 msgid "Add Location"
@@ -231,6 +235,12 @@ msgstr "全部"
 msgid "All Recovery Codes Have Been Used"
 msgid "All Recovery Codes Have Been Used"
 msgstr "所有恢復代碼已用完"
 msgstr "所有恢復代碼已用完"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:156
+msgid ""
+"All selected subdomains must belong to the same DNS Provider, otherwise the "
+"certificate application will fail."
+msgstr "所有選定的子網域名稱必須屬於同一 DNS 提供商,否則證書申請將失敗。"
+
 #: src/views/preference/tabs/OpenAISettings.vue:32
 #: src/views/preference/tabs/OpenAISettings.vue:32
 msgid "API Base Url"
 msgid "API Base Url"
 msgstr "API 基礎網址"
 msgstr "API 基礎網址"
@@ -257,7 +267,7 @@ msgstr "應用"
 
 
 #: src/views/system/Upgrade.vue:195
 #: src/views/system/Upgrade.vue:195
 msgid "Arch"
 msgid "Arch"
-msgstr "\"架構\""
+msgstr "架構"
 
 
 #: src/views/preference/tabs/AuthSettings.vue:130
 #: src/views/preference/tabs/AuthSettings.vue:130
 msgid "Are you sure to delete this banned IP immediately?"
 msgid "Are you sure to delete this banned IP immediately?"
@@ -392,7 +402,7 @@ msgstr "已關閉 %{name} 的自動續簽"
 msgid "Auto-renewal enabled for %{name}"
 msgid "Auto-renewal enabled for %{name}"
 msgstr "已啟用 %{name} 的自動續簽"
 msgstr "已啟用 %{name} 的自動續簽"
 
 
-#: src/views/certificate/components/RenewCert.vue:49
+#: src/views/certificate/components/RenewCert.vue:51
 #: src/views/site/site_edit/components/Cert/IssueCert.vue:84
 #: src/views/site/site_edit/components/Cert/IssueCert.vue:84
 msgid "AutoCert is running, please wait..."
 msgid "AutoCert is running, please wait..."
 msgstr "AutoCert 正在執行中,請稍候..."
 msgstr "AutoCert 正在執行中,請稍候..."
@@ -405,7 +415,7 @@ msgstr "\"AutoCert 正在運行...\""
 msgid "Automatic Restart"
 msgid "Automatic Restart"
 msgstr "\"自動重啟\""
 msgstr "\"自動重啟\""
 
 
-#: src/views/certificate/CertificateEditor.vue:259
+#: src/views/certificate/CertificateEditor.vue:257
 #: src/views/config/components/ConfigLeftPanel.vue:273
 #: src/views/config/components/ConfigLeftPanel.vue:273
 #: src/views/config/ConfigList.vue:112 src/views/config/ConfigList.vue:195
 #: src/views/config/ConfigList.vue:112 src/views/config/ConfigList.vue:195
 #: src/views/nginx_log/NginxLog.vue:174
 #: src/views/nginx_log/NginxLog.vue:174
@@ -696,12 +706,16 @@ msgstr "憑證更新成功"
 msgid "Certificate revoked successfully"
 msgid "Certificate revoked successfully"
 msgstr "證書撤銷成功"
 msgstr "證書撤銷成功"
 
 
-#: src/views/certificate/CertificateEditor.vue:128
+#: src/views/certificate/CertificateEditor.vue:126
 #: src/views/site/site_edit/components/Cert/Cert.vue:58
 #: src/views/site/site_edit/components/Cert/Cert.vue:58
 msgid "Certificate Status"
 msgid "Certificate Status"
 msgid_plural "Certificates Status"
 msgid_plural "Certificates Status"
 msgstr[0] "憑證狀態"
 msgstr[0] "憑證狀態"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:104
+msgid "Certificate Type"
+msgstr "證書類型"
+
 #: src/routes/modules/certificates.ts:11
 #: src/routes/modules/certificates.ts:11
 #: src/views/certificate/CertificateList/Certificate.vue:19
 #: src/views/certificate/CertificateList/Certificate.vue:19
 msgid "Certificates"
 msgid "Certificates"
@@ -1165,6 +1179,14 @@ msgstr "自訂 cron 表達式"
 msgid "Custom Directory"
 msgid "Custom Directory"
 msgstr "自訂目錄"
 msgstr "自訂目錄"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:126
+msgid "Custom Domains"
+msgstr "自訂網域"
+
+#: src/views/certificate/components/DNSIssueCertificate.vue:110
+msgid "Custom Domains Certificate"
+msgstr "自訂網域證書"
+
 #: src/views/preference/tabs/NodeSettings.vue:19
 #: src/views/preference/tabs/NodeSettings.vue:19
 msgid ""
 msgid ""
 "Customize the name of local node to be displayed in the environment "
 "Customize the name of local node to be displayed in the environment "
@@ -1472,11 +1494,11 @@ msgid "Document"
 msgid_plural "Documents"
 msgid_plural "Documents"
 msgstr[0] "檔案"
 msgstr[0] "檔案"
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:66
+#: src/views/certificate/components/DNSIssueCertificate.vue:116
 msgid "Domain"
 msgid "Domain"
 msgstr "網域"
 msgstr "網域"
 
 
-#: src/views/certificate/CertificateEditor.vue:112
+#: src/views/certificate/CertificateEditor.vue:110
 msgid "Domains list is empty, try to reopen Auto Cert for %{config}"
 msgid "Domains list is empty, try to reopen Auto Cert for %{config}"
 msgstr "網域列表為空,請嘗試重新開啟 %{config} 的自動憑證"
 msgstr "網域列表為空,請嘗試重新開啟 %{config} 的自動憑證"
 
 
@@ -1676,6 +1698,14 @@ msgstr "用 Let's Encrypt 對網站進行加密"
 msgid "End"
 msgid "End"
 msgstr "結束"
 msgstr "結束"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:135
+msgid "Enter domain name"
+msgstr "輸入網域名稱"
+
+#: src/views/certificate/components/DNSIssueCertificate.vue:120
+msgid "Enter your domain"
+msgstr "輸入您的域名"
+
 #: src/language/constants.ts:22
 #: src/language/constants.ts:22
 msgid "Environment variables cleaned"
 msgid "Environment variables cleaned"
 msgstr "環境變數已清理"
 msgstr "環境變數已清理"
@@ -1750,7 +1780,7 @@ msgstr "外部 Docker 容器"
 msgid "External Notify"
 msgid "External Notify"
 msgstr "外部通知"
 msgstr "外部通知"
 
 
-#: src/views/site/site_edit/components/Cert/ObtainCertLive.vue:80
+#: src/views/site/site_edit/components/Cert/ObtainCertLive.vue:81
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
 msgstr "取得憑證失敗"
 msgstr "取得憑證失敗"
 
 
@@ -2271,7 +2301,7 @@ msgid "Import"
 msgstr "匯入"
 msgstr "匯入"
 
 
 #: src/routes/modules/certificates.ts:46
 #: src/routes/modules/certificates.ts:46
-#: src/views/certificate/CertificateEditor.vue:85
+#: src/views/certificate/CertificateEditor.vue:83
 msgid "Import Certificate"
 msgid "Import Certificate"
 msgstr "匯入憑證"
 msgstr "匯入憑證"
 
 
@@ -2412,12 +2442,12 @@ msgid "IP"
 msgstr "IP"
 msgstr "IP"
 
 
 #: src/views/certificate/CertificateList/Certificate.vue:37
 #: src/views/certificate/CertificateList/Certificate.vue:37
-msgid "Issue wildcard certificate"
-msgstr "發行萬用字元憑證"
+msgid "Issue certificate"
+msgstr "發證"
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:57
-msgid "Issue Wildcard Certificate"
-msgstr "簽發萬用字元憑證"
+#: src/views/certificate/components/DNSIssueCertificate.vue:95
+msgid "Issue Certificate"
+msgstr "簽發證"
 
 
 #: src/language/constants.ts:20
 #: src/language/constants.ts:20
 msgid "Issued certificate successfully"
 msgid "Issued certificate successfully"
@@ -2498,8 +2528,8 @@ msgstr "留空表示不修改"
 msgid "Leave blank if you don't need this."
 msgid "Leave blank if you don't need this."
 msgstr "留空表示不需要此項目。"
 msgstr "留空表示不需要此項目。"
 
 
-#: src/views/certificate/CertificateEditor.vue:223
-#: src/views/certificate/CertificateEditor.vue:237
+#: src/views/certificate/CertificateEditor.vue:221
+#: src/views/certificate/CertificateEditor.vue:235
 msgid "Leave blank will not change anything"
 msgid "Leave blank will not change anything"
 msgstr "留空將不會改變任何內容"
 msgstr "留空將不會改變任何內容"
 
 
@@ -2586,7 +2616,7 @@ msgstr "Location"
 msgid "Locations"
 msgid "Locations"
 msgstr "Locations"
 msgstr "Locations"
 
 
-#: src/views/certificate/CertificateEditor.vue:247
+#: src/views/certificate/CertificateEditor.vue:245
 msgid "Log"
 msgid "Log"
 msgstr "日誌"
 msgstr "日誌"
 
 
@@ -2793,7 +2823,7 @@ msgid "Modify"
 msgstr "修改"
 msgstr "修改"
 
 
 #: src/routes/modules/certificates.ts:36
 #: src/routes/modules/certificates.ts:36
-#: src/views/certificate/CertificateEditor.vue:85
+#: src/views/certificate/CertificateEditor.vue:83
 msgid "Modify Certificate"
 msgid "Modify Certificate"
 msgstr "修改憑證"
 msgstr "修改憑證"
 
 
@@ -2828,7 +2858,7 @@ msgstr "多行指令"
 #: src/components/NgxConfigEditor/NgxUpstream.vue:199
 #: src/components/NgxConfigEditor/NgxUpstream.vue:199
 #: src/views/backup/AutoBackup/AutoBackup.vue:11
 #: src/views/backup/AutoBackup/AutoBackup.vue:11
 #: src/views/certificate/ACMEUser.vue:11
 #: src/views/certificate/ACMEUser.vue:11
-#: src/views/certificate/CertificateEditor.vue:162
+#: src/views/certificate/CertificateEditor.vue:160
 #: src/views/certificate/CertificateList/certColumns.tsx:9
 #: src/views/certificate/CertificateList/certColumns.tsx:9
 #: src/views/certificate/DNSCredential.vue:9
 #: src/views/certificate/DNSCredential.vue:9
 #: src/views/config/components/ConfigRightPanel/Basic.vue:34
 #: src/views/config/components/ConfigRightPanel/Basic.vue:34
@@ -2888,7 +2918,7 @@ msgstr "新路徑"
 msgid "New version released"
 msgid "New version released"
 msgstr "新版本發布"
 msgstr "新版本發布"
 
 
-#: src/views/certificate/components/WildcardCertificate.vue:89
+#: src/views/certificate/components/DNSIssueCertificate.vue:181
 #: src/views/install/components/InstallView.vue:96
 #: src/views/install/components/InstallView.vue:96
 #: src/views/site/site_add/SiteAdd.vue:132
 #: src/views/site/site_add/SiteAdd.vue:132
 #: src/views/site/site_edit/components/Cert/ObtainCert.vue:214
 #: src/views/site/site_edit/components/Cert/ObtainCert.vue:214
@@ -3463,6 +3493,10 @@ msgstr "請輸入您希望建立的通行金鑰名稱,並點選下面的確定
 msgid "Please enter a valid port range"
 msgid "Please enter a valid port range"
 msgstr "請輸入有效的端口範圍"
 msgstr "請輸入有效的端口範圍"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:74
+msgid "Please enter at least one domain"
+msgstr "請輸入至少一個域名"
+
 #: src/components/TwoFA/Authorization.vue:85
 #: src/components/TwoFA/Authorization.vue:85
 msgid "Please enter the OTP code:"
 msgid "Please enter the OTP code:"
 msgstr "請輸入 OTP 代碼:"
 msgstr "請輸入 OTP 代碼:"
@@ -3788,6 +3822,7 @@ msgstr "重新載入中"
 msgid "Reloading nginx"
 msgid "Reloading nginx"
 msgstr "正在重新載入 Nginx"
 msgstr "正在重新載入 Nginx"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:144
 #: src/views/preference/tabs/AuthSettings.vue:137
 #: src/views/preference/tabs/AuthSettings.vue:137
 msgid "Remove"
 msgid "Remove"
 msgstr "移除"
 msgstr "移除"
@@ -3870,8 +3905,8 @@ msgstr "重新命名成功"
 msgid "Renamed successfully"
 msgid "Renamed successfully"
 msgstr "重新命名成功"
 msgstr "重新命名成功"
 
 
-#: src/views/certificate/components/RenewCert.vue:46
-#: src/views/certificate/components/RenewCert.vue:53
+#: src/views/certificate/components/RenewCert.vue:48
+#: src/views/certificate/components/RenewCert.vue:55
 msgid "Renew Certificate"
 msgid "Renew Certificate"
 msgstr "更換憑證"
 msgstr "更換憑證"
 
 
@@ -3883,8 +3918,8 @@ msgstr "更新憑證錯誤"
 msgid "Renew Certificate Success"
 msgid "Renew Certificate Success"
 msgstr "更新憑證成功"
 msgstr "更新憑證成功"
 
 
-#: src/views/certificate/components/RenewCert.vue:28
-#: src/views/certificate/components/WildcardCertificate.vue:46
+#: src/views/certificate/components/DNSIssueCertificate.vue:84
+#: src/views/certificate/components/RenewCert.vue:30
 msgid "Renew successfully"
 msgid "Renew successfully"
 msgstr "更新成功"
 msgstr "更新成功"
 
 
@@ -4138,7 +4173,7 @@ msgstr "星期六"
 
 
 #: src/components/ChatGPT/ChatMessage.vue:215
 #: src/components/ChatGPT/ChatMessage.vue:215
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:129
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:129
-#: src/language/curd.ts:18 src/views/certificate/CertificateEditor.vue:266
+#: src/language/curd.ts:18 src/views/certificate/CertificateEditor.vue:264
 #: src/views/config/components/ConfigLeftPanel.vue:282
 #: src/views/config/components/ConfigLeftPanel.vue:282
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/preference/components/AuthSettings/Passkey.vue:130
 #: src/views/preference/components/AuthSettings/Passkey.vue:130
@@ -4193,7 +4228,7 @@ msgstr "儲存串流 %{name} 至 %{node} 失敗"
 msgid "Save stream %{name} to %{node} successfully"
 msgid "Save stream %{name} to %{node} successfully"
 msgstr "串流 %{name} 成功儲存至 %{node}"
 msgstr "串流 %{name} 成功儲存至 %{node}"
 
 
-#: src/language/curd.ts:35 src/views/certificate/CertificateEditor.vue:49
+#: src/language/curd.ts:35 src/views/certificate/store.ts:13
 #: src/views/preference/store/index.ts:118
 #: src/views/preference/store/index.ts:118
 msgid "Save successfully"
 msgid "Save successfully"
 msgstr "儲存成功"
 msgstr "儲存成功"
@@ -4301,6 +4336,10 @@ msgstr "傳送"
 msgid "Server"
 msgid "Server"
 msgstr "伺服器"
 msgstr "伺服器"
 
 
+#: src/views/certificate/CertificateEditor.vue:55
+msgid "Server error"
+msgstr "伺服器錯誤"
+
 #: src/views/dashboard/ServerAnalytic.vue:175
 #: src/views/dashboard/ServerAnalytic.vue:175
 msgid "Server Info"
 msgid "Server Info"
 msgstr "伺服器資訊"
 msgstr "伺服器資訊"
@@ -4435,7 +4474,7 @@ msgstr "快取載入器迭代間的休眠時間"
 msgid "Sleep time between cache manager iterations"
 msgid "Sleep time between cache manager iterations"
 msgstr "快取管理器迭代間的休眠時間"
 msgstr "快取管理器迭代間的休眠時間"
 
 
-#: src/views/certificate/CertificateEditor.vue:213
+#: src/views/certificate/CertificateEditor.vue:211
 msgid "SSL Certificate Content"
 msgid "SSL Certificate Content"
 msgstr "SSL 憑證內容"
 msgstr "SSL 憑證內容"
 
 
@@ -4447,15 +4486,15 @@ msgstr "SSL 憑證檔案必須位於 Nginx 設定目錄下:{0}"
 msgid "SSL certificate file not found"
 msgid "SSL certificate file not found"
 msgstr "SSL 憑證檔案未找到"
 msgstr "SSL 憑證檔案未找到"
 
 
-#: src/views/certificate/CertificateEditor.vue:227
+#: src/views/certificate/CertificateEditor.vue:225
 msgid "SSL Certificate Key Content"
 msgid "SSL Certificate Key Content"
 msgstr "SSL 憑證金鑰內容"
 msgstr "SSL 憑證金鑰內容"
 
 
-#: src/views/certificate/CertificateEditor.vue:192
+#: src/views/certificate/CertificateEditor.vue:190
 msgid "SSL Certificate Key Path"
 msgid "SSL Certificate Key Path"
 msgstr "SSL 憑證金鑰路徑"
 msgstr "SSL 憑證金鑰路徑"
 
 
-#: src/views/certificate/CertificateEditor.vue:177
+#: src/views/certificate/CertificateEditor.vue:175
 #: src/views/preference/tabs/ServerSettings.vue:37
 #: src/views/preference/tabs/ServerSettings.vue:37
 msgid "SSL Certificate Path"
 msgid "SSL Certificate Path"
 msgstr "SSL 憑證路徑"
 msgstr "SSL 憑證路徑"
@@ -4686,7 +4725,7 @@ msgstr "同步節點"
 msgid "Sync strategy"
 msgid "Sync strategy"
 msgstr "同步策略"
 msgstr "同步策略"
 
 
-#: src/views/certificate/CertificateEditor.vue:206
+#: src/views/certificate/CertificateEditor.vue:204
 msgid "Sync to"
 msgid "Sync to"
 msgstr "同步到"
 msgstr "同步到"
 
 
@@ -4757,11 +4796,11 @@ msgid ""
 "dashes, colons, and dots."
 "dashes, colons, and dots."
 msgstr "ICP 編號僅能包含字母、Unicode 字元、數字、連字號、破折號、冒號和句點。"
 msgstr "ICP 編號僅能包含字母、Unicode 字元、數字、連字號、破折號、冒號和句點。"
 
 
-#: src/views/certificate/CertificateEditor.vue:216
+#: src/views/certificate/CertificateEditor.vue:214
 msgid "The input is not a SSL Certificate"
 msgid "The input is not a SSL Certificate"
 msgstr "輸入的不是 SSL 憑證"
 msgstr "輸入的不是 SSL 憑證"
 
 
-#: src/views/certificate/CertificateEditor.vue:230
+#: src/views/certificate/CertificateEditor.vue:228
 msgid "The input is not a SSL Certificate Key"
 msgid "The input is not a SSL Certificate Key"
 msgstr "輸入的不是 SSL 憑證金鑰"
 msgstr "輸入的不是 SSL 憑證金鑰"
 
 
@@ -4792,11 +4831,11 @@ msgstr "節點名稱僅能包含字母、Unicode 字元、數字、連字號、
 msgid "The parameter of server_name is required"
 msgid "The parameter of server_name is required"
 msgstr "必須提供 server_name 參數"
 msgstr "必須提供 server_name 參數"
 
 
-#: src/views/certificate/CertificateEditor.vue:181
+#: src/views/certificate/CertificateEditor.vue:179
 msgid "The path exists, but the file is not a certificate"
 msgid "The path exists, but the file is not a certificate"
 msgstr "路徑存在,但檔案不是憑證"
 msgstr "路徑存在,但檔案不是憑證"
 
 
-#: src/views/certificate/CertificateEditor.vue:196
+#: src/views/certificate/CertificateEditor.vue:194
 msgid "The path exists, but the file is not a private key"
 msgid "The path exists, but the file is not a private key"
 msgstr "路徑存在,但檔案不是金鑰"
 msgstr "路徑存在,但檔案不是金鑰"
 
 
@@ -4848,17 +4887,17 @@ msgid ""
 "lose access to your account."
 "lose access to your account."
 msgstr "這些代碼是您在遺失密碼和第二重驗證因素時,存取帳戶的最後手段。如果您找不到這些代碼,您將無法再存取您的帳戶。"
 msgstr "這些代碼是您在遺失密碼和第二重驗證因素時,存取帳戶的最後手段。如果您找不到這些代碼,您將無法再存取您的帳戶。"
 
 
-#: src/views/certificate/CertificateEditor.vue:102
+#: src/views/certificate/CertificateEditor.vue:100
 msgid "This Auto Cert item is invalid, please remove it."
 msgid "This Auto Cert item is invalid, please remove it."
 msgstr "此自動憑證項目無效,請將其移除。"
 msgstr "此自動憑證項目無效,請將其移除。"
 
 
-#: src/views/certificate/CertificateEditor.vue:92
+#: src/views/certificate/CertificateEditor.vue:90
 msgid "This certificate is managed by Nginx UI"
 msgid "This certificate is managed by Nginx UI"
 msgstr "此憑證由 Nginx UI 管理"
 msgstr "此憑證由 Nginx UI 管理"
 
 
-#: src/views/certificate/CertificateEditor.vue:165
-#: src/views/certificate/CertificateEditor.vue:179
-#: src/views/certificate/CertificateEditor.vue:194
+#: src/views/certificate/CertificateEditor.vue:163
+#: src/views/certificate/CertificateEditor.vue:177
+#: src/views/certificate/CertificateEditor.vue:192
 msgid "This field is required"
 msgid "This field is required"
 msgstr "此欄位為必填項"
 msgstr "此欄位為必填項"
 
 
@@ -5299,6 +5338,10 @@ msgstr "當您產生新的復原碼時,必須下載或列印新的代碼。"
 msgid "Whether to use a temporary path when writing temporary files"
 msgid "Whether to use a temporary path when writing temporary files"
 msgstr "寫入暫存檔案時是否使用暫存路徑"
 msgstr "寫入暫存檔案時是否使用暫存路徑"
 
 
+#: src/views/certificate/components/DNSIssueCertificate.vue:107
+msgid "Wildcard Certificate"
+msgstr "萬用字元憑證"
+
 #: src/views/dashboard/components/ParamsOpt/PerformanceConfig.vue:48
 #: src/views/dashboard/components/ParamsOpt/PerformanceConfig.vue:48
 msgid "Worker Connections"
 msgid "Worker Connections"
 msgstr "工作進程連接數"
 msgstr "工作進程連接數"
@@ -5619,9 +5662,6 @@ msgstr "您的通行金鑰"
 #~ msgid "File"
 #~ msgid "File"
 #~ msgstr "檔案"
 #~ msgstr "檔案"
 
 
-#~ msgid "Server error"
-#~ msgstr "伺服器錯誤"
-
 #~ msgid "Incorrect username or password"
 #~ msgid "Incorrect username or password"
 #~ msgstr "使用者名稱或密碼不正確"
 #~ msgstr "使用者名稱或密碼不正確"
 
 

+ 8 - 13
app/src/views/certificate/CertificateEditor.vue

@@ -10,14 +10,18 @@ import FooterToolBar from '@/components/FooterToolbar'
 import NodeSelector from '@/components/NodeSelector'
 import NodeSelector from '@/components/NodeSelector'
 import { AutoCertState } from '@/constants'
 import { AutoCertState } from '@/constants'
 import RenewCert from './components/RenewCert.vue'
 import RenewCert from './components/RenewCert.vue'
+import { useCertStore } from './store'
 
 
 const route = useRoute()
 const route = useRoute()
+const certStore = useCertStore()
+const router = useRouter()
+const errors = ref({}) as Ref<Record<string, string>>
 
 
 const id = computed(() => {
 const id = computed(() => {
   return Number.parseInt(route.params.id as string)
   return Number.parseInt(route.params.id as string)
 })
 })
 
 
-const data = ref({}) as Ref<Cert>
+const { data } = storeToRefs(certStore)
 
 
 const notShowInAutoCert = computed(() => {
 const notShowInAutoCert = computed(() => {
   return data.value.auto_cert !== AutoCertState.Enable
   return data.value.auto_cert !== AutoCertState.Enable
@@ -38,28 +42,19 @@ onMounted(() => {
   init()
   init()
 })
 })
 
 
-const router = useRouter()
-const errors = ref({}) as Ref<Record<string, string>>
-
 async function save() {
 async function save() {
   try {
   try {
-    const r = data.value.id
-      ? await cert.updateItem(data.value.id, data.value)
-      : await cert.createItem(data.value)
-    data.value = r
+    await certStore.save()
     errors.value = {}
     errors.value = {}
-    message.success($gettext('Save successfully'))
-    await router.push(`/certificates/${r.id}`)
+    await router.push(`/certificates/${certStore.data.id}`)
   }
   }
   // eslint-disable-next-line ts/no-explicit-any
   // eslint-disable-next-line ts/no-explicit-any
   catch (e: any) {
   catch (e: any) {
     errors.value = e.errors
     errors.value = e.errors
-    throw e
+    message.error(e.message ?? $gettext('Server error'))
   }
   }
 }
 }
 
 
-provide('saveCert', save)
-
 const log = computed(() => {
 const log = computed(() => {
   if (!data.value.log)
   if (!data.value.log)
     return ''
     return ''

+ 3 - 3
app/src/views/certificate/CertificateList/Certificate.vue

@@ -3,8 +3,8 @@ import { CloudUploadOutlined, SafetyCertificateOutlined } from '@ant-design/icon
 import { StdTable } from '@uozi-admin/curd'
 import { StdTable } from '@uozi-admin/curd'
 import cert from '@/api/cert'
 import cert from '@/api/cert'
 import { useGlobalStore } from '@/pinia'
 import { useGlobalStore } from '@/pinia'
+import WildcardCertificate from '../components/DNSIssueCertificate.vue'
 import RemoveCert from '../components/RemoveCert.vue'
 import RemoveCert from '../components/RemoveCert.vue'
-import WildcardCertificate from '../components/WildcardCertificate.vue'
 import certColumns from './certColumns'
 import certColumns from './certColumns'
 
 
 const refWildcard = ref()
 const refWildcard = ref()
@@ -34,7 +34,7 @@ const { processingStatus } = storeToRefs(globalStore)
         @click="() => refWildcard.open()"
         @click="() => refWildcard.open()"
       >
       >
         <SafetyCertificateOutlined />
         <SafetyCertificateOutlined />
-        {{ $gettext('Issue wildcard certificate') }}
+        {{ $gettext('Issue certificate') }}
       </AButton>
       </AButton>
     </template>
     </template>
     <StdTable
     <StdTable
@@ -56,7 +56,7 @@ const { processingStatus } = storeToRefs(globalStore)
     </StdTable>
     </StdTable>
     <WildcardCertificate
     <WildcardCertificate
       ref="refWildcard"
       ref="refWildcard"
-      @issued="() => refTable.get_list()"
+      @issued="() => refTable.refresh()"
     />
     />
   </ACard>
   </ACard>
 </template>
 </template>

+ 201 - 0
app/src/views/certificate/components/DNSIssueCertificate.vue

@@ -0,0 +1,201 @@
+<script setup lang="ts">
+import type { Ref } from 'vue'
+import type { AutoCertOptions } from '@/api/auto_cert'
+import { message } from 'ant-design-vue'
+import AutoCertForm from '@/components/AutoCertForm'
+import ObtainCertLive from '@/views/site/site_edit/components/Cert/ObtainCertLive.vue'
+
+const emit = defineEmits<{
+  issued: [void]
+}>()
+
+const step = ref(0)
+const visible = ref(false)
+const data = ref({}) as Ref<AutoCertOptions>
+const domain = ref('')
+const certType = ref<'wildcard' | 'custom'>('wildcard')
+const customDomains = ref<string[]>([''])
+
+function open() {
+  visible.value = true
+  step.value = 0
+  data.value = {
+    challenge_method: 'dns01',
+    key_type: 'P256',
+  } as AutoCertOptions
+  domain.value = ''
+  certType.value = 'wildcard'
+  customDomains.value = ['']
+}
+
+defineExpose({
+  open,
+})
+
+const modalVisible = ref(false)
+const modalClosable = ref(true)
+
+const refObtainCertLive = useTemplateRef('refObtainCertLive')
+
+const computedDomain = computed(() => {
+  return `*.${domain.value}`
+})
+
+const computedDomains = computed(() => {
+  if (certType.value === 'wildcard') {
+    return [computedDomain.value, domain.value]
+  }
+  else {
+    return customDomains.value.filter(d => d.trim())
+  }
+})
+
+const computedMainDomain = computed(() => {
+  if (certType.value === 'wildcard') {
+    return computedDomain.value
+  }
+  else {
+    return customDomains.value.find(d => d.trim()) || ''
+  }
+})
+
+function addCustomDomain() {
+  customDomains.value.push('')
+}
+
+function removeCustomDomain(index: number) {
+  if (customDomains.value.length > 1) {
+    customDomains.value.splice(index, 1)
+  }
+}
+
+function issueCert() {
+  if (certType.value === 'custom') {
+    const validDomains = customDomains.value.filter(d => d.trim())
+    if (validDomains.length === 0) {
+      message.error($gettext('Please enter at least one domain'))
+      return
+    }
+  }
+
+  step.value++
+  modalVisible.value = true
+
+  refObtainCertLive.value?.issue_cert(computedMainDomain.value, computedDomains.value, data.value.key_type)
+    .then(() => {
+      message.success($gettext('Renew successfully'))
+      emit('issued')
+    })
+}
+</script>
+
+<template>
+  <div>
+    <AModal
+      v-model:open="visible"
+      :mask="false"
+      :title="$gettext('Issue Certificate')"
+      destroy-on-close
+      :footer="null"
+      :mask-closable="modalClosable"
+      :closable="modalClosable"
+      force-render
+    >
+      <template v-if="step === 0">
+        <AForm layout="vertical">
+          <AFormItem :label="$gettext('Certificate Type')">
+            <ASelect v-model:value="certType">
+              <ASelectOption value="wildcard">
+                {{ $gettext('Wildcard Certificate') }}
+              </ASelectOption>
+              <ASelectOption value="custom">
+                {{ $gettext('Custom Domains Certificate') }}
+              </ASelectOption>
+            </ASelect>
+          </AFormItem>
+
+          <template v-if="certType === 'wildcard'">
+            <AFormItem :label="$gettext('Domain')">
+              <AInput
+                v-model:value="domain"
+                addon-before="*."
+                :placeholder="$gettext('Enter your domain')"
+              />
+            </AFormItem>
+          </template>
+
+          <template v-else>
+            <AFormItem :label="$gettext('Custom Domains')">
+              <div class="space-y-2">
+                <div
+                  v-for="(_, index) in customDomains"
+                  :key="index"
+                  class="flex items-center gap-2"
+                >
+                  <AInput
+                    v-model:value="customDomains[index]"
+                    :placeholder="$gettext('Enter domain name')"
+                    class="flex-1"
+                  />
+                  <AButton
+                    v-if="customDomains.length > 1"
+                    type="link"
+                    danger
+                    @click="removeCustomDomain(index)"
+                  >
+                    {{ $gettext('Remove') }}
+                  </AButton>
+                </div>
+                <AButton
+                  block
+                  @click="addCustomDomain"
+                >
+                  {{ $gettext('Add Domain') }}
+                </AButton>
+              </div>
+
+              <AAlert
+                :message="$gettext('All selected subdomains must belong to the same DNS Provider, otherwise the certificate application will fail.')"
+                type="info"
+                show-icon
+                banner
+                class="mt-3"
+              />
+            </AFormItem>
+          </template>
+        </AForm>
+
+        <AutoCertForm
+          v-model:options="data"
+          style="max-width: 600px"
+          hide-note
+          force-dns-challenge
+        />
+
+        <div
+          v-if="step === 0"
+          class="flex justify-end"
+        >
+          <AButton
+            type="primary"
+            @click="issueCert"
+          >
+            {{ $gettext('Next') }}
+          </AButton>
+        </div>
+      </template>
+
+      <ObtainCertLive
+        v-show="step === 1"
+        ref="refObtainCertLive"
+        v-model:modal-closable="modalClosable"
+        v-model:modal-visible="modalVisible"
+        :options="data"
+      />
+    </AModal>
+  </div>
+</template>
+
+<style scoped lang="less">
+
+</style>

+ 4 - 2
app/src/views/certificate/components/RenewCert.vue

@@ -3,6 +3,7 @@ import type { AutoCertOptions } from '@/api/auto_cert'
 import { message } from 'ant-design-vue'
 import { message } from 'ant-design-vue'
 import { useGlobalStore } from '@/pinia'
 import { useGlobalStore } from '@/pinia'
 import ObtainCertLive from '@/views/site/site_edit/components/Cert/ObtainCertLive.vue'
 import ObtainCertLive from '@/views/site/site_edit/components/Cert/ObtainCertLive.vue'
+import { useCertStore } from '../store'
 
 
 const props = defineProps<{
 const props = defineProps<{
   options: AutoCertOptions
   options: AutoCertOptions
@@ -12,13 +13,14 @@ const emit = defineEmits<{
   renewed: [void]
   renewed: [void]
 }>()
 }>()
 
 
+const certStore = useCertStore()
+
 const modalVisible = ref(false)
 const modalVisible = ref(false)
 const modalClosable = ref(true)
 const modalClosable = ref(true)
 const refObtainCertLive = useTemplateRef('refObtainCertLive')
 const refObtainCertLive = useTemplateRef('refObtainCertLive')
-const saveCert = inject<() => Promise<void>>('saveCert')!
 
 
 async function issueCert() {
 async function issueCert() {
-  await saveCert()
+  await certStore.save()
 
 
   modalVisible.value = true
   modalVisible.value = true
 
 

+ 0 - 107
app/src/views/certificate/components/WildcardCertificate.vue

@@ -1,107 +0,0 @@
-<script setup lang="ts">
-import type { Ref } from 'vue'
-import type { AutoCertOptions } from '@/api/auto_cert'
-import { message } from 'ant-design-vue'
-import AutoCertForm from '@/components/AutoCertForm'
-import ObtainCertLive from '@/views/site/site_edit/components/Cert/ObtainCertLive.vue'
-
-const emit = defineEmits<{
-  issued: [void]
-}>()
-
-const step = ref(0)
-const visible = ref(false)
-const data = ref({}) as Ref<AutoCertOptions>
-const domain = ref('')
-
-function open() {
-  visible.value = true
-  step.value = 0
-  data.value = {
-    challenge_method: 'dns01',
-    key_type: 'P256',
-  } as AutoCertOptions
-  domain.value = ''
-}
-
-defineExpose({
-  open,
-})
-
-const modalVisible = ref(false)
-const modalClosable = ref(true)
-
-const refObtainCertLive = useTemplateRef('refObtainCertLive')
-
-const computedDomain = computed(() => {
-  return `*.${domain.value}`
-})
-
-function issueCert() {
-  step.value++
-  modalVisible.value = true
-
-  refObtainCertLive.value?.issue_cert(computedDomain.value, [computedDomain.value, domain.value], data.value.key_type)
-    .then(() => {
-      message.success($gettext('Renew successfully'))
-      emit('issued')
-    })
-}
-</script>
-
-<template>
-  <div>
-    <AModal
-      v-model:open="visible"
-      :mask="false"
-      :title="$gettext('Issue Wildcard Certificate')"
-      destroy-on-close
-      :footer="null"
-      :mask-closable="modalClosable"
-      :closable="modalClosable"
-      force-render
-    >
-      <template v-if="step === 0">
-        <AForm layout="vertical">
-          <AFormItem :label="$gettext('Domain')">
-            <AInput
-              v-model:value="domain"
-              addon-before="*."
-            />
-          </AFormItem>
-        </AForm>
-
-        <AutoCertForm
-          v-model:options="data"
-          style="max-width: 600px"
-          hide-note
-          force-dns-challenge
-        />
-
-        <div
-          v-if="step === 0"
-          class="flex justify-end"
-        >
-          <AButton
-            type="primary"
-            @click="issueCert"
-          >
-            {{ $gettext('Next') }}
-          </AButton>
-        </div>
-      </template>
-
-      <ObtainCertLive
-        v-show="step === 1"
-        ref="refObtainCertLive"
-        v-model:modal-closable="modalClosable"
-        v-model:modal-visible="modalVisible"
-        :options="data"
-      />
-    </AModal>
-  </div>
-</template>
-
-<style scoped lang="less">
-
-</style>

+ 21 - 0
app/src/views/certificate/store.ts

@@ -0,0 +1,21 @@
+import type { Cert } from '@/api/cert'
+import { message } from 'ant-design-vue'
+import { defineStore } from 'pinia'
+import cert from '@/api/cert'
+
+export const useCertStore = defineStore('cert', () => {
+  const data = ref<Cert>({} as Cert)
+
+  async function save() {
+    const r = data.value.id
+      ? await cert.updateItem(data.value.id, data.value)
+      : await cert.createItem(data.value)
+    data.value = r
+    message.success($gettext('Save successfully'))
+  }
+
+  return {
+    data,
+    save,
+  }
+})

+ 1 - 0
app/src/views/site/site_edit/components/Cert/ObtainCertLive.vue

@@ -76,6 +76,7 @@ async function issue_cert(config_name: string, server_name: string[], key_type:
           }
           }
           break
           break
         case 'error':
         case 'error':
+          modalClosable.value = true
           progressStatus.value = 'exception'
           progressStatus.value = 'exception'
           reject($gettext('Fail to obtain certificate'))
           reject($gettext('Fail to obtain certificate'))
           break
           break

+ 3 - 11
internal/cert/auto_cert.go

@@ -17,7 +17,7 @@ func AutoCert() {
 		if err := recover(); err != nil {
 		if err := recover(); err != nil {
 			buf := make([]byte, 1024)
 			buf := make([]byte, 1024)
 			runtime.Stack(buf, false)
 			runtime.Stack(buf, false)
-			logger.Error("AutoCert Recover", err, string(buf))
+			logger.Errorf("%s\n%s", err, buf)
 		}
 		}
 	}()
 	}()
 	logger.Info("AutoCert Worker Started")
 	logger.Info("AutoCert Worker Started")
@@ -67,9 +67,6 @@ func autoCert(certModel *model.Cert) {
 	}
 	}
 
 
 	// after 1 mo, reissue certificate
 	// after 1 mo, reissue certificate
-	logChan := make(chan string, 1)
-	errChan := make(chan error, 1)
-
 	// support SAN certification
 	// support SAN certification
 	payload := &ConfigPayload{
 	payload := &ConfigPayload{
 		CertID:                  certModel.ID,
 		CertID:                  certModel.ID,
@@ -93,11 +90,8 @@ func autoCert(certModel *model.Cert) {
 		}
 		}
 	}
 	}
 
 
-	// errChan will be closed inside IssueCert
-	go IssueCert(payload, log, errChan)
-
-	// block, unless errChan closed
-	for err := range errChan {
+	err = IssueCert(payload, log)
+	if err != nil {
 		log.Error(err)
 		log.Error(err)
 		notification.Error("Renew Certificate Error", strings.Join(payload.ServerName, ", "), nil)
 		notification.Error("Renew Certificate Error", strings.Join(payload.ServerName, ", "), nil)
 		return
 		return
@@ -109,6 +103,4 @@ func autoCert(certModel *model.Cert) {
 		notification.Error("Sync Certificate Error", err.Error(), nil)
 		notification.Error("Sync Certificate Error", err.Error(), nil)
 		return
 		return
 	}
 	}
-
-	close(logChan)
 }
 }

+ 16 - 0
internal/cert/errors.go

@@ -11,4 +11,20 @@ var (
 	ErrPayloadResourceIsNil              = e.New(50005, "payload resource is nil")
 	ErrPayloadResourceIsNil              = e.New(50005, "payload resource is nil")
 	ErrPathIsNotUnderTheNginxConfDir     = e.New(50006, "path: {0} is not under the nginx conf dir: {1}")
 	ErrPathIsNotUnderTheNginxConfDir     = e.New(50006, "path: {0} is not under the nginx conf dir: {1}")
 	ErrCertPathIsEmpty                   = e.New(50007, "certificate path is empty")
 	ErrCertPathIsEmpty                   = e.New(50007, "certificate path is empty")
+	ErrGetACMEUser                       = e.New(50008, "get acme user error: {0}")
+	ErrNewTransport                      = e.New(50009, "new transport error: {0}")
+	ErrNewLegoClient                     = e.New(50010, "new lego client error: {0}")
+	ErrGetDNSCredential                  = e.New(50011, "get dns credential error: {0}")
+	ErrProviderNotFound                  = e.New(50012, "provider not found: {0}")
+	ErrSetEnv                            = e.New(50013, "set env error: {0}")
+	ErrNewDNSChallengeProvider           = e.New(50014, "new dns challenge provider error: {0}")
+	ErrEnvironmentConfigurationIsEmpty   = e.New(50015, "environment configuration is empty")
+	ErrChallengeError                    = e.New(50016, "challenge error: {0}")
+	ErrSetEnvFlagToDisableLegoCNAME      = e.New(50017, "set env flag to disable lego CNAME support error: {0}")
+	ErrRenewCert                         = e.New(50018, "renew cert error: {0}")
+	ErrMakeCertificateDir                = e.New(50019, "make certificate dir error: {0}")
+	ErrWriteFullchainCer                 = e.New(50020, "write fullchain.cer error: {0}")
+	ErrWritePrivateKey                   = e.New(50021, "write private.key error: {0}")
+	ErrObtainCert                        = e.New(50022, "obtain cert error: {0}")
+	ErrRevokeCert                        = e.New(50023, "revoke cert error: {0}")
 )
 )

+ 28 - 31
internal/cert/issue.go

@@ -18,7 +18,7 @@ import (
 	"github.com/go-acme/lego/v4/lego"
 	"github.com/go-acme/lego/v4/lego"
 	legolog "github.com/go-acme/lego/v4/log"
 	legolog "github.com/go-acme/lego/v4/log"
 	dnsproviders "github.com/go-acme/lego/v4/providers/dns"
 	dnsproviders "github.com/go-acme/lego/v4/providers/dns"
-	"github.com/pkg/errors"
+	"github.com/uozi-tech/cosy"
 	"github.com/uozi-tech/cosy/logger"
 	"github.com/uozi-tech/cosy/logger"
 	cSettings "github.com/uozi-tech/cosy/settings"
 	cSettings "github.com/uozi-tech/cosy/settings"
 )
 )
@@ -28,20 +28,19 @@ const (
 	DNS01  = "dns01"
 	DNS01  = "dns01"
 )
 )
 
 
-func IssueCert(payload *ConfigPayload, certLogger *Logger, errChan chan error) {
+func IssueCert(payload *ConfigPayload, certLogger *Logger) error {
 	lock()
 	lock()
 	defer unlock()
 	defer unlock()
 	defer func() {
 	defer func() {
 		if err := recover(); err != nil {
 		if err := recover(); err != nil {
 			buf := make([]byte, 1024)
 			buf := make([]byte, 1024)
 			runtime.Stack(buf, false)
 			runtime.Stack(buf, false)
-			logger.Error(err)
+			logger.Errorf("%s\n%s", err, buf)
 		}
 		}
 	}()
 	}()
 
 
 	// initial a channelWriter to receive logs
 	// initial a channelWriter to receive logs
 	cw := NewChannelWriter()
 	cw := NewChannelWriter()
-	defer close(errChan)
 	defer close(cw.Ch)
 	defer close(cw.Ch)
 
 
 	// initial a logger
 	// initial a logger
@@ -58,8 +57,7 @@ func IssueCert(payload *ConfigPayload, certLogger *Logger, errChan chan error) {
 	certLogger.Info(translation.C("[Nginx UI] Preparing lego configurations"))
 	certLogger.Info(translation.C("[Nginx UI] Preparing lego configurations"))
 	user, err := payload.GetACMEUser()
 	user, err := payload.GetACMEUser()
 	if err != nil {
 	if err != nil {
-		errChan <- errors.Wrap(err, "issue cert get acme user error")
-		return
+		return cosy.WrapErrorWithParams(ErrGetACMEUser, err.Error())
 	}
 	}
 
 
 	certLogger.Info(translation.C("[Nginx UI] ACME User: %{name}, Email: %{email}, CA Dir: %{caDir}", map[string]any{
 	certLogger.Info(translation.C("[Nginx UI] ACME User: %{name}, Email: %{email}, CA Dir: %{caDir}", map[string]any{
@@ -84,7 +82,7 @@ func IssueCert(payload *ConfigPayload, certLogger *Logger, errChan chan error) {
 		t, err := transport.NewTransport(
 		t, err := transport.NewTransport(
 			transport.WithProxy(user.Proxy))
 			transport.WithProxy(user.Proxy))
 		if err != nil {
 		if err != nil {
-			return
+			return cosy.WrapErrorWithParams(ErrNewTransport, err.Error())
 		}
 		}
 		config.HTTPClient.Transport = t
 		config.HTTPClient.Transport = t
 	}
 	}
@@ -95,8 +93,7 @@ func IssueCert(payload *ConfigPayload, certLogger *Logger, errChan chan error) {
 	// A client facilitates communication with the CA server.
 	// A client facilitates communication with the CA server.
 	client, err := lego.NewClient(config)
 	client, err := lego.NewClient(config)
 	if err != nil {
 	if err != nil {
-		errChan <- errors.Wrap(err, "issue cert new client error")
-		return
+		return cosy.WrapErrorWithParams(ErrNewLegoClient, err.Error())
 	}
 	}
 
 
 	switch payload.ChallengeMethod {
 	switch payload.ChallengeMethod {
@@ -113,24 +110,20 @@ func IssueCert(payload *ConfigPayload, certLogger *Logger, errChan chan error) {
 		d := query.DnsCredential
 		d := query.DnsCredential
 		dnsCredential, err := d.FirstByID(payload.DNSCredentialID)
 		dnsCredential, err := d.FirstByID(payload.DNSCredentialID)
 		if err != nil {
 		if err != nil {
-			errChan <- errors.Wrap(err, "get dns credential error")
-			return
+			return cosy.WrapErrorWithParams(ErrGetDNSCredential, err.Error())
 		}
 		}
 
 
 		certLogger.Info(translation.C("[Nginx UI] Setting DNS01 challenge provider"))
 		certLogger.Info(translation.C("[Nginx UI] Setting DNS01 challenge provider"))
 		code := dnsCredential.Config.Code
 		code := dnsCredential.Config.Code
 		pConfig, ok := dns.GetProvider(code)
 		pConfig, ok := dns.GetProvider(code)
 		if !ok {
 		if !ok {
-			errChan <- errors.Wrap(err, "provider not found")
-			return
+			return cosy.WrapErrorWithParams(ErrProviderNotFound, err.Error())
 		}
 		}
 		certLogger.Info(translation.C("[Nginx UI] Setting environment variables"))
 		certLogger.Info(translation.C("[Nginx UI] Setting environment variables"))
 		if dnsCredential.Config.Configuration != nil {
 		if dnsCredential.Config.Configuration != nil {
 			err = pConfig.SetEnv(*dnsCredential.Config.Configuration)
 			err = pConfig.SetEnv(*dnsCredential.Config.Configuration)
 			if err != nil {
 			if err != nil {
-				errChan <- errors.Wrap(err, "set env error")
-				logger.Error(err)
-				break
+				return cosy.WrapErrorWithParams(ErrSetEnv, err.Error())
 			}
 			}
 			defer func() {
 			defer func() {
 				pConfig.CleanEnv()
 				pConfig.CleanEnv()
@@ -138,9 +131,7 @@ func IssueCert(payload *ConfigPayload, certLogger *Logger, errChan chan error) {
 			}()
 			}()
 			provider, err := dnsproviders.NewDNSChallengeProviderByName(code)
 			provider, err := dnsproviders.NewDNSChallengeProviderByName(code)
 			if err != nil {
 			if err != nil {
-				errChan <- errors.Wrap(err, "new dns challenge provider error")
-				logger.Error(err)
-				break
+				return cosy.WrapErrorWithParams(ErrNewDNSChallengeProvider, err.Error())
 			}
 			}
 			challengeOptions := make([]dns01.ChallengeOption, 0)
 			challengeOptions := make([]dns01.ChallengeOption, 0)
 
 
@@ -152,26 +143,21 @@ func IssueCert(payload *ConfigPayload, certLogger *Logger, errChan chan error) {
 
 
 			err = client.Challenge.SetDNS01Provider(provider, challengeOptions...)
 			err = client.Challenge.SetDNS01Provider(provider, challengeOptions...)
 		} else {
 		} else {
-			errChan <- errors.Wrap(err, "environment configuration is empty")
-			return
+			return cosy.WrapErrorWithParams(ErrEnvironmentConfigurationIsEmpty, err.Error())
 		}
 		}
 	}
 	}
 
 
 	if err != nil {
 	if err != nil {
-		errChan <- errors.Wrap(err, "challenge error")
-		return
+		return cosy.WrapErrorWithParams(ErrChallengeError, err.Error())
 	}
 	}
 
 
 	// fix #407
 	// fix #407
 	if payload.LegoDisableCNAMESupport {
 	if payload.LegoDisableCNAMESupport {
 		err = os.Setenv("LEGO_DISABLE_CNAME_SUPPORT", "true")
 		err = os.Setenv("LEGO_DISABLE_CNAME_SUPPORT", "true")
 		if err != nil {
 		if err != nil {
-			errChan <- errors.Wrap(err, "set env flag to disable lego CNAME support error")
-			return
+			return cosy.WrapErrorWithParams(ErrSetEnvFlagToDisableLegoCNAME, err.Error())
 		}
 		}
-		defer func() {
-			_ = os.Unsetenv("LEGO_DISABLE_CNAME_SUPPORT")
-		}()
+		defer os.Unsetenv("LEGO_DISABLE_CNAME_SUPPORT")
 	}
 	}
 
 
 	// Backup current certificate and key if RevokeOld is true
 	// Backup current certificate and key if RevokeOld is true
@@ -190,9 +176,15 @@ func IssueCert(payload *ConfigPayload, certLogger *Logger, errChan chan error) {
 
 
 	if time.Now().Sub(payload.NotBefore).Hours()/24 <= 21 &&
 	if time.Now().Sub(payload.NotBefore).Hours()/24 <= 21 &&
 		payload.Resource != nil && payload.Resource.Certificate != nil {
 		payload.Resource != nil && payload.Resource.Certificate != nil {
-		renew(payload, client, certLogger, errChan)
+		err = renew(payload, client, certLogger)
+		if err != nil {
+			return err
+		}
 	} else {
 	} else {
-		obtain(payload, client, certLogger, errChan)
+		err = obtain(payload, client, certLogger)
+		if err != nil {
+			return err
+		}
 	}
 	}
 
 
 	certLogger.Info(translation.C("[Nginx UI] Reloading nginx"))
 	certLogger.Info(translation.C("[Nginx UI] Reloading nginx"))
@@ -222,9 +214,14 @@ func IssueCert(payload *ConfigPayload, certLogger *Logger, errChan chan error) {
 		}
 		}
 
 
 		// Revoke the old certificate
 		// Revoke the old certificate
-		revoke(revokePayload, client, certLogger, errChan)
+		err = revoke(revokePayload, client, certLogger)
+		if err != nil {
+			return err
+		}
 	}
 	}
 
 
 	// Wait log to be written
 	// Wait log to be written
 	time.Sleep(2 * time.Second)
 	time.Sleep(2 * time.Second)
+
+	return nil
 }
 }

+ 6 - 9
internal/cert/logger.go

@@ -59,14 +59,15 @@ func (t *Logger) SetWebSocket(ws *websocket.Conn) {
 }
 }
 
 
 func (t *Logger) Info(c *translation.Container) {
 func (t *Logger) Info(c *translation.Container) {
+	t.mu.Lock()
+	defer t.mu.Unlock()
+
 	result, err := c.ToJSON()
 	result, err := c.ToJSON()
 	if err != nil {
 	if err != nil {
 		return
 		return
 	}
 	}
 
 
-	t.mu.Lock()
 	t.buffer = append(t.buffer, string(result))
 	t.buffer = append(t.buffer, string(result))
-	t.mu.Unlock()
 
 
 	logger.Info("AutoCert", c.ToString())
 	logger.Info("AutoCert", c.ToString())
 
 
@@ -75,11 +76,11 @@ func (t *Logger) Info(c *translation.Container) {
 
 
 func (t *Logger) Error(err error) {
 func (t *Logger) Error(err error) {
 	t.mu.Lock()
 	t.mu.Lock()
+	defer t.mu.Unlock()
 	t.buffer = append(t.buffer, fmt.Sprintf("%s [Error] %s",
 	t.buffer = append(t.buffer, fmt.Sprintf("%s [Error] %s",
 		time.Now().Format(time.DateTime),
 		time.Now().Format(time.DateTime),
 		strings.TrimSpace(err.Error()),
 		strings.TrimSpace(err.Error()),
 	))
 	))
-	t.mu.Unlock()
 
 
 	logger.Error("AutoCert", err)
 	logger.Error("AutoCert", err)
 }
 }
@@ -100,10 +101,6 @@ func (t *Logger) Close() {
 	})
 	})
 }
 }
 
 
-func (t *Logger) ToString() (content string) {
-	t.mu.Lock()
-	defer t.mu.Unlock()
-
-	content = strings.Join(t.buffer, "\n")
-	return
+func (t *Logger) ToString() string {
+	return strings.Join(t.buffer, "\n")
 }
 }

+ 10 - 5
internal/cert/obtain.go

@@ -5,10 +5,10 @@ import (
 	"github.com/0xJacky/Nginx-UI/model"
 	"github.com/0xJacky/Nginx-UI/model"
 	"github.com/go-acme/lego/v4/certificate"
 	"github.com/go-acme/lego/v4/certificate"
 	"github.com/go-acme/lego/v4/lego"
 	"github.com/go-acme/lego/v4/lego"
-	"github.com/pkg/errors"
+	"github.com/uozi-tech/cosy"
 )
 )
 
 
-func obtain(payload *ConfigPayload, client *lego.Client, l *Logger, errChan chan error) {
+func obtain(payload *ConfigPayload, client *lego.Client, l *Logger) error {
 	request := certificate.ObtainRequest{
 	request := certificate.ObtainRequest{
 		Domains:    payload.ServerName,
 		Domains:    payload.ServerName,
 		Bundle:     true,
 		Bundle:     true,
@@ -18,9 +18,9 @@ func obtain(payload *ConfigPayload, client *lego.Client, l *Logger, errChan chan
 	l.Info(translation.C("[Nginx UI] Obtaining certificate"))
 	l.Info(translation.C("[Nginx UI] Obtaining certificate"))
 	certificates, err := client.Certificate.Obtain(request)
 	certificates, err := client.Certificate.Obtain(request)
 	if err != nil {
 	if err != nil {
-		errChan <- errors.Wrap(err, "obtain certificate error")
-		return
+		return cosy.WrapErrorWithParams(ErrObtainCert, err.Error())
 	}
 	}
+
 	payload.Resource = &model.CertificateResource{
 	payload.Resource = &model.CertificateResource{
 		Resource:          certificates,
 		Resource:          certificates,
 		PrivateKey:        certificates.PrivateKey,
 		PrivateKey:        certificates.PrivateKey,
@@ -29,5 +29,10 @@ func obtain(payload *ConfigPayload, client *lego.Client, l *Logger, errChan chan
 		CSR:               certificates.CSR,
 		CSR:               certificates.CSR,
 	}
 	}
 
 
-	payload.WriteFile(l, errChan)
+	err = payload.WriteFile(l)
+	if err != nil {
+		return err
+	}
+
+	return nil
 }
 }

+ 8 - 9
internal/cert/payload.go

@@ -12,7 +12,7 @@ import (
 	"github.com/0xJacky/Nginx-UI/model"
 	"github.com/0xJacky/Nginx-UI/model"
 	"github.com/0xJacky/Nginx-UI/query"
 	"github.com/0xJacky/Nginx-UI/query"
 	"github.com/go-acme/lego/v4/certcrypto"
 	"github.com/go-acme/lego/v4/certcrypto"
-	"github.com/pkg/errors"
+	"github.com/uozi-tech/cosy"
 	"github.com/uozi-tech/cosy/logger"
 	"github.com/uozi-tech/cosy/logger"
 )
 )
 
 
@@ -76,11 +76,10 @@ func (c *ConfigPayload) mkCertificateDir() (err error) {
 	return
 	return
 }
 }
 
 
-func (c *ConfigPayload) WriteFile(l *Logger, errChan chan error) {
+func (c *ConfigPayload) WriteFile(l *Logger) error {
 	err := c.mkCertificateDir()
 	err := c.mkCertificateDir()
 	if err != nil {
 	if err != nil {
-		errChan <- errors.Wrap(err, "make certificate dir error")
-		return
+		return cosy.WrapErrorWithParams(ErrMakeCertificateDir, err.Error())
 	}
 	}
 
 
 	// Each certificate comes back with the cert bytes, the bytes of the client's
 	// Each certificate comes back with the cert bytes, the bytes of the client's
@@ -90,8 +89,7 @@ func (c *ConfigPayload) WriteFile(l *Logger, errChan chan error) {
 		c.Resource.Certificate, 0644)
 		c.Resource.Certificate, 0644)
 
 
 	if err != nil {
 	if err != nil {
-		errChan <- errors.Wrap(err, "write fullchain.cer error")
-		return
+		return cosy.WrapErrorWithParams(ErrWriteFullchainCer, err.Error())
 	}
 	}
 
 
 	l.Info(translation.C("[Nginx UI] Writing certificate private key to disk"))
 	l.Info(translation.C("[Nginx UI] Writing certificate private key to disk"))
@@ -99,13 +97,12 @@ func (c *ConfigPayload) WriteFile(l *Logger, errChan chan error) {
 		c.Resource.PrivateKey, 0644)
 		c.Resource.PrivateKey, 0644)
 
 
 	if err != nil {
 	if err != nil {
-		errChan <- errors.Wrap(err, "write private.key error")
-		return
+		return cosy.WrapErrorWithParams(ErrWritePrivateKey, err.Error())
 	}
 	}
 
 
 	// update database
 	// update database
 	if c.CertID <= 0 {
 	if c.CertID <= 0 {
-		return
+		return nil
 	}
 	}
 
 
 	db := model.UseDB()
 	db := model.UseDB()
@@ -114,6 +111,8 @@ func (c *ConfigPayload) WriteFile(l *Logger, errChan chan error) {
 		SSLCertificateKeyPath: c.GetCertificateKeyPath(),
 		SSLCertificateKeyPath: c.GetCertificateKeyPath(),
 		Resource:              c.Resource,
 		Resource:              c.Resource,
 	})
 	})
+
+	return nil
 }
 }
 
 
 func (c *ConfigPayload) getCertificateDirPath() string {
 func (c *ConfigPayload) getCertificateDirPath() string {

+ 10 - 7
internal/cert/renew.go

@@ -5,13 +5,12 @@ import (
 	"github.com/0xJacky/Nginx-UI/model"
 	"github.com/0xJacky/Nginx-UI/model"
 	"github.com/go-acme/lego/v4/certificate"
 	"github.com/go-acme/lego/v4/certificate"
 	"github.com/go-acme/lego/v4/lego"
 	"github.com/go-acme/lego/v4/lego"
-	"github.com/pkg/errors"
+	"github.com/uozi-tech/cosy"
 )
 )
 
 
-func renew(payload *ConfigPayload, client *lego.Client, l *Logger, errChan chan error) {
+func renew(payload *ConfigPayload, client *lego.Client, l *Logger) error {
 	if payload.Resource == nil {
 	if payload.Resource == nil {
-		errChan <- ErrPayloadResourceIsNil
-		return
+		return ErrPayloadResourceIsNil
 	}
 	}
 
 
 	options := &certificate.RenewOptions{
 	options := &certificate.RenewOptions{
@@ -21,8 +20,7 @@ func renew(payload *ConfigPayload, client *lego.Client, l *Logger, errChan chan
 
 
 	cert, err := client.Certificate.RenewWithOptions(payload.Resource.GetResource(), options)
 	cert, err := client.Certificate.RenewWithOptions(payload.Resource.GetResource(), options)
 	if err != nil {
 	if err != nil {
-		errChan <- errors.Wrap(err, "renew cert error")
-		return
+		return cosy.WrapErrorWithParams(ErrRenewCert, err.Error())
 	}
 	}
 
 
 	payload.Resource = &model.CertificateResource{
 	payload.Resource = &model.CertificateResource{
@@ -33,7 +31,12 @@ func renew(payload *ConfigPayload, client *lego.Client, l *Logger, errChan chan
 		CSR:               cert.CSR,
 		CSR:               cert.CSR,
 	}
 	}
 
 
-	payload.WriteFile(l, errChan)
+	err = payload.WriteFile(l)
+	if err != nil {
+		return err
+	}
 
 
 	l.Info(translation.C("[Nginx UI] Certificate renewed successfully"))
 	l.Info(translation.C("[Nginx UI] Certificate renewed successfully"))
+
+	return nil
 }
 }

+ 9 - 6
internal/cert/revoke.go

@@ -11,6 +11,7 @@ import (
 	"github.com/go-acme/lego/v4/lego"
 	"github.com/go-acme/lego/v4/lego"
 	legolog "github.com/go-acme/lego/v4/log"
 	legolog "github.com/go-acme/lego/v4/log"
 	"github.com/pkg/errors"
 	"github.com/pkg/errors"
+	"github.com/uozi-tech/cosy"
 	"github.com/uozi-tech/cosy/logger"
 	"github.com/uozi-tech/cosy/logger"
 	cSettings "github.com/uozi-tech/cosy/settings"
 	cSettings "github.com/uozi-tech/cosy/settings"
 )
 )
@@ -23,7 +24,7 @@ func RevokeCert(payload *ConfigPayload, certLogger *Logger, logChan chan string,
 		if err := recover(); err != nil {
 		if err := recover(); err != nil {
 			buf := make([]byte, 1024)
 			buf := make([]byte, 1024)
 			runtime.Stack(buf, false)
 			runtime.Stack(buf, false)
-			logger.Error(err)
+			logger.Errorf("%s\n%s", err, buf)
 		}
 		}
 	}()
 	}()
 
 
@@ -82,7 +83,10 @@ func RevokeCert(payload *ConfigPayload, certLogger *Logger, logChan chan string,
 		return
 		return
 	}
 	}
 
 
-	revoke(payload, client, certLogger, errChan)
+	err = revoke(payload, client, certLogger)
+	if err != nil {
+		return
+	}
 
 
 	// If the revoked certificate was used for the server itself, reload server TLS certificate
 	// If the revoked certificate was used for the server itself, reload server TLS certificate
 	if payload.GetCertificatePath() == cSettings.ServerSettings.SSLCert &&
 	if payload.GetCertificatePath() == cSettings.ServerSettings.SSLCert &&
@@ -98,14 +102,13 @@ func RevokeCert(payload *ConfigPayload, certLogger *Logger, logChan chan string,
 }
 }
 
 
 // revoke implements the internal certificate revocation logic
 // revoke implements the internal certificate revocation logic
-func revoke(payload *ConfigPayload, client *lego.Client, l *Logger, errChan chan error) {
+func revoke(payload *ConfigPayload, client *lego.Client, l *Logger) error {
 	l.Info(translation.C("[Nginx UI] Revoking certificate"))
 	l.Info(translation.C("[Nginx UI] Revoking certificate"))
 	err := client.Certificate.Revoke(payload.Resource.Certificate)
 	err := client.Certificate.Revoke(payload.Resource.Certificate)
 	if err != nil {
 	if err != nil {
-		errChan <- errors.Wrap(err, "revoke certificate error")
-		return
+		return cosy.WrapErrorWithParams(ErrRevokeCert, err.Error())
 	}
 	}
 
 
 	l.Info(translation.C("[Nginx UI] Certificate successfully revoked"))
 	l.Info(translation.C("[Nginx UI] Certificate successfully revoked"))
-	return
+	return nil
 }
 }

+ 0 - 125
internal/cert/tencent_cloud_dns_test.go

@@ -1,125 +0,0 @@
-package cert
-
-import (
-	"crypto/ecdsa"
-	"crypto/elliptic"
-	"crypto/rand"
-	"crypto/tls"
-	"github.com/0xJacky/Nginx-UI/model"
-	"github.com/0xJacky/Nginx-UI/settings"
-	"github.com/go-acme/lego/v4/certcrypto"
-	"github.com/go-acme/lego/v4/certificate"
-	"github.com/go-acme/lego/v4/lego"
-	"github.com/go-acme/lego/v4/providers/dns/tencentcloud"
-	"github.com/go-acme/lego/v4/registration"
-	"log"
-	"net/http"
-	"os"
-	"path/filepath"
-	"strings"
-	"testing"
-)
-
-func TestTencentCloudDNS(t *testing.T) {
-	domain := []string{"test.jackyu.cn"}
-
-	privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
-	if err != nil {
-		log.Println(err)
-		return
-	}
-
-	myUser := model.AcmeUser{
-		Email: settings.CertSettings.Email,
-		Key: model.PrivateKey{
-			X: privateKey.PublicKey.X,
-			Y: privateKey.PublicKey.Y,
-		},
-	}
-
-	config := lego.NewConfig(&myUser)
-
-	if settings.NodeSettings.Demo {
-		config.CADirURL = "https://acme-staging-v02.api.letsencrypt.org/directory"
-	}
-
-	if settings.CertSettings.CADir != "" {
-		config.CADirURL = settings.CertSettings.CADir
-		if config.HTTPClient != nil {
-			config.HTTPClient.Transport = &http.Transport{
-				Proxy:           http.ProxyFromEnvironment,
-				TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
-			}
-		}
-	}
-
-	config.Certificate.KeyType = certcrypto.RSA2048
-
-	// A client facilitates communication with the CA server.
-	client, err := lego.NewClient(config)
-	if err != nil {
-		log.Println(err)
-		return
-	}
-
-	provider, err := tencentcloud.NewDNSProvider()
-
-	if err != nil {
-		log.Println(err)
-		return
-	}
-
-	err = client.Challenge.SetDNS01Provider(
-		provider,
-	)
-
-	if err != nil {
-		log.Println(err)
-		return
-	}
-
-	// New users will need to register
-	reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
-	if err != nil {
-		log.Println(err)
-		return
-	}
-	myUser.Registration = *reg
-
-	request := certificate.ObtainRequest{
-		Domains: domain,
-		Bundle:  true,
-	}
-
-	certificates, err := client.Certificate.Obtain(request)
-	if err != nil {
-		log.Println(err)
-		return
-	}
-	name := strings.Join(domain, "_")
-	saveDir := "tmp/" + name
-	if _, err = os.Stat(saveDir); os.IsNotExist(err) {
-		err = os.MkdirAll(saveDir, 0755)
-		if err != nil {
-			return
-		}
-	}
-
-	// Each certificate comes back with the cert bytes, the bytes of the client's
-	// private key, and a certificate URL. SAVE THESE TO DISK.
-	err = os.WriteFile(filepath.Join(saveDir, "fullchain.cer"),
-		certificates.Certificate, 0644)
-
-	if err != nil {
-		log.Println(err)
-		return
-	}
-
-	err = os.WriteFile(filepath.Join(saveDir, "private.key"),
-		certificates.PrivateKey, 0644)
-
-	if err != nil {
-		log.Println(err)
-		return
-	}
-}

+ 1 - 1
internal/site/delete.go

@@ -62,7 +62,7 @@ func syncDelete(name string) {
 				if err := recover(); err != nil {
 				if err := recover(); err != nil {
 					buf := make([]byte, 1024)
 					buf := make([]byte, 1024)
 					runtime.Stack(buf, false)
 					runtime.Stack(buf, false)
-					logger.Error(err)
+					logger.Errorf("%s\n%s", err, buf)
 				}
 				}
 			}()
 			}()
 			client := resty.New()
 			client := resty.New()

+ 1 - 1
internal/site/disable.go

@@ -56,7 +56,7 @@ func syncDisable(name string) {
 				if err := recover(); err != nil {
 				if err := recover(); err != nil {
 					buf := make([]byte, 1024)
 					buf := make([]byte, 1024)
 					runtime.Stack(buf, false)
 					runtime.Stack(buf, false)
-					logger.Error(err)
+					logger.Errorf("%s\n%s", err, buf)
 				}
 				}
 			}()
 			}()
 			defer wg.Done()
 			defer wg.Done()

+ 1 - 1
internal/site/enable.go

@@ -61,7 +61,7 @@ func syncEnable(name string) {
 				if err := recover(); err != nil {
 				if err := recover(); err != nil {
 					buf := make([]byte, 1024)
 					buf := make([]byte, 1024)
 					runtime.Stack(buf, false)
 					runtime.Stack(buf, false)
-					logger.Error(err)
+					logger.Errorf("%s\n%s", err, buf)
 				}
 				}
 			}()
 			}()
 			defer wg.Done()
 			defer wg.Done()

+ 2 - 2
internal/site/maintenance.go

@@ -323,7 +323,7 @@ func syncEnableMaintenance(name string) {
 				if err := recover(); err != nil {
 				if err := recover(); err != nil {
 					buf := make([]byte, 1024)
 					buf := make([]byte, 1024)
 					runtime.Stack(buf, false)
 					runtime.Stack(buf, false)
-					logger.Error(err)
+					logger.Errorf("%s\n%s", err, buf)
 				}
 				}
 			}()
 			}()
 			defer wg.Done()
 			defer wg.Done()
@@ -361,7 +361,7 @@ func syncDisableMaintenance(name string) {
 				if err := recover(); err != nil {
 				if err := recover(); err != nil {
 					buf := make([]byte, 1024)
 					buf := make([]byte, 1024)
 					runtime.Stack(buf, false)
 					runtime.Stack(buf, false)
-					logger.Error(err)
+					logger.Errorf("%s\n%s", err, buf)
 				}
 				}
 			}()
 			}()
 			defer wg.Done()
 			defer wg.Done()

+ 1 - 1
internal/site/rename.go

@@ -87,7 +87,7 @@ func syncRename(oldName, newName string) {
 				if err := recover(); err != nil {
 				if err := recover(); err != nil {
 					buf := make([]byte, 1024)
 					buf := make([]byte, 1024)
 					runtime.Stack(buf, false)
 					runtime.Stack(buf, false)
-					logger.Error(err)
+					logger.Errorf("%s\n%s", err, buf)
 				}
 				}
 			}()
 			}()
 			defer wg.Done()
 			defer wg.Done()

+ 1 - 1
internal/site/save.go

@@ -82,7 +82,7 @@ func syncSave(name string, content string) {
 				if err := recover(); err != nil {
 				if err := recover(); err != nil {
 					buf := make([]byte, 1024)
 					buf := make([]byte, 1024)
 					runtime.Stack(buf, false)
 					runtime.Stack(buf, false)
-					logger.Error(err)
+					logger.Errorf("%s\n%s", err, buf)
 				}
 				}
 			}()
 			}()
 			defer wg.Done()
 			defer wg.Done()

+ 1 - 1
internal/stream/delete.go

@@ -57,7 +57,7 @@ func syncDelete(name string) {
 				if err := recover(); err != nil {
 				if err := recover(); err != nil {
 					buf := make([]byte, 1024)
 					buf := make([]byte, 1024)
 					runtime.Stack(buf, false)
 					runtime.Stack(buf, false)
-					logger.Error(err)
+					logger.Errorf("%s\n%s", err, buf)
 				}
 				}
 			}()
 			}()
 			client := resty.New()
 			client := resty.New()

+ 1 - 1
internal/stream/disable.go

@@ -56,7 +56,7 @@ func syncDisable(name string) {
 				if err := recover(); err != nil {
 				if err := recover(); err != nil {
 					buf := make([]byte, 1024)
 					buf := make([]byte, 1024)
 					runtime.Stack(buf, false)
 					runtime.Stack(buf, false)
-					logger.Error(err)
+					logger.Errorf("%s\n%s", err, buf)
 				}
 				}
 			}()
 			}()
 			defer wg.Done()
 			defer wg.Done()

+ 1 - 1
internal/stream/enable.go

@@ -61,7 +61,7 @@ func syncEnable(name string) {
 				if err := recover(); err != nil {
 				if err := recover(); err != nil {
 					buf := make([]byte, 1024)
 					buf := make([]byte, 1024)
 					runtime.Stack(buf, false)
 					runtime.Stack(buf, false)
-					logger.Error(err)
+					logger.Errorf("%s\n%s", err, buf)
 				}
 				}
 			}()
 			}()
 			defer wg.Done()
 			defer wg.Done()

+ 1 - 1
internal/stream/rename.go

@@ -87,7 +87,7 @@ func syncRename(oldName, newName string) {
 				if err := recover(); err != nil {
 				if err := recover(); err != nil {
 					buf := make([]byte, 1024)
 					buf := make([]byte, 1024)
 					runtime.Stack(buf, false)
 					runtime.Stack(buf, false)
-					logger.Error(err)
+					logger.Errorf("%s\n%s", err, buf)
 				}
 				}
 			}()
 			}()
 			defer wg.Done()
 			defer wg.Done()

+ 1 - 1
internal/stream/save.go

@@ -81,7 +81,7 @@ func syncSave(name string, content string) {
 				if err := recover(); err != nil {
 				if err := recover(); err != nil {
 					buf := make([]byte, 1024)
 					buf := make([]byte, 1024)
 					runtime.Stack(buf, false)
 					runtime.Stack(buf, false)
-					logger.Error(err)
+					logger.Errorf("%s\n%s", err, buf)
 				}
 				}
 			}()
 			}()
 			defer wg.Done()
 			defer wg.Done()