Browse Source

refactor(cert): introducing new management page

1. User can now view the latest renew logs of the certain certificate.

2. Add manually renew button in certificate modify page for managed certificate (auto cert)
0xJacky 1 year ago
parent
commit
ac68fd05c9
36 changed files with 1921 additions and 1299 deletions
  1. 59 80
      api/certificate/certificate.go
  2. 19 12
      api/certificate/issue.go
  3. 15 20
      api/sites/domain.go
  4. 2 8
      api/sites/sites.go
  5. 1 1
      app/src/api/auto_cert.ts
  6. 1 1
      app/src/api/domain.ts
  7. 2 2
      app/src/language/constants.ts
  8. 116 79
      app/src/language/en/app.po
  9. 126 81
      app/src/language/es/app.po
  10. 126 81
      app/src/language/fr_FR/app.po
  11. 102 75
      app/src/language/messages.pot
  12. 124 81
      app/src/language/ru_RU/app.po
  13. BIN
      app/src/language/zh_CN/app.mo
  14. 116 79
      app/src/language/zh_CN/app.po
  15. 126 81
      app/src/language/zh_TW/app.po
  16. 17 0
      app/src/routes/index.ts
  17. 1 1
      app/src/version.json
  18. 44 95
      app/src/views/certificate/Certificate.vue
  19. 200 0
      app/src/views/certificate/CertificateEditor.vue
  20. 68 0
      app/src/views/certificate/RenewCert.vue
  21. 4 1
      app/src/views/domain/cert/Cert.vue
  22. 1 1
      app/src/views/domain/cert/CertInfo.vue
  23. 0 21
      app/src/views/domain/cert/IssueCert.vue
  24. 54 51
      app/src/views/domain/cert/components/AutoCertStepOne.vue
  25. 10 10
      app/src/views/domain/cert/components/DNSChallenge.vue
  26. 19 84
      app/src/views/domain/cert/components/ObtainCert.vue
  27. 163 0
      app/src/views/domain/cert/components/ObtainCertLive.vue
  28. 1 1
      app/version.json
  29. 49 97
      internal/cert/auto_cert.go
  30. 203 235
      internal/cert/cert.go
  31. 17 2
      internal/cert/cert_info.go
  32. 43 0
      internal/cert/issue.go
  33. 46 0
      internal/cert/logger.go
  34. 46 0
      internal/cert/write_file.go
  35. 0 18
      model/cert.go
  36. 0 1
      settings/settings.go

+ 59 - 80
api/certificate/certificate.go

@@ -3,48 +3,31 @@ package certificate
 import (
 import (
 	"github.com/0xJacky/Nginx-UI/api"
 	"github.com/0xJacky/Nginx-UI/api"
 	"github.com/0xJacky/Nginx-UI/api/cosy"
 	"github.com/0xJacky/Nginx-UI/api/cosy"
-	"github.com/0xJacky/Nginx-UI/api/sites"
 	"github.com/0xJacky/Nginx-UI/internal/cert"
 	"github.com/0xJacky/Nginx-UI/internal/cert"
 	"github.com/0xJacky/Nginx-UI/model"
 	"github.com/0xJacky/Nginx-UI/model"
+	"github.com/0xJacky/Nginx-UI/query"
 	"github.com/gin-gonic/gin"
 	"github.com/gin-gonic/gin"
 	"github.com/spf13/cast"
 	"github.com/spf13/cast"
 	"net/http"
 	"net/http"
 	"os"
 	"os"
-	"path/filepath"
 )
 )
 
 
-func GetCertList(c *gin.Context) {
-	cosy.Core[model.Cert](c).SetFussy("name", "domain").PagingList()
+type APICertificate struct {
+	*model.Cert
+	SSLCertificate    string     `json:"ssl_certificate,omitempty"`
+	SSLCertificateKey string     `json:"ssl_certificate_key,omitempty"`
+	CertificateInfo   *cert.Info `json:"certificate_info,omitempty"`
 }
 }
 
 
-func getCert(c *gin.Context, certModel *model.Cert) {
-	type resp struct {
-		*model.Cert
-		SSLCertificate    string                 `json:"ssl_certificate"`
-		SSLCertificateKey string                 `json:"ssl_certificate_key"`
-		CertificateInfo   *sites.CertificateInfo `json:"certificate_info,omitempty"`
-	}
-
+func Transformer(certModel *model.Cert) (certificate *APICertificate) {
 	var sslCertificationBytes, sslCertificationKeyBytes []byte
 	var sslCertificationBytes, sslCertificationKeyBytes []byte
-	var certificateInfo *sites.CertificateInfo
+	var certificateInfo *cert.Info
 	if certModel.SSLCertificatePath != "" {
 	if certModel.SSLCertificatePath != "" {
 		if _, err := os.Stat(certModel.SSLCertificatePath); err == nil {
 		if _, err := os.Stat(certModel.SSLCertificatePath); err == nil {
 			sslCertificationBytes, _ = os.ReadFile(certModel.SSLCertificatePath)
 			sslCertificationBytes, _ = os.ReadFile(certModel.SSLCertificatePath)
 		}
 		}
 
 
-		pubKey, err := cert.GetCertInfo(certModel.SSLCertificatePath)
-
-		if err != nil {
-			api.ErrHandler(c, err)
-			return
-		}
-
-		certificateInfo = &sites.CertificateInfo{
-			SubjectName: pubKey.Subject.CommonName,
-			IssuerName:  pubKey.Issuer.CommonName,
-			NotAfter:    pubKey.NotAfter,
-			NotBefore:   pubKey.NotBefore,
-		}
+		certificateInfo, _ = cert.GetCertInfo(certModel.SSLCertificatePath)
 	}
 	}
 
 
 	if certModel.SSLCertificateKeyPath != "" {
 	if certModel.SSLCertificateKeyPath != "" {
@@ -53,23 +36,37 @@ func getCert(c *gin.Context, certModel *model.Cert) {
 		}
 		}
 	}
 	}
 
 
-	c.JSON(http.StatusOK, resp{
-		certModel,
-		string(sslCertificationBytes),
-		string(sslCertificationKeyBytes),
-		certificateInfo,
-	})
+	return &APICertificate{
+		Cert:              certModel,
+		SSLCertificate:    string(sslCertificationBytes),
+		SSLCertificateKey: string(sslCertificationKeyBytes),
+		CertificateInfo:   certificateInfo,
+	}
+}
+
+func GetCertList(c *gin.Context) {
+	cosy.Core[model.Cert](c).SetFussy("name", "domain").SetTransformer(func(m *model.Cert) any {
+
+		info, _ := cert.GetCertInfo(m.SSLCertificatePath)
+
+		return APICertificate{
+			Cert:            m,
+			CertificateInfo: info,
+		}
+	}).PagingList()
 }
 }
 
 
 func GetCert(c *gin.Context) {
 func GetCert(c *gin.Context) {
-	certModel, err := model.FirstCertByID(cast.ToInt(c.Param("id")))
+	q := query.Cert
+
+	certModel, err := q.FirstByID(cast.ToInt(c.Param("id")))
 
 
 	if err != nil {
 	if err != nil {
 		api.ErrHandler(c, err)
 		api.ErrHandler(c, err)
 		return
 		return
 	}
 	}
 
 
-	getCert(c, &certModel)
+	c.JSON(http.StatusOK, Transformer(certModel))
 }
 }
 
 
 func AddCert(c *gin.Context) {
 func AddCert(c *gin.Context) {
@@ -77,8 +74,10 @@ func AddCert(c *gin.Context) {
 		Name                  string `json:"name"`
 		Name                  string `json:"name"`
 		SSLCertificatePath    string `json:"ssl_certificate_path" binding:"required"`
 		SSLCertificatePath    string `json:"ssl_certificate_path" binding:"required"`
 		SSLCertificateKeyPath string `json:"ssl_certificate_key_path" binding:"required"`
 		SSLCertificateKeyPath string `json:"ssl_certificate_key_path" binding:"required"`
-		SSLCertification      string `json:"ssl_certification"`
-		SSLCertificationKey   string `json:"ssl_certification_key"`
+		SSLCertificate        string `json:"ssl_certificate"`
+		SSLCertificateKey     string `json:"ssl_certificate_key"`
+		ChallengeMethod       string `json:"challenge_method"`
+		DnsCredentialID       int    `json:"dns_credential_id"`
 	}
 	}
 	if !api.BindAndValid(c, &json) {
 	if !api.BindAndValid(c, &json) {
 		return
 		return
@@ -87,6 +86,8 @@ func AddCert(c *gin.Context) {
 		Name:                  json.Name,
 		Name:                  json.Name,
 		SSLCertificatePath:    json.SSLCertificatePath,
 		SSLCertificatePath:    json.SSLCertificatePath,
 		SSLCertificateKeyPath: json.SSLCertificateKeyPath,
 		SSLCertificateKeyPath: json.SSLCertificateKeyPath,
+		ChallengeMethod:       json.ChallengeMethod,
+		DnsCredentialID:       json.DnsCredentialID,
 	}
 	}
 
 
 	err := certModel.Insert()
 	err := certModel.Insert()
@@ -96,35 +97,21 @@ func AddCert(c *gin.Context) {
 		return
 		return
 	}
 	}
 
 
-	err = os.MkdirAll(filepath.Dir(json.SSLCertificatePath), 0644)
-	if err != nil {
-		api.ErrHandler(c, err)
-		return
+	content := &cert.Content{
+		SSLCertificatePath:    json.SSLCertificatePath,
+		SSLCertificateKeyPath: json.SSLCertificateKeyPath,
+		SSLCertificate:        json.SSLCertificate,
+		SSLCertificateKey:     json.SSLCertificateKey,
 	}
 	}
 
 
-	err = os.MkdirAll(filepath.Dir(json.SSLCertificateKeyPath), 0644)
+	err = content.WriteFile()
+
 	if err != nil {
 	if err != nil {
 		api.ErrHandler(c, err)
 		api.ErrHandler(c, err)
 		return
 		return
 	}
 	}
 
 
-	if json.SSLCertification != "" {
-		err = os.WriteFile(json.SSLCertificatePath, []byte(json.SSLCertification), 0644)
-		if err != nil {
-			api.ErrHandler(c, err)
-			return
-		}
-	}
-
-	if json.SSLCertificationKey != "" {
-		err = os.WriteFile(json.SSLCertificateKeyPath, []byte(json.SSLCertificationKey), 0644)
-		if err != nil {
-			api.ErrHandler(c, err)
-			return
-		}
-	}
-
-	getCert(c, certModel)
+	c.JSON(http.StatusOK, Transformer(certModel))
 }
 }
 
 
 func ModifyCert(c *gin.Context) {
 func ModifyCert(c *gin.Context) {
@@ -136,13 +123,17 @@ func ModifyCert(c *gin.Context) {
 		SSLCertificateKeyPath string `json:"ssl_certificate_key_path" binding:"required"`
 		SSLCertificateKeyPath string `json:"ssl_certificate_key_path" binding:"required"`
 		SSLCertificate        string `json:"ssl_certificate"`
 		SSLCertificate        string `json:"ssl_certificate"`
 		SSLCertificateKey     string `json:"ssl_certificate_key"`
 		SSLCertificateKey     string `json:"ssl_certificate_key"`
+		ChallengeMethod       string `json:"challenge_method"`
+		DnsCredentialID       int    `json:"dns_credential_id"`
 	}
 	}
 
 
 	if !api.BindAndValid(c, &json) {
 	if !api.BindAndValid(c, &json) {
 		return
 		return
 	}
 	}
 
 
-	certModel, err := model.FirstCertByID(id)
+	q := query.Cert
+
+	certModel, err := q.FirstByID(id)
 	if err != nil {
 	if err != nil {
 		api.ErrHandler(c, err)
 		api.ErrHandler(c, err)
 		return
 		return
@@ -152,6 +143,8 @@ func ModifyCert(c *gin.Context) {
 		Name:                  json.Name,
 		Name:                  json.Name,
 		SSLCertificatePath:    json.SSLCertificatePath,
 		SSLCertificatePath:    json.SSLCertificatePath,
 		SSLCertificateKeyPath: json.SSLCertificateKeyPath,
 		SSLCertificateKeyPath: json.SSLCertificateKeyPath,
+		ChallengeMethod:       json.ChallengeMethod,
+		DnsCredentialID:       json.DnsCredentialID,
 	})
 	})
 
 
 	if err != nil {
 	if err != nil {
@@ -159,34 +152,20 @@ func ModifyCert(c *gin.Context) {
 		return
 		return
 	}
 	}
 
 
-	err = os.MkdirAll(filepath.Dir(json.SSLCertificatePath), 0644)
-	if err != nil {
-		api.ErrHandler(c, err)
-		return
+	content := &cert.Content{
+		SSLCertificatePath:    json.SSLCertificatePath,
+		SSLCertificateKeyPath: json.SSLCertificateKeyPath,
+		SSLCertificate:        json.SSLCertificate,
+		SSLCertificateKey:     json.SSLCertificateKey,
 	}
 	}
 
 
-	err = os.MkdirAll(filepath.Dir(json.SSLCertificateKeyPath), 0644)
+	err = content.WriteFile()
+
 	if err != nil {
 	if err != nil {
 		api.ErrHandler(c, err)
 		api.ErrHandler(c, err)
 		return
 		return
 	}
 	}
 
 
-	if json.SSLCertificate != "" {
-		err = os.WriteFile(json.SSLCertificatePath, []byte(json.SSLCertificate), 0644)
-		if err != nil {
-			api.ErrHandler(c, err)
-			return
-		}
-	}
-
-	if json.SSLCertificateKeyPath != "" {
-		err = os.WriteFile(json.SSLCertificateKeyPath, []byte(json.SSLCertificateKey), 0644)
-		if err != nil {
-			api.ErrHandler(c, err)
-			return
-		}
-	}
-
 	GetCert(c)
 	GetCert(c)
 }
 }
 
 

+ 19 - 12
api/certificate/issue.go

@@ -24,7 +24,7 @@ type IssueCertResponse struct {
 	SSLCertificateKey string `json:"ssl_certificate_key,omitempty"`
 	SSLCertificateKey string `json:"ssl_certificate_key,omitempty"`
 }
 }
 
 
-func handleIssueCertLogChan(conn *websocket.Conn, logChan chan string) {
+func handleIssueCertLogChan(conn *websocket.Conn, log *cert.Logger, logChan chan string) {
 	defer func() {
 	defer func() {
 		if err := recover(); err != nil {
 		if err := recover(); err != nil {
 			logger.Error(err)
 			logger.Error(err)
@@ -33,6 +33,8 @@ func handleIssueCertLogChan(conn *websocket.Conn, logChan chan string) {
 
 
 	for logString := range logChan {
 	for logString := range logChan {
 
 
+		log.Info(logString)
+
 		err := conn.WriteJSON(IssueCertResponse{
 		err := conn.WriteJSON(IssueCertResponse{
 			Status:  Info,
 			Status:  Info,
 			Message: logString,
 			Message: logString,
@@ -42,7 +44,6 @@ func handleIssueCertLogChan(conn *websocket.Conn, logChan chan string) {
 			logger.Error(err)
 			logger.Error(err)
 			return
 			return
 		}
 		}
-
 	}
 	}
 }
 }
 
 
@@ -65,9 +66,9 @@ func IssueCert(c *gin.Context) {
 	}(ws)
 	}(ws)
 
 
 	// read
 	// read
-	buffer := &cert.ConfigPayload{}
+	payload := &cert.ConfigPayload{}
 
 
-	err = ws.ReadJSON(buffer)
+	err = ws.ReadJSON(payload)
 
 
 	if err != nil {
 	if err != nil {
 		logger.Error(err)
 		logger.Error(err)
@@ -84,15 +85,20 @@ func IssueCert(c *gin.Context) {
 	logChan := make(chan string, 1)
 	logChan := make(chan string, 1)
 	errChan := make(chan error, 1)
 	errChan := make(chan error, 1)
 
 
-	go cert.IssueCert(buffer, logChan, errChan)
+	log := &cert.Logger{}
+	log.SetCertModel(&certModel)
+
+	go cert.IssueCert(payload, logChan, errChan)
 
 
-	go handleIssueCertLogChan(ws, logChan)
+	go handleIssueCertLogChan(ws, log, logChan)
 
 
 	// block, until errChan closes
 	// block, until errChan closes
 	for err = range errChan {
 	for err = range errChan {
-		errLog := &cert.AutoCertErrorLog{}
-		errLog.SetCertModel(&certModel)
-		errLog.Exit("issue cert", err)
+
+		log.Error(err)
+
+		// Save logs to db
+		log.Exit()
 
 
 		err = ws.WriteJSON(IssueCertResponse{
 		err = ws.WriteJSON(IssueCertResponse{
 			Status:  Error,
 			Status:  Error,
@@ -107,12 +113,12 @@ func IssueCert(c *gin.Context) {
 		return
 		return
 	}
 	}
 
 
-	certDirName := strings.Join(buffer.ServerName, "_")
+	certDirName := strings.Join(payload.ServerName, "_")
 	sslCertificatePath := nginx.GetConfPath("ssl", certDirName, "fullchain.cer")
 	sslCertificatePath := nginx.GetConfPath("ssl", certDirName, "fullchain.cer")
 	sslCertificateKeyPath := nginx.GetConfPath("ssl", certDirName, "private.key")
 	sslCertificateKeyPath := nginx.GetConfPath("ssl", certDirName, "private.key")
 
 
 	err = certModel.Updates(&model.Cert{
 	err = certModel.Updates(&model.Cert{
-		Domains:               buffer.ServerName,
+		Domains:               payload.ServerName,
 		SSLCertificatePath:    sslCertificatePath,
 		SSLCertificatePath:    sslCertificatePath,
 		SSLCertificateKeyPath: sslCertificateKeyPath,
 		SSLCertificateKeyPath: sslCertificateKeyPath,
 	})
 	})
@@ -126,7 +132,8 @@ func IssueCert(c *gin.Context) {
 		return
 		return
 	}
 	}
 
 
-	certModel.ClearLog()
+	// Save logs to db
+	log.Exit()
 
 
 	err = ws.WriteJSON(IssueCertResponse{
 	err = ws.WriteJSON(IssueCertResponse{
 		Status:            Success,
 		Status:            Success,

+ 15 - 20
api/sites/domain.go

@@ -1,19 +1,19 @@
 package sites
 package sites
 
 
 import (
 import (
-    "github.com/0xJacky/Nginx-UI/api"
-    "github.com/0xJacky/Nginx-UI/internal/cert"
-    "github.com/0xJacky/Nginx-UI/internal/config"
-    "github.com/0xJacky/Nginx-UI/internal/helper"
-    "github.com/0xJacky/Nginx-UI/internal/logger"
-    "github.com/0xJacky/Nginx-UI/internal/nginx"
-    "github.com/0xJacky/Nginx-UI/model"
-    "github.com/0xJacky/Nginx-UI/query"
-    "github.com/gin-gonic/gin"
-    "github.com/sashabaranov/go-openai"
-    "net/http"
-    "os"
-    "strings"
+	"github.com/0xJacky/Nginx-UI/api"
+	"github.com/0xJacky/Nginx-UI/internal/cert"
+	"github.com/0xJacky/Nginx-UI/internal/config"
+	"github.com/0xJacky/Nginx-UI/internal/helper"
+	"github.com/0xJacky/Nginx-UI/internal/logger"
+	"github.com/0xJacky/Nginx-UI/internal/nginx"
+	"github.com/0xJacky/Nginx-UI/model"
+	"github.com/0xJacky/Nginx-UI/query"
+	"github.com/gin-gonic/gin"
+	"github.com/sashabaranov/go-openai"
+	"net/http"
+	"os"
+	"strings"
 )
 )
 
 
 func GetDomains(c *gin.Context) {
 func GetDomains(c *gin.Context) {
@@ -146,7 +146,7 @@ func GetDomain(c *gin.Context) {
 
 
 	c.Set("maybe_error", "")
 	c.Set("maybe_error", "")
 
 
-	certInfoMap := make(map[int]CertificateInfo)
+	certInfoMap := make(map[int]*cert.Info)
 	for serverIdx, server := range nginxConfig.Servers {
 	for serverIdx, server := range nginxConfig.Servers {
 		for _, directive := range server.Directives {
 		for _, directive := range server.Directives {
 			if directive.Directive == "ssl_certificate" {
 			if directive.Directive == "ssl_certificate" {
@@ -158,12 +158,7 @@ func GetDomain(c *gin.Context) {
 					break
 					break
 				}
 				}
 
 
-				certInfoMap[serverIdx] = CertificateInfo{
-					SubjectName: pubKey.Subject.CommonName,
-					IssuerName:  pubKey.Issuer.CommonName,
-					NotAfter:    pubKey.NotAfter,
-					NotBefore:   pubKey.NotBefore,
-				}
+				certInfoMap[serverIdx] = pubKey
 
 
 				break
 				break
 			}
 			}

+ 2 - 8
api/sites/sites.go

@@ -1,18 +1,12 @@
 package sites
 package sites
 
 
 import (
 import (
+	"github.com/0xJacky/Nginx-UI/internal/cert"
 	"github.com/0xJacky/Nginx-UI/internal/nginx"
 	"github.com/0xJacky/Nginx-UI/internal/nginx"
 	"github.com/sashabaranov/go-openai"
 	"github.com/sashabaranov/go-openai"
 	"time"
 	"time"
 )
 )
 
 
-type CertificateInfo struct {
-	SubjectName string    `json:"subject_name"`
-	IssuerName  string    `json:"issuer_name"`
-	NotAfter    time.Time `json:"not_after"`
-	NotBefore   time.Time `json:"not_before"`
-}
-
 type Site struct {
 type Site struct {
 	ModifiedAt      time.Time                      `json:"modified_at"`
 	ModifiedAt      time.Time                      `json:"modified_at"`
 	Advanced        bool                           `json:"advanced"`
 	Advanced        bool                           `json:"advanced"`
@@ -22,5 +16,5 @@ type Site struct {
 	AutoCert        bool                           `json:"auto_cert"`
 	AutoCert        bool                           `json:"auto_cert"`
 	ChatGPTMessages []openai.ChatCompletionMessage `json:"chatgpt_messages,omitempty"`
 	ChatGPTMessages []openai.ChatCompletionMessage `json:"chatgpt_messages,omitempty"`
 	Tokenized       *nginx.NgxConfig               `json:"tokenized,omitempty"`
 	Tokenized       *nginx.NgxConfig               `json:"tokenized,omitempty"`
-	CertInfo        map[int]CertificateInfo        `json:"cert_info,omitempty"`
+	CertInfo        map[int]*cert.Info             `json:"cert_info,omitempty"`
 }
 }

+ 1 - 1
app/src/api/auto_cert.ts

@@ -18,7 +18,7 @@ export interface DNSProvider {
   }
   }
 }
 }
 export interface DnsChallenge extends DNSProvider {
 export interface DnsChallenge extends DNSProvider {
-  dns_credential_id: number
+  dns_credential_id: number | null
   challenge_method: string
   challenge_method: string
 }
 }
 
 

+ 1 - 1
app/src/api/domain.ts

@@ -19,7 +19,7 @@ export interface Site {
 }
 }
 
 
 export interface AutoCertRequest {
 export interface AutoCertRequest {
-  dns_credential_id: number
+  dns_credential_id: number | null
   challenge_method: string
   challenge_method: string
   domains: string[]
   domains: string[]
 }
 }

+ 2 - 2
app/src/language/constants.ts

@@ -11,8 +11,8 @@ export const msg = [
   $gettext('Generating private key for registering account'),
   $gettext('Generating private key for registering account'),
   $gettext('Preparing lego configurations'),
   $gettext('Preparing lego configurations'),
   $gettext('Creating client facilitates communication with the CA server'),
   $gettext('Creating client facilitates communication with the CA server'),
-  $gettext('Using HTTP01 challenge provider'),
-  $gettext('Using DNS01 challenge provider'),
+  $gettext('Setting HTTP01 challenge provider'),
+  $gettext('Setting DNS01 challenge provider'),
   $gettext('Setting environment variables'),
   $gettext('Setting environment variables'),
   $gettext('Cleaning environment variables'),
   $gettext('Cleaning environment variables'),
   $gettext('Registering user'),
   $gettext('Registering user'),

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

@@ -9,15 +9,15 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
 
-#: src/routes/index.ts:182
+#: src/routes/index.ts:199
 msgid "About"
 msgid "About"
 msgstr "About"
 msgstr "About"
 
 
-#: src/routes/index.ts:134 src/views/domain/ngx_conf/LogEntry.vue:78
+#: src/routes/index.ts:151 src/views/domain/ngx_conf/LogEntry.vue:78
 msgid "Access Logs"
 msgid "Access Logs"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/Certificate.vue:87
+#: src/views/certificate/Certificate.vue:96
 #: src/views/certificate/DNSCredential.vue:32 src/views/config/config.ts:36
 #: src/views/certificate/DNSCredential.vue:32 src/views/config/config.ts:36
 #: src/views/domain/DomainList.vue:50 src/views/environment/Environment.vue:105
 #: src/views/domain/DomainList.vue:50 src/views/environment/Environment.vue:105
 #: src/views/user/User.vue:46
 #: src/views/user/User.vue:46
@@ -31,6 +31,12 @@ msgstr "Action"
 msgid "Add"
 msgid "Add"
 msgstr ""
 msgstr ""
 
 
+#: src/routes/index.ts:122 src/views/certificate/Certificate.vue:115
+#: src/views/certificate/CertificateEditor.vue:76
+#, fuzzy
+msgid "Add Certificate"
+msgstr "Certificate Status"
+
 #: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:98
 #: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:98
 msgid "Add Directive Below"
 msgid "Add Directive Below"
 msgstr "Add Directive Below"
 msgstr "Add Directive Below"
@@ -102,31 +108,23 @@ msgstr ""
 msgid "Author"
 msgid "Author"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/Certificate.vue:46
 #: src/views/domain/cert/ChangeCert.vue:37
 #: src/views/domain/cert/ChangeCert.vue:37
 msgid "Auto Cert"
 msgid "Auto Cert"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/Certificate.vue:105
-msgid "Auto Cert is enabled"
-msgstr ""
-
-#: src/views/certificate/Certificate.vue:135
-msgid "Auto Cert Log"
-msgstr ""
-
 #: src/views/nginx_log/NginxLog.vue:149
 #: src/views/nginx_log/NginxLog.vue:149
 msgid "Auto Refresh"
 msgid "Auto Refresh"
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:126
+#: src/views/domain/cert/components/ObtainCert.vue:76
 msgid "Auto-renewal disabled for %{name}"
 msgid "Auto-renewal disabled for %{name}"
 msgstr "Auto-renewal disabled for %{name}"
 msgstr "Auto-renewal disabled for %{name}"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:119
+#: src/views/domain/cert/components/ObtainCert.vue:69
 msgid "Auto-renewal enabled for %{name}"
 msgid "Auto-renewal enabled for %{name}"
 msgstr "Auto-renewal enabled for %{name}"
 msgstr "Auto-renewal enabled for %{name}"
 
 
+#: src/views/certificate/CertificateEditor.vue:168
 #: src/views/config/Config.vue:75 src/views/config/ConfigEdit.vue:89
 #: src/views/config/Config.vue:75 src/views/config/ConfigEdit.vue:89
 #: src/views/domain/DomainEdit.vue:261 src/views/nginx_log/NginxLog.vue:170
 #: src/views/domain/DomainEdit.vue:261 src/views/nginx_log/NginxLog.vue:170
 msgid "Back"
 msgid "Back"
@@ -170,7 +168,7 @@ msgstr ""
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:58
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:58
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:139
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:139
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:103
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:103
-#: src/views/domain/cert/components/ObtainCert.vue:211
+#: src/views/domain/cert/components/ObtainCert.vue:150
 #: src/views/domain/components/Deploy.vue:24
 #: src/views/domain/components/Deploy.vue:24
 #: src/views/domain/components/RightSettings.vue:52
 #: src/views/domain/components/RightSettings.vue:52
 #: src/views/domain/ngx_conf/NgxConfigEditor.vue:216
 #: src/views/domain/ngx_conf/NgxConfigEditor.vue:216
@@ -186,22 +184,22 @@ msgstr "Certificate has expired"
 msgid "Certificate is valid"
 msgid "Certificate is valid"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
 
 
-#: src/views/certificate/Certificate.vue:145 src/views/domain/cert/Cert.vue:35
+#: src/views/certificate/CertificateEditor.vue:119
+#: src/views/domain/cert/Cert.vue:35
 msgid "Certificate Status"
 msgid "Certificate Status"
 msgstr "Certificate Status"
 msgstr "Certificate Status"
 
 
-#: src/routes/index.ts:100 src/views/certificate/Certificate.vue:96
+#: src/routes/index.ts:100 src/views/certificate/Certificate.vue:109
 #, fuzzy
 #, fuzzy
 msgid "Certificates"
 msgid "Certificates"
 msgstr "Certificate Status"
 msgstr "Certificate Status"
 
 
-#: src/routes/index.ts:108
+#: src/routes/index.ts:109
 #, fuzzy
 #, fuzzy
 msgid "Certificates List"
 msgid "Certificates List"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
 
 
-#: src/views/certificate/Certificate.vue:150
-#: src/views/domain/cert/components/AutoCertStepOne.vue:63
+#: src/views/domain/cert/components/AutoCertStepOne.vue:65
 msgid "Challenge Method"
 msgid "Challenge Method"
 msgstr ""
 msgstr ""
 
 
@@ -242,11 +240,6 @@ msgstr ""
 msgid "Comments"
 msgid "Comments"
 msgstr "Comments"
 msgstr "Comments"
 
 
-#: src/views/certificate/Certificate.vue:41
-#, fuzzy
-msgid "Config Name"
-msgstr "Configuration Name"
-
 #: src/views/domain/ngx_conf/config_template/ConfigTemplate.vue:82
 #: src/views/domain/ngx_conf/config_template/ConfigTemplate.vue:82
 #, fuzzy
 #, fuzzy
 msgid "Config Templates"
 msgid "Config Templates"
@@ -302,7 +295,7 @@ msgstr "Created at"
 msgid "Creating client facilitates communication with the CA server"
 msgid "Creating client facilitates communication with the CA server"
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/cert/components/DNSChallenge.vue:89
+#: src/views/domain/cert/components/DNSChallenge.vue:105
 msgid "Credential"
 msgid "Credential"
 msgstr ""
 msgstr ""
 
 
@@ -387,11 +380,10 @@ msgstr "Directive"
 msgid "Disable"
 msgid "Disable"
 msgstr "Disabled"
 msgstr "Disabled"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:128
+#: src/views/domain/cert/components/ObtainCert.vue:78
 msgid "Disable auto-renewal failed for %{name}"
 msgid "Disable auto-renewal failed for %{name}"
 msgstr "Disable auto-renewal failed for %{name}"
 msgstr "Disable auto-renewal failed for %{name}"
 
 
-#: src/views/certificate/Certificate.vue:57
 #: src/views/domain/cert/ChangeCert.vue:48 src/views/domain/DomainEdit.vue:190
 #: src/views/domain/cert/ChangeCert.vue:48 src/views/domain/DomainEdit.vue:190
 #: src/views/domain/DomainList.vue:123
 #: src/views/domain/DomainList.vue:123
 msgid "Disabled"
 msgid "Disabled"
@@ -406,16 +398,16 @@ msgstr "Disabled successfully"
 msgid "Disk IO"
 msgid "Disk IO"
 msgstr "Disk IO"
 msgstr "Disk IO"
 
 
-#: src/routes/index.ts:113 src/views/certificate/DNSCredential.vue:39
+#: src/routes/index.ts:130 src/views/certificate/DNSCredential.vue:39
 msgid "DNS Credentials"
 msgid "DNS Credentials"
 msgstr ""
 msgstr ""
 
 
 #: src/views/certificate/DNSChallenge.vue:74
 #: src/views/certificate/DNSChallenge.vue:74
-#: src/views/domain/cert/components/DNSChallenge.vue:79
+#: src/views/domain/cert/components/DNSChallenge.vue:95
 msgid "DNS Provider"
 msgid "DNS Provider"
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:69
+#: src/views/domain/cert/components/AutoCertStepOne.vue:71
 msgid "DNS01"
 msgid "DNS01"
 msgstr ""
 msgstr ""
 
 
@@ -426,7 +418,7 @@ msgid_plural "Do you want to deploy this file to remote servers?"
 msgstr[0] "Are you sure you want to remove this directive?"
 msgstr[0] "Are you sure you want to remove this directive?"
 msgstr[1] "Are you sure you want to remove this directive?"
 msgstr[1] "Are you sure you want to remove this directive?"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:207
+#: src/views/domain/cert/components/ObtainCert.vue:146
 msgid "Do you want to disable auto-cert renewal?"
 msgid "Do you want to disable auto-cert renewal?"
 msgstr ""
 msgstr ""
 
 
@@ -454,7 +446,7 @@ msgstr "Are you sure you want to remove this directive?"
 msgid "Domain Config Created Successfully"
 msgid "Domain Config Created Successfully"
 msgstr "Domain Config Created Successfully"
 msgstr "Domain Config Created Successfully"
 
 
-#: src/views/certificate/Certificate.vue:125
+#: src/views/certificate/CertificateEditor.vue:103
 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 ""
 
 
@@ -524,7 +516,7 @@ msgstr ""
 msgid "Enable %{conf_name} in %{node_name} successfully"
 msgid "Enable %{conf_name} in %{node_name} successfully"
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:121
+#: src/views/domain/cert/components/ObtainCert.vue:71
 msgid "Enable auto-renewal failed for %{name}"
 msgid "Enable auto-renewal failed for %{name}"
 msgstr "Enable auto-renewal failed for %{name}"
 msgstr "Enable auto-renewal failed for %{name}"
 
 
@@ -541,7 +533,6 @@ msgstr "Enabled successfully"
 msgid "Enable TLS"
 msgid "Enable TLS"
 msgstr "Enable TLS"
 msgstr "Enable TLS"
 
 
-#: src/views/certificate/Certificate.vue:53
 #: src/views/domain/cert/ChangeCert.vue:44
 #: src/views/domain/cert/ChangeCert.vue:44
 #: src/views/domain/components/Deploy.vue:89
 #: src/views/domain/components/Deploy.vue:89
 #: src/views/domain/components/RightSettings.vue:75
 #: src/views/domain/components/RightSettings.vue:75
@@ -559,7 +550,7 @@ msgstr "Enabled successfully"
 msgid "Encrypt website with Let's Encrypt"
 msgid "Encrypt website with Let's Encrypt"
 msgstr "Encrypt website with Let's Encrypt"
 msgstr "Encrypt website with Let's Encrypt"
 
 
-#: src/routes/index.ts:151 src/views/environment/Environment.vue:113
+#: src/routes/index.ts:168 src/views/environment/Environment.vue:113
 msgid "Environment"
 msgid "Environment"
 msgstr ""
 msgstr ""
 
 
@@ -572,7 +563,7 @@ msgstr "Comments"
 msgid "Error"
 msgid "Error"
 msgstr ""
 msgstr ""
 
 
-#: src/routes/index.ts:138 src/views/domain/ngx_conf/LogEntry.vue:86
+#: src/routes/index.ts:155 src/views/domain/ngx_conf/LogEntry.vue:86
 msgid "Error Logs"
 msgid "Error Logs"
 msgstr ""
 msgstr ""
 
 
@@ -580,6 +571,10 @@ msgstr ""
 msgid "Executable Path"
 msgid "Executable Path"
 msgstr ""
 msgstr ""
 
 
+#: src/views/certificate/Certificate.vue:84
+msgid "Expired"
+msgstr ""
+
 #: src/views/domain/cert/CertInfo.vue:27
 #: src/views/domain/cert/CertInfo.vue:27
 #, fuzzy
 #, fuzzy
 msgid "Expired At: %{date}"
 msgid "Expired At: %{date}"
@@ -655,7 +650,7 @@ msgstr ""
 msgid "Get release information error"
 msgid "Get release information error"
 msgstr "Base information"
 msgstr "Base information"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:64
+#: src/views/domain/cert/components/ObtainCertLive.vue:68
 msgid "Getting the certificate, please wait..."
 msgid "Getting the certificate, please wait..."
 msgstr "Getting the certificate, please wait..."
 msgstr "Getting the certificate, please wait..."
 
 
@@ -695,7 +690,7 @@ msgstr ""
 msgid "HTTP Port"
 msgid "HTTP Port"
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:66
+#: src/views/domain/cert/components/AutoCertStepOne.vue:68
 msgid "HTTP01"
 msgid "HTTP01"
 msgstr ""
 msgstr ""
 
 
@@ -707,7 +702,7 @@ msgstr ""
 msgid "Initialing core upgrader"
 msgid "Initialing core upgrader"
 msgstr ""
 msgstr ""
 
 
-#: src/routes/index.ts:194 src/views/other/Install.vue:139
+#: src/routes/index.ts:211 src/views/other/Install.vue:139
 msgid "Install"
 msgid "Install"
 msgstr "Install"
 msgstr "Install"
 
 
@@ -769,7 +764,12 @@ msgstr "Location"
 msgid "Locations"
 msgid "Locations"
 msgstr "Locations"
 msgstr "Locations"
 
 
-#: src/routes/index.ts:200 src/views/other/Login.vue:147
+#: src/views/certificate/CertificateEditor.vue:156
+#, fuzzy
+msgid "Log"
+msgstr "Login"
+
+#: src/routes/index.ts:217 src/views/other/Login.vue:147
 msgid "Login"
 msgid "Login"
 msgstr "Login"
 msgstr "Login"
 
 
@@ -781,7 +781,7 @@ msgstr "Login successful"
 msgid "Logout successful"
 msgid "Logout successful"
 msgstr "Logout successful"
 msgstr "Logout successful"
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:51
+#: src/views/domain/cert/components/AutoCertStepOne.vue:54
 #, fuzzy
 #, fuzzy
 msgid ""
 msgid ""
 "Make sure you have configured a reverse proxy for .well-known directory to "
 "Make sure you have configured a reverse proxy for .well-known directory to "
@@ -798,7 +798,7 @@ msgstr "Manage Configs"
 msgid "Manage Sites"
 msgid "Manage Sites"
 msgstr "Manage Sites"
 msgstr "Manage Sites"
 
 
-#: src/routes/index.ts:159 src/views/user/User.vue:53
+#: src/routes/index.ts:176 src/views/user/User.vue:53
 msgid "Manage Users"
 msgid "Manage Users"
 msgstr "Manage Users"
 msgstr "Manage Users"
 
 
@@ -813,11 +813,15 @@ msgstr "Memory and Storage"
 #: src/components/ChatGPT/ChatGPT.vue:256
 #: src/components/ChatGPT/ChatGPT.vue:256
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:137
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:137
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:336
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:336
-#: src/views/certificate/Certificate.vue:156
 #, fuzzy
 #, fuzzy
 msgid "Modify"
 msgid "Modify"
 msgstr "Modify Config"
 msgstr "Modify Config"
 
 
+#: src/routes/index.ts:114 src/views/certificate/CertificateEditor.vue:76
+#, fuzzy
+msgid "Modify Certificate"
+msgstr "Certificate Status"
+
 #: src/views/domain/DomainAdd.vue:153
 #: src/views/domain/DomainAdd.vue:153
 msgid "Modify Config"
 msgid "Modify Config"
 msgstr "Modify Config"
 msgstr "Modify Config"
@@ -827,7 +831,7 @@ msgstr "Modify Config"
 msgid "Multi-line Directive"
 msgid "Multi-line Directive"
 msgstr "Single Directive"
 msgstr "Single Directive"
 
 
-#: src/views/certificate/Certificate.vue:24
+#: src/views/certificate/Certificate.vue:22
 #: src/views/certificate/DNSCredential.vue:13 src/views/config/config.ts:9
 #: src/views/certificate/DNSCredential.vue:13 src/views/config/config.ts:9
 #: src/views/domain/cert/ChangeCert.vue:21
 #: src/views/domain/cert/ChangeCert.vue:21
 #: src/views/domain/components/RightSettings.vue:81
 #: src/views/domain/components/RightSettings.vue:81
@@ -856,7 +860,7 @@ msgstr "Network Total Send"
 msgid "New version released"
 msgid "New version released"
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:281
+#: src/views/domain/cert/components/ObtainCert.vue:216
 #: src/views/domain/DomainAdd.vue:140
 #: src/views/domain/DomainAdd.vue:140
 msgid "Next"
 msgid "Next"
 msgstr "Next"
 msgstr "Next"
@@ -882,7 +886,7 @@ msgstr ""
 msgid "Nginx Error Log Path"
 msgid "Nginx Error Log Path"
 msgstr ""
 msgstr ""
 
 
-#: src/routes/index.ts:128 src/views/nginx_log/NginxLog.vue:145
+#: src/routes/index.ts:145 src/views/nginx_log/NginxLog.vue:145
 msgid "Nginx Log"
 msgid "Nginx Log"
 msgstr ""
 msgstr ""
 
 
@@ -908,7 +912,11 @@ msgstr "No"
 msgid "Node Secret"
 msgid "Node Secret"
 msgstr ""
 msgstr ""
 
 
-#: src/routes/index.ts:206 src/routes/index.ts:208
+#: src/views/certificate/Certificate.vue:90
+msgid "Not After"
+msgstr ""
+
+#: src/routes/index.ts:223 src/routes/index.ts:225
 msgid "Not Found"
 msgid "Not Found"
 msgstr "Not Found"
 msgstr "Not Found"
 
 
@@ -917,11 +925,11 @@ msgid "Not Valid Before: %{date}"
 msgstr "Not Valid Before: %{date}"
 msgstr "Not Valid Before: %{date}"
 
 
 #: src/views/certificate/DNSCredential.vue:48
 #: src/views/certificate/DNSCredential.vue:48
-#: src/views/domain/cert/components/AutoCertStepOne.vue:38
+#: src/views/domain/cert/components/AutoCertStepOne.vue:40
 msgid "Note"
 msgid "Note"
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:252
+#: src/views/domain/cert/components/ObtainCert.vue:191
 #, fuzzy
 #, fuzzy
 msgid "Obtain certificate"
 msgid "Obtain certificate"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
@@ -941,7 +949,7 @@ msgstr ""
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:140
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:140
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:346
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:346
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:104
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:104
-#: src/views/domain/cert/components/ObtainCert.vue:210
+#: src/views/domain/cert/components/ObtainCert.vue:149
 #: src/views/domain/components/Deploy.vue:23
 #: src/views/domain/components/Deploy.vue:23
 #: src/views/domain/components/RightSettings.vue:51
 #: src/views/domain/components/RightSettings.vue:51
 #: src/views/domain/DomainList.vue:144
 #: src/views/domain/DomainList.vue:144
@@ -1014,7 +1022,7 @@ msgid ""
 "provider."
 "provider."
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:55
+#: src/views/domain/cert/components/AutoCertStepOne.vue:58
 msgid ""
 msgid ""
 "Please first add credentials in Certification > DNS Credentials, and then "
 "Please first add credentials in Certification > DNS Credentials, and then "
 "select one of the credentialsbelow to request the API of the DNS provider."
 "select one of the credentialsbelow to request the API of the DNS provider."
@@ -1051,7 +1059,7 @@ msgstr ""
 msgid "Pre-release"
 msgid "Pre-release"
 msgstr ""
 msgstr ""
 
 
-#: src/routes/index.ts:167 src/views/preference/Preference.vue:85
+#: src/routes/index.ts:184 src/views/preference/Preference.vue:85
 msgid "Preference"
 msgid "Preference"
 msgstr ""
 msgstr ""
 
 
@@ -1116,6 +1124,17 @@ msgstr ""
 msgid "Reloading nginx"
 msgid "Reloading nginx"
 msgstr ""
 msgstr ""
 
 
+#: src/views/certificate/RenewCert.vue:43
+#: src/views/certificate/RenewCert.vue:47
+#, fuzzy
+msgid "Renew Certificate"
+msgstr "Certificate is valid"
+
+#: src/views/certificate/RenewCert.vue:25
+#, fuzzy
+msgid "Renew successfully"
+msgstr "Enabled successfully"
+
 #: src/language/constants.ts:35
 #: src/language/constants.ts:35
 msgid "Requested with wrong parameters"
 msgid "Requested with wrong parameters"
 msgstr ""
 msgstr ""
@@ -1141,8 +1160,9 @@ msgstr "Advance Mode"
 msgid "Running"
 msgid "Running"
 msgstr ""
 msgstr ""
 
 
-#: src/components/ChatGPT/ChatGPT.vue:259 src/views/config/ConfigEdit.vue:98
-#: src/views/domain/DomainEdit.vue:268
+#: src/components/ChatGPT/ChatGPT.vue:259
+#: src/views/certificate/CertificateEditor.vue:175
+#: src/views/config/ConfigEdit.vue:98 src/views/domain/DomainEdit.vue:268
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:111
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:111
 #: src/views/preference/Preference.vue:113
 #: src/views/preference/Preference.vue:113
 msgid "Save"
 msgid "Save"
@@ -1158,6 +1178,7 @@ msgid "Save error %{msg}"
 msgstr "Save error %{msg}"
 msgstr "Save error %{msg}"
 
 
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:42
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:42
+#: src/views/certificate/CertificateEditor.vue:46
 #: src/views/preference/Preference.vue:58
 #: src/views/preference/Preference.vue:58
 #, fuzzy
 #, fuzzy
 msgid "Save successfully"
 msgid "Save successfully"
@@ -1199,24 +1220,32 @@ msgstr "Server error"
 msgid "Server Info"
 msgid "Server Info"
 msgstr "Server Info"
 msgstr "Server Info"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:165
+#: src/views/domain/cert/components/ObtainCert.vue:115
 msgid "server_name not found in directives"
 msgid "server_name not found in directives"
 msgstr "server_name not found in directives"
 msgstr "server_name not found in directives"
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:27
+#: src/views/domain/cert/components/AutoCertStepOne.vue:29
 #: src/views/domain/DomainAdd.vue:119
 #: src/views/domain/DomainAdd.vue:119
 msgid "server_name parameter is required"
 msgid "server_name parameter is required"
 msgstr "server_name parameter is required"
 msgstr "server_name parameter is required"
 
 
+#: src/language/constants.ts:15
+msgid "Setting DNS01 challenge provider"
+msgstr ""
+
 #: src/language/constants.ts:16
 #: src/language/constants.ts:16
 msgid "Setting environment variables"
 msgid "Setting environment variables"
 msgstr ""
 msgstr ""
 
 
+#: src/language/constants.ts:14
+msgid "Setting HTTP01 challenge provider"
+msgstr ""
+
 #: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:54
 #: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:54
 msgid "Single Directive"
 msgid "Single Directive"
 msgstr "Single Directive"
 msgstr "Single Directive"
 
 
-#: src/routes/index.ts:142
+#: src/routes/index.ts:159
 #, fuzzy
 #, fuzzy
 msgid "Site Logs"
 msgid "Site Logs"
 msgstr "Sites List"
 msgstr "Sites List"
@@ -1225,22 +1254,22 @@ msgstr "Sites List"
 msgid "Sites List"
 msgid "Sites List"
 msgstr "Sites List"
 msgstr "Sites List"
 
 
-#: src/views/certificate/Certificate.vue:164
+#: src/views/certificate/CertificateEditor.vue:135
 #, fuzzy
 #, fuzzy
 msgid "SSL Certificate Content"
 msgid "SSL Certificate Content"
 msgstr "Certificate Status"
 msgstr "Certificate Status"
 
 
-#: src/views/certificate/Certificate.vue:171
+#: src/views/certificate/CertificateEditor.vue:142
 #, fuzzy
 #, fuzzy
 msgid "SSL Certificate Key Content"
 msgid "SSL Certificate Key Content"
 msgstr "Certificate Status"
 msgstr "Certificate Status"
 
 
-#: src/views/certificate/Certificate.vue:73
+#: src/views/certificate/Certificate.vue:63
 #, fuzzy
 #, fuzzy
 msgid "SSL Certificate Key Path"
 msgid "SSL Certificate Key Path"
 msgstr "Certificate Status"
 msgstr "Certificate Status"
 
 
-#: src/views/certificate/Certificate.vue:65
+#: src/views/certificate/Certificate.vue:55
 #, fuzzy
 #, fuzzy
 msgid "SSL Certificate Path"
 msgid "SSL Certificate Path"
 msgstr "Certificate Status"
 msgstr "Certificate Status"
@@ -1255,7 +1284,8 @@ msgstr "Login"
 msgid "Stable"
 msgid "Stable"
 msgstr "Enabled"
 msgstr "Enabled"
 
 
-#: src/views/domain/DomainList.vue:25 src/views/environment/Environment.vue:78
+#: src/views/certificate/Certificate.vue:71 src/views/domain/DomainList.vue:25
+#: src/views/environment/Environment.vue:78
 msgid "Status"
 msgid "Status"
 msgstr "Status"
 msgstr "Status"
 
 
@@ -1284,7 +1314,7 @@ msgstr ""
 msgid "Switch to light theme"
 msgid "Switch to light theme"
 msgstr ""
 msgstr ""
 
 
-#: src/routes/index.ts:175
+#: src/routes/index.ts:192
 msgid "System"
 msgid "System"
 msgstr ""
 msgstr ""
 
 
@@ -1297,7 +1327,7 @@ msgstr "Enabled"
 msgid "Target"
 msgid "Target"
 msgstr ""
 msgstr ""
 
 
-#: src/routes/index.ts:120 src/views/pty/Terminal.vue:95
+#: src/routes/index.ts:137 src/views/pty/Terminal.vue:95
 msgid "Terminal"
 msgid "Terminal"
 msgstr "Terminal"
 msgstr "Terminal"
 
 
@@ -1305,7 +1335,7 @@ msgstr "Terminal"
 msgid "Terminal Start Command"
 msgid "Terminal Start Command"
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:47
+#: src/views/domain/cert/components/AutoCertStepOne.vue:50
 #, fuzzy
 #, fuzzy
 msgid ""
 msgid ""
 "The certificate for the domain will be checked 5 minutes, and will be "
 "The certificate for the domain will be checked 5 minutes, and will be "
@@ -1318,7 +1348,7 @@ msgstr ""
 msgid "The filename cannot contain the following characters: %{c}"
 msgid "The filename cannot contain the following characters: %{c}"
 msgstr "The filename cannot contain the following characters: %{c}"
 msgstr "The filename cannot contain the following characters: %{c}"
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:42
+#: src/views/domain/cert/components/AutoCertStepOne.vue:45
 #, fuzzy
 #, fuzzy
 msgid ""
 msgid ""
 "The server_name in the current configuration must be the domain name you "
 "The server_name in the current configuration must be the domain name you "
@@ -1331,10 +1361,14 @@ msgstr ""
 msgid "The username or password is incorrect"
 msgid "The username or password is incorrect"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/Certificate.vue:115
+#: src/views/certificate/CertificateEditor.vue:93
 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:83
+msgid "This certificate is managed by Nginx UI"
+msgstr ""
+
 #: src/components/StdDesign/StdDataEntry/StdFormItem.vue:31
 #: src/components/StdDesign/StdDataEntry/StdFormItem.vue:31
 msgid "This field should not be empty"
 msgid "This field should not be empty"
 msgstr ""
 msgstr ""
@@ -1347,11 +1381,10 @@ msgid ""
 "continue?"
 "continue?"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/config.ts:14
+#: src/views/certificate/Certificate.vue:39 src/views/config/config.ts:14
 msgid "Type"
 msgid "Type"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/Certificate.vue:81
 #: src/views/certificate/DNSCredential.vue:26 src/views/config/config.ts:29
 #: src/views/certificate/DNSCredential.vue:26 src/views/config/config.ts:29
 #: src/views/config/ConfigEdit.vue:123
 #: src/views/config/ConfigEdit.vue:123
 #: src/views/domain/components/RightSettings.vue:84
 #: src/views/domain/components/RightSettings.vue:84
@@ -1365,7 +1398,7 @@ msgstr "Updated at"
 msgid "Updated successfully"
 msgid "Updated successfully"
 msgstr "Saved successfully"
 msgstr "Saved successfully"
 
 
-#: src/routes/index.ts:186 src/views/system/Upgrade.vue:143
+#: src/routes/index.ts:203 src/views/system/Upgrade.vue:143
 #: src/views/system/Upgrade.vue:235
 #: src/views/system/Upgrade.vue:235
 msgid "Upgrade"
 msgid "Upgrade"
 msgstr ""
 msgstr ""
@@ -1400,12 +1433,8 @@ msgstr "Username"
 msgid "Username (*)"
 msgid "Username (*)"
 msgstr "Username (*)"
 msgstr "Username (*)"
 
 
-#: src/language/constants.ts:15
-msgid "Using DNS01 challenge provider"
-msgstr ""
-
-#: src/language/constants.ts:14
-msgid "Using HTTP01 challenge provider"
+#: src/views/certificate/Certificate.vue:80
+msgid "Valid"
 msgstr ""
 msgstr ""
 
 
 #: src/views/domain/ngx_conf/config_template/ConfigTemplate.vue:101
 #: src/views/domain/ngx_conf/config_template/ConfigTemplate.vue:101
@@ -1413,7 +1442,7 @@ msgid "View"
 msgstr ""
 msgstr ""
 
 
 #: src/views/config/InspectConfig.vue:36
 #: src/views/config/InspectConfig.vue:36
-#: src/views/domain/cert/components/AutoCertStepOne.vue:21
+#: src/views/domain/cert/components/AutoCertStepOne.vue:23
 #: src/views/domain/DomainAdd.vue:114
 #: src/views/domain/DomainAdd.vue:114
 msgid "Warning"
 msgid "Warning"
 msgstr "Warning"
 msgstr "Warning"
@@ -1424,7 +1453,7 @@ msgid ""
 "ownership verification."
 "ownership verification."
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:208
+#: src/views/domain/cert/components/ObtainCert.vue:147
 msgid ""
 msgid ""
 "We will remove the HTTPChallenge configuration from this file and reload the "
 "We will remove the HTTPChallenge configuration from this file and reload the "
 "Nginx. Are you sure you want to continue?"
 "Nginx. Are you sure you want to continue?"
@@ -1456,6 +1485,14 @@ msgstr ""
 msgid "You can check Nginx UI upgrade at this page."
 msgid "You can check Nginx UI upgrade at this page."
 msgstr ""
 msgstr ""
 
 
+#, fuzzy
+#~ msgid "Renew certificate"
+#~ msgstr "Certificate is valid"
+
+#, fuzzy
+#~ msgid "Config Name"
+#~ msgstr "Configuration Name"
+
 #, fuzzy
 #, fuzzy
 #~ msgid "Certification"
 #~ msgid "Certification"
 #~ msgstr "Certificate is valid"
 #~ msgstr "Certificate is valid"

+ 126 - 81
app/src/language/es/app.po

@@ -14,15 +14,15 @@ msgstr ""
 "Plural-Forms: nplurals=2; plural=n != 1;\n"
 "Plural-Forms: nplurals=2; plural=n != 1;\n"
 "X-Generator: Weblate 5.0\n"
 "X-Generator: Weblate 5.0\n"
 
 
-#: src/routes/index.ts:182
+#: src/routes/index.ts:199
 msgid "About"
 msgid "About"
 msgstr "Acerca de"
 msgstr "Acerca de"
 
 
-#: src/routes/index.ts:134 src/views/domain/ngx_conf/LogEntry.vue:78
+#: src/routes/index.ts:151 src/views/domain/ngx_conf/LogEntry.vue:78
 msgid "Access Logs"
 msgid "Access Logs"
 msgstr "Registros de acceso"
 msgstr "Registros de acceso"
 
 
-#: src/views/certificate/Certificate.vue:87
+#: src/views/certificate/Certificate.vue:96
 #: src/views/certificate/DNSCredential.vue:32 src/views/config/config.ts:36
 #: src/views/certificate/DNSCredential.vue:32 src/views/config/config.ts:36
 #: src/views/domain/DomainList.vue:50 src/views/environment/Environment.vue:105
 #: src/views/domain/DomainList.vue:50 src/views/environment/Environment.vue:105
 #: src/views/user/User.vue:46
 #: src/views/user/User.vue:46
@@ -36,6 +36,12 @@ msgstr "Acción"
 msgid "Add"
 msgid "Add"
 msgstr "Agregar"
 msgstr "Agregar"
 
 
+#: src/routes/index.ts:122 src/views/certificate/Certificate.vue:115
+#: src/views/certificate/CertificateEditor.vue:76
+#, fuzzy
+msgid "Add Certificate"
+msgstr "Estado del Certificado"
+
 #: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:98
 #: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:98
 msgid "Add Directive Below"
 msgid "Add Directive Below"
 msgstr "Añadir directiva a continuación"
 msgstr "Añadir directiva a continuación"
@@ -103,33 +109,23 @@ msgstr "Asistente"
 msgid "Author"
 msgid "Author"
 msgstr "Autor"
 msgstr "Autor"
 
 
-#: src/views/certificate/Certificate.vue:46
 #: src/views/domain/cert/ChangeCert.vue:37
 #: src/views/domain/cert/ChangeCert.vue:37
 msgid "Auto Cert"
 msgid "Auto Cert"
 msgstr "Certificado automático"
 msgstr "Certificado automático"
 
 
-#: src/views/certificate/Certificate.vue:105
-#, fuzzy
-msgid "Auto Cert is enabled"
-msgstr "Certificado automático"
-
-#: src/views/certificate/Certificate.vue:135
-#, fuzzy
-msgid "Auto Cert Log"
-msgstr "Registro del Certificado automático"
-
 #: src/views/nginx_log/NginxLog.vue:149
 #: src/views/nginx_log/NginxLog.vue:149
 msgid "Auto Refresh"
 msgid "Auto Refresh"
 msgstr "Actualización automática"
 msgstr "Actualización automática"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:126
+#: src/views/domain/cert/components/ObtainCert.vue:76
 msgid "Auto-renewal disabled for %{name}"
 msgid "Auto-renewal disabled for %{name}"
 msgstr "Renovación automática deshabilitada por %{name}"
 msgstr "Renovación automática deshabilitada por %{name}"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:119
+#: src/views/domain/cert/components/ObtainCert.vue:69
 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/CertificateEditor.vue:168
 #: src/views/config/Config.vue:75 src/views/config/ConfigEdit.vue:89
 #: src/views/config/Config.vue:75 src/views/config/ConfigEdit.vue:89
 #: src/views/domain/DomainEdit.vue:261 src/views/nginx_log/NginxLog.vue:170
 #: src/views/domain/DomainEdit.vue:261 src/views/nginx_log/NginxLog.vue:170
 msgid "Back"
 msgid "Back"
@@ -170,7 +166,7 @@ msgstr "Directorio CA"
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:58
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:58
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:139
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:139
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:103
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:103
-#: src/views/domain/cert/components/ObtainCert.vue:211
+#: src/views/domain/cert/components/ObtainCert.vue:150
 #: src/views/domain/components/Deploy.vue:24
 #: src/views/domain/components/Deploy.vue:24
 #: src/views/domain/components/RightSettings.vue:52
 #: src/views/domain/components/RightSettings.vue:52
 #: src/views/domain/ngx_conf/NgxConfigEditor.vue:216
 #: src/views/domain/ngx_conf/NgxConfigEditor.vue:216
@@ -186,22 +182,22 @@ msgstr "El certificado expiró"
 msgid "Certificate is valid"
 msgid "Certificate is valid"
 msgstr "El certificado es válido"
 msgstr "El certificado es válido"
 
 
-#: src/views/certificate/Certificate.vue:145 src/views/domain/cert/Cert.vue:35
+#: src/views/certificate/CertificateEditor.vue:119
+#: src/views/domain/cert/Cert.vue:35
 msgid "Certificate Status"
 msgid "Certificate Status"
 msgstr "Estado del Certificado"
 msgstr "Estado del Certificado"
 
 
-#: src/routes/index.ts:100 src/views/certificate/Certificate.vue:96
+#: src/routes/index.ts:100 src/views/certificate/Certificate.vue:109
 #, fuzzy
 #, fuzzy
 msgid "Certificates"
 msgid "Certificates"
 msgstr "Estado del Certificado"
 msgstr "Estado del Certificado"
 
 
-#: src/routes/index.ts:108
+#: src/routes/index.ts:109
 #, fuzzy
 #, fuzzy
 msgid "Certificates List"
 msgid "Certificates List"
 msgstr "Lista de Certificados"
 msgstr "Lista de Certificados"
 
 
-#: src/views/certificate/Certificate.vue:150
-#: src/views/domain/cert/components/AutoCertStepOne.vue:63
+#: src/views/domain/cert/components/AutoCertStepOne.vue:65
 msgid "Challenge Method"
 msgid "Challenge Method"
 msgstr "Método de desafío"
 msgstr "Método de desafío"
 
 
@@ -241,10 +237,6 @@ msgstr "Limpiar"
 msgid "Comments"
 msgid "Comments"
 msgstr "Comentarios"
 msgstr "Comentarios"
 
 
-#: src/views/certificate/Certificate.vue:41
-msgid "Config Name"
-msgstr "Nombre de la configuración"
-
 #: src/views/domain/ngx_conf/config_template/ConfigTemplate.vue:82
 #: src/views/domain/ngx_conf/config_template/ConfigTemplate.vue:82
 msgid "Config Templates"
 msgid "Config Templates"
 msgstr "Plantillas de configuración"
 msgstr "Plantillas de configuración"
@@ -299,7 +291,7 @@ msgstr "Creado el"
 msgid "Creating client facilitates communication with the CA server"
 msgid "Creating client facilitates communication with the CA server"
 msgstr "La creación de un cliente facilita la comunicación con el servidor CA"
 msgstr "La creación de un cliente facilita la comunicación con el servidor CA"
 
 
-#: src/views/domain/cert/components/DNSChallenge.vue:89
+#: src/views/domain/cert/components/DNSChallenge.vue:105
 msgid "Credential"
 msgid "Credential"
 msgstr "Credencial"
 msgstr "Credencial"
 
 
@@ -383,11 +375,10 @@ msgstr "Directiva"
 msgid "Disable"
 msgid "Disable"
 msgstr "Desactivado"
 msgstr "Desactivado"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:128
+#: src/views/domain/cert/components/ObtainCert.vue:78
 msgid "Disable auto-renewal failed for %{name}"
 msgid "Disable auto-renewal failed for %{name}"
 msgstr "No se pudo desactivar la renovación automática por %{name}"
 msgstr "No se pudo desactivar la renovación automática por %{name}"
 
 
-#: src/views/certificate/Certificate.vue:57
 #: src/views/domain/cert/ChangeCert.vue:48 src/views/domain/DomainEdit.vue:190
 #: src/views/domain/cert/ChangeCert.vue:48 src/views/domain/DomainEdit.vue:190
 #: src/views/domain/DomainList.vue:123
 #: src/views/domain/DomainList.vue:123
 msgid "Disabled"
 msgid "Disabled"
@@ -402,16 +393,16 @@ msgstr "Desactivado con éxito"
 msgid "Disk IO"
 msgid "Disk IO"
 msgstr "I/O del disco"
 msgstr "I/O del disco"
 
 
-#: src/routes/index.ts:113 src/views/certificate/DNSCredential.vue:39
+#: src/routes/index.ts:130 src/views/certificate/DNSCredential.vue:39
 msgid "DNS Credentials"
 msgid "DNS Credentials"
 msgstr "Credenciales de DNS"
 msgstr "Credenciales de DNS"
 
 
 #: src/views/certificate/DNSChallenge.vue:74
 #: src/views/certificate/DNSChallenge.vue:74
-#: src/views/domain/cert/components/DNSChallenge.vue:79
+#: src/views/domain/cert/components/DNSChallenge.vue:95
 msgid "DNS Provider"
 msgid "DNS Provider"
 msgstr "Proveedor DNS"
 msgstr "Proveedor DNS"
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:69
+#: src/views/domain/cert/components/AutoCertStepOne.vue:71
 msgid "DNS01"
 msgid "DNS01"
 msgstr "DNS01"
 msgstr "DNS01"
 
 
@@ -421,7 +412,7 @@ msgid_plural "Do you want to deploy this file to remote servers?"
 msgstr[0] "¿Desea desplegar este archivo en un servidor remoto?"
 msgstr[0] "¿Desea desplegar este archivo en un servidor remoto?"
 msgstr[1] "¿Desea desplegar este archivo en los servidores remotos?"
 msgstr[1] "¿Desea desplegar este archivo en los servidores remotos?"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:207
+#: src/views/domain/cert/components/ObtainCert.vue:146
 msgid "Do you want to disable auto-cert renewal?"
 msgid "Do you want to disable auto-cert renewal?"
 msgstr "¿Desea deshabilitar la renovación automática de certificado?"
 msgstr "¿Desea deshabilitar la renovación automática de certificado?"
 
 
@@ -445,7 +436,7 @@ msgstr "¿Quieres eliminar este servidor?"
 msgid "Domain Config Created Successfully"
 msgid "Domain Config Created Successfully"
 msgstr "Configuración de dominio creada con éxito"
 msgstr "Configuración de dominio creada con éxito"
 
 
-#: src/views/certificate/Certificate.vue:125
+#: src/views/certificate/CertificateEditor.vue:103
 #, fuzzy
 #, fuzzy
 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 ""
@@ -514,7 +505,7 @@ msgstr "Falló el habilitado de %{conf_name} en %{node_name}"
 msgid "Enable %{conf_name} in %{node_name} successfully"
 msgid "Enable %{conf_name} in %{node_name} successfully"
 msgstr "Habilitado exitoso de %{conf_name} en %{node_name}"
 msgstr "Habilitado exitoso de %{conf_name} en %{node_name}"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:121
+#: src/views/domain/cert/components/ObtainCert.vue:71
 msgid "Enable auto-renewal failed for %{name}"
 msgid "Enable auto-renewal failed for %{name}"
 msgstr "No se pudo activar la renovación automática por %{name}"
 msgstr "No se pudo activar la renovación automática por %{name}"
 
 
@@ -530,7 +521,6 @@ msgstr "Habilitado con éxito"
 msgid "Enable TLS"
 msgid "Enable TLS"
 msgstr "Habilitar TLS"
 msgstr "Habilitar TLS"
 
 
-#: src/views/certificate/Certificate.vue:53
 #: src/views/domain/cert/ChangeCert.vue:44
 #: src/views/domain/cert/ChangeCert.vue:44
 #: src/views/domain/components/Deploy.vue:89
 #: src/views/domain/components/Deploy.vue:89
 #: src/views/domain/components/RightSettings.vue:75
 #: src/views/domain/components/RightSettings.vue:75
@@ -548,7 +538,7 @@ msgstr "Habilitado con éxito"
 msgid "Encrypt website with Let's Encrypt"
 msgid "Encrypt website with Let's Encrypt"
 msgstr "Encriptar sitio web con Let's Encrypt"
 msgstr "Encriptar sitio web con Let's Encrypt"
 
 
-#: src/routes/index.ts:151 src/views/environment/Environment.vue:113
+#: src/routes/index.ts:168 src/views/environment/Environment.vue:113
 msgid "Environment"
 msgid "Environment"
 msgstr "Entorno"
 msgstr "Entorno"
 
 
@@ -560,7 +550,7 @@ msgstr "Entornos"
 msgid "Error"
 msgid "Error"
 msgstr "Error"
 msgstr "Error"
 
 
-#: src/routes/index.ts:138 src/views/domain/ngx_conf/LogEntry.vue:86
+#: src/routes/index.ts:155 src/views/domain/ngx_conf/LogEntry.vue:86
 msgid "Error Logs"
 msgid "Error Logs"
 msgstr "Registros de acceso"
 msgstr "Registros de acceso"
 
 
@@ -568,6 +558,10 @@ msgstr "Registros de acceso"
 msgid "Executable Path"
 msgid "Executable Path"
 msgstr "Ruta ejecutable"
 msgstr "Ruta ejecutable"
 
 
+#: src/views/certificate/Certificate.vue:84
+msgid "Expired"
+msgstr ""
+
 #: src/views/domain/cert/CertInfo.vue:27
 #: src/views/domain/cert/CertInfo.vue:27
 #, fuzzy
 #, fuzzy
 msgid "Expired At: %{date}"
 msgid "Expired At: %{date}"
@@ -641,7 +635,7 @@ msgstr "Generando clave privada para registrar cuenta"
 msgid "Get release information error"
 msgid "Get release information error"
 msgstr "Obtener error de información de versión"
 msgstr "Obtener error de información de versión"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:64
+#: src/views/domain/cert/components/ObtainCertLive.vue:68
 msgid "Getting the certificate, please wait..."
 msgid "Getting the certificate, please wait..."
 msgstr "Obteniendo el certificado, por favor espere..."
 msgstr "Obteniendo el certificado, por favor espere..."
 
 
@@ -682,7 +676,7 @@ msgstr "Host HTTP"
 msgid "HTTP Port"
 msgid "HTTP Port"
 msgstr "Puerto HTTP"
 msgstr "Puerto HTTP"
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:66
+#: src/views/domain/cert/components/AutoCertStepOne.vue:68
 msgid "HTTP01"
 msgid "HTTP01"
 msgstr "HTTP01"
 msgstr "HTTP01"
 
 
@@ -694,7 +688,7 @@ msgstr "Error de actualización de kernel inicial"
 msgid "Initialing core upgrader"
 msgid "Initialing core upgrader"
 msgstr "Inicializando la actualización del kernel"
 msgstr "Inicializando la actualización del kernel"
 
 
-#: src/routes/index.ts:194 src/views/other/Install.vue:139
+#: src/routes/index.ts:211 src/views/other/Install.vue:139
 msgid "Install"
 msgid "Install"
 msgstr "Instalar"
 msgstr "Instalar"
 
 
@@ -753,7 +747,12 @@ msgstr "Ubicación"
 msgid "Locations"
 msgid "Locations"
 msgstr "Ubicaciones"
 msgstr "Ubicaciones"
 
 
-#: src/routes/index.ts:200 src/views/other/Login.vue:147
+#: src/views/certificate/CertificateEditor.vue:156
+#, fuzzy
+msgid "Log"
+msgstr "Acceso"
+
+#: src/routes/index.ts:217 src/views/other/Login.vue:147
 msgid "Login"
 msgid "Login"
 msgstr "Acceso"
 msgstr "Acceso"
 
 
@@ -765,7 +764,7 @@ msgstr "Acceso exitoso"
 msgid "Logout successful"
 msgid "Logout successful"
 msgstr "Cierre de sesión exitoso"
 msgstr "Cierre de sesión exitoso"
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:51
+#: src/views/domain/cert/components/AutoCertStepOne.vue:54
 msgid ""
 msgid ""
 "Make sure you have configured a reverse proxy for .well-known directory to "
 "Make sure you have configured a reverse proxy for .well-known directory to "
 "HTTPChallengePort before obtaining the certificate."
 "HTTPChallengePort before obtaining the certificate."
@@ -781,7 +780,7 @@ msgstr "Administrar configuraciones"
 msgid "Manage Sites"
 msgid "Manage Sites"
 msgstr "Administrar sitios"
 msgstr "Administrar sitios"
 
 
-#: src/routes/index.ts:159 src/views/user/User.vue:53
+#: src/routes/index.ts:176 src/views/user/User.vue:53
 msgid "Manage Users"
 msgid "Manage Users"
 msgstr "Administrar usuarios"
 msgstr "Administrar usuarios"
 
 
@@ -796,10 +795,14 @@ msgstr "Memoria y almacenamiento"
 #: src/components/ChatGPT/ChatGPT.vue:256
 #: src/components/ChatGPT/ChatGPT.vue:256
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:137
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:137
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:336
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:336
-#: src/views/certificate/Certificate.vue:156
 msgid "Modify"
 msgid "Modify"
 msgstr "Modificar"
 msgstr "Modificar"
 
 
+#: src/routes/index.ts:114 src/views/certificate/CertificateEditor.vue:76
+#, fuzzy
+msgid "Modify Certificate"
+msgstr "Estado del Certificado"
+
 #: src/views/domain/DomainAdd.vue:153
 #: src/views/domain/DomainAdd.vue:153
 msgid "Modify Config"
 msgid "Modify Config"
 msgstr "Modificar configuración"
 msgstr "Modificar configuración"
@@ -808,7 +811,7 @@ msgstr "Modificar configuración"
 msgid "Multi-line Directive"
 msgid "Multi-line Directive"
 msgstr "Directiva multilínea"
 msgstr "Directiva multilínea"
 
 
-#: src/views/certificate/Certificate.vue:24
+#: src/views/certificate/Certificate.vue:22
 #: src/views/certificate/DNSCredential.vue:13 src/views/config/config.ts:9
 #: src/views/certificate/DNSCredential.vue:13 src/views/config/config.ts:9
 #: src/views/domain/cert/ChangeCert.vue:21
 #: src/views/domain/cert/ChangeCert.vue:21
 #: src/views/domain/components/RightSettings.vue:81
 #: src/views/domain/components/RightSettings.vue:81
@@ -837,7 +840,7 @@ msgstr "Total enviado por la red"
 msgid "New version released"
 msgid "New version released"
 msgstr "Se liberó una nueva versión"
 msgstr "Se liberó una nueva versión"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:281
+#: src/views/domain/cert/components/ObtainCert.vue:216
 #: src/views/domain/DomainAdd.vue:140
 #: src/views/domain/DomainAdd.vue:140
 msgid "Next"
 msgid "Next"
 msgstr "Siguiente"
 msgstr "Siguiente"
@@ -862,7 +865,7 @@ msgstr "Control de Nginx"
 msgid "Nginx Error Log Path"
 msgid "Nginx Error Log Path"
 msgstr "Ruta de registro de errores de Nginx"
 msgstr "Ruta de registro de errores de Nginx"
 
 
-#: src/routes/index.ts:128 src/views/nginx_log/NginxLog.vue:145
+#: src/routes/index.ts:145 src/views/nginx_log/NginxLog.vue:145
 msgid "Nginx Log"
 msgid "Nginx Log"
 msgstr "Registro Nginx"
 msgstr "Registro Nginx"
 
 
@@ -886,7 +889,11 @@ msgstr "No"
 msgid "Node Secret"
 msgid "Node Secret"
 msgstr "Secreto del nodo"
 msgstr "Secreto del nodo"
 
 
-#: src/routes/index.ts:206 src/routes/index.ts:208
+#: src/views/certificate/Certificate.vue:90
+msgid "Not After"
+msgstr ""
+
+#: src/routes/index.ts:223 src/routes/index.ts:225
 msgid "Not Found"
 msgid "Not Found"
 msgstr "No encontrado"
 msgstr "No encontrado"
 
 
@@ -895,11 +902,11 @@ msgid "Not Valid Before: %{date}"
 msgstr "No válido antes: %{date}"
 msgstr "No válido antes: %{date}"
 
 
 #: src/views/certificate/DNSCredential.vue:48
 #: src/views/certificate/DNSCredential.vue:48
-#: src/views/domain/cert/components/AutoCertStepOne.vue:38
+#: src/views/domain/cert/components/AutoCertStepOne.vue:40
 msgid "Note"
 msgid "Note"
 msgstr "Nota"
 msgstr "Nota"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:252
+#: src/views/domain/cert/components/ObtainCert.vue:191
 msgid "Obtain certificate"
 msgid "Obtain certificate"
 msgstr "Obtener certificado"
 msgstr "Obtener certificado"
 
 
@@ -918,7 +925,7 @@ msgstr "Desconectado"
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:140
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:140
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:346
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:346
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:104
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:104
-#: src/views/domain/cert/components/ObtainCert.vue:210
+#: src/views/domain/cert/components/ObtainCert.vue:149
 #: src/views/domain/components/Deploy.vue:23
 #: src/views/domain/components/Deploy.vue:23
 #: src/views/domain/components/RightSettings.vue:51
 #: src/views/domain/components/RightSettings.vue:51
 #: src/views/domain/DomainList.vue:144
 #: src/views/domain/DomainList.vue:144
@@ -990,7 +997,7 @@ msgid ""
 "provider."
 "provider."
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:55
+#: src/views/domain/cert/components/AutoCertStepOne.vue:58
 #, fuzzy
 #, fuzzy
 msgid ""
 msgid ""
 "Please first add credentials in Certification > DNS Credentials, and then "
 "Please first add credentials in Certification > DNS Credentials, and then "
@@ -1033,7 +1040,7 @@ msgstr "¡Seleccione al menos un nodo!"
 msgid "Pre-release"
 msgid "Pre-release"
 msgstr "Prelanzamiento"
 msgstr "Prelanzamiento"
 
 
-#: src/routes/index.ts:167 src/views/preference/Preference.vue:85
+#: src/routes/index.ts:184 src/views/preference/Preference.vue:85
 msgid "Preference"
 msgid "Preference"
 msgstr "Configuración"
 msgstr "Configuración"
 
 
@@ -1096,6 +1103,17 @@ msgstr "Recargando"
 msgid "Reloading nginx"
 msgid "Reloading nginx"
 msgstr "Recargando Nginx"
 msgstr "Recargando Nginx"
 
 
+#: src/views/certificate/RenewCert.vue:43
+#: src/views/certificate/RenewCert.vue:47
+#, fuzzy
+msgid "Renew Certificate"
+msgstr "Cambiar Certificado"
+
+#: src/views/certificate/RenewCert.vue:25
+#, fuzzy
+msgid "Renew successfully"
+msgstr "Habilitado con éxito"
+
 #: src/language/constants.ts:35
 #: src/language/constants.ts:35
 msgid "Requested with wrong parameters"
 msgid "Requested with wrong parameters"
 msgstr "Pedido con parámetros incorrectos"
 msgstr "Pedido con parámetros incorrectos"
@@ -1120,8 +1138,9 @@ msgstr "Modo de ejecución"
 msgid "Running"
 msgid "Running"
 msgstr "Corriendo"
 msgstr "Corriendo"
 
 
-#: src/components/ChatGPT/ChatGPT.vue:259 src/views/config/ConfigEdit.vue:98
-#: src/views/domain/DomainEdit.vue:268
+#: src/components/ChatGPT/ChatGPT.vue:259
+#: src/views/certificate/CertificateEditor.vue:175
+#: src/views/config/ConfigEdit.vue:98 src/views/domain/DomainEdit.vue:268
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:111
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:111
 #: src/views/preference/Preference.vue:113
 #: src/views/preference/Preference.vue:113
 msgid "Save"
 msgid "Save"
@@ -1137,6 +1156,7 @@ msgid "Save error %{msg}"
 msgstr "Error al guardar %{msg}"
 msgstr "Error al guardar %{msg}"
 
 
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:42
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:42
+#: src/views/certificate/CertificateEditor.vue:46
 #: src/views/preference/Preference.vue:58
 #: src/views/preference/Preference.vue:58
 msgid "Save successfully"
 msgid "Save successfully"
 msgstr "Guardado con éxito"
 msgstr "Guardado con éxito"
@@ -1176,24 +1196,34 @@ msgstr "Error del servidor"
 msgid "Server Info"
 msgid "Server Info"
 msgstr "Información del servidor"
 msgstr "Información del servidor"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:165
+#: src/views/domain/cert/components/ObtainCert.vue:115
 msgid "server_name not found in directives"
 msgid "server_name not found in directives"
 msgstr "No se encuentra server_name en las directivas"
 msgstr "No se encuentra server_name en las directivas"
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:27
+#: src/views/domain/cert/components/AutoCertStepOne.vue:29
 #: src/views/domain/DomainAdd.vue:119
 #: src/views/domain/DomainAdd.vue:119
 msgid "server_name parameter is required"
 msgid "server_name parameter is required"
 msgstr "Se requiere el parámetro server_name"
 msgstr "Se requiere el parámetro server_name"
 
 
+#: src/language/constants.ts:15
+#, fuzzy
+msgid "Setting DNS01 challenge provider"
+msgstr "Usando el proveedor de desafíos DNS01"
+
 #: src/language/constants.ts:16
 #: src/language/constants.ts:16
 msgid "Setting environment variables"
 msgid "Setting environment variables"
 msgstr "Configuración de variables de entorno"
 msgstr "Configuración de variables de entorno"
 
 
+#: src/language/constants.ts:14
+#, fuzzy
+msgid "Setting HTTP01 challenge provider"
+msgstr "Usando el proveedor de desafíos HTTP01"
+
 #: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:54
 #: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:54
 msgid "Single Directive"
 msgid "Single Directive"
 msgstr "Directiva de una sola línea"
 msgstr "Directiva de una sola línea"
 
 
-#: src/routes/index.ts:142
+#: src/routes/index.ts:159
 msgid "Site Logs"
 msgid "Site Logs"
 msgstr "Registros del sitio"
 msgstr "Registros del sitio"
 
 
@@ -1201,21 +1231,21 @@ msgstr "Registros del sitio"
 msgid "Sites List"
 msgid "Sites List"
 msgstr "Lista de sitios"
 msgstr "Lista de sitios"
 
 
-#: src/views/certificate/Certificate.vue:164
+#: src/views/certificate/CertificateEditor.vue:135
 #, fuzzy
 #, fuzzy
 msgid "SSL Certificate Content"
 msgid "SSL Certificate Content"
 msgstr "Contenido de certificado SSL"
 msgstr "Contenido de certificado SSL"
 
 
-#: src/views/certificate/Certificate.vue:171
+#: src/views/certificate/CertificateEditor.vue:142
 #, fuzzy
 #, fuzzy
 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/Certificate.vue:73
+#: src/views/certificate/Certificate.vue:63
 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/Certificate.vue:65
+#: src/views/certificate/Certificate.vue:55
 msgid "SSL Certificate Path"
 msgid "SSL Certificate Path"
 msgstr "Ruta del certificado SSL"
 msgstr "Ruta del certificado SSL"
 
 
@@ -1228,7 +1258,8 @@ msgstr "Acceso"
 msgid "Stable"
 msgid "Stable"
 msgstr "Estable"
 msgstr "Estable"
 
 
-#: src/views/domain/DomainList.vue:25 src/views/environment/Environment.vue:78
+#: src/views/certificate/Certificate.vue:71 src/views/domain/DomainList.vue:25
+#: src/views/environment/Environment.vue:78
 msgid "Status"
 msgid "Status"
 msgstr "Estado"
 msgstr "Estado"
 
 
@@ -1257,7 +1288,7 @@ msgstr ""
 msgid "Switch to light theme"
 msgid "Switch to light theme"
 msgstr ""
 msgstr ""
 
 
-#: src/routes/index.ts:175
+#: src/routes/index.ts:192
 msgid "System"
 msgid "System"
 msgstr "Sistema"
 msgstr "Sistema"
 
 
@@ -1269,7 +1300,7 @@ msgstr "Tabla"
 msgid "Target"
 msgid "Target"
 msgstr "Objetivo"
 msgstr "Objetivo"
 
 
-#: src/routes/index.ts:120 src/views/pty/Terminal.vue:95
+#: src/routes/index.ts:137 src/views/pty/Terminal.vue:95
 msgid "Terminal"
 msgid "Terminal"
 msgstr "Terminal"
 msgstr "Terminal"
 
 
@@ -1277,7 +1308,7 @@ msgstr "Terminal"
 msgid "Terminal Start Command"
 msgid "Terminal Start Command"
 msgstr "Comando de inicio de terminal"
 msgstr "Comando de inicio de terminal"
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:47
+#: src/views/domain/cert/components/AutoCertStepOne.vue:50
 #, fuzzy
 #, fuzzy
 msgid ""
 msgid ""
 "The certificate for the domain will be checked 5 minutes, and will be "
 "The certificate for the domain will be checked 5 minutes, and will be "
@@ -1291,7 +1322,7 @@ msgid "The filename cannot contain the following characters: %{c}"
 msgstr ""
 msgstr ""
 "El nombre del archivo no puede contener los siguientes caracteres: %{c}"
 "El nombre del archivo no puede contener los siguientes caracteres: %{c}"
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:42
+#: src/views/domain/cert/components/AutoCertStepOne.vue:45
 #, fuzzy
 #, fuzzy
 msgid ""
 msgid ""
 "The server_name in the current configuration must be the domain name you "
 "The server_name in the current configuration must be the domain name you "
@@ -1304,11 +1335,15 @@ msgstr ""
 msgid "The username or password is incorrect"
 msgid "The username or password is incorrect"
 msgstr "El nombre de usuario o contraseña son incorrectos"
 msgstr "El nombre de usuario o contraseña son incorrectos"
 
 
-#: src/views/certificate/Certificate.vue:115
+#: src/views/certificate/CertificateEditor.vue:93
 #, fuzzy
 #, fuzzy
 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:83
+msgid "This certificate is managed by Nginx UI"
+msgstr ""
+
 #: src/components/StdDesign/StdDataEntry/StdFormItem.vue:31
 #: src/components/StdDesign/StdDataEntry/StdFormItem.vue:31
 msgid "This field should not be empty"
 msgid "This field should not be empty"
 msgstr "Este campo no debe estar vacío"
 msgstr "Este campo no debe estar vacío"
@@ -1325,11 +1360,10 @@ msgstr ""
 "de la autoridad al backend, y debemos guardar este archivo y volver a cargar "
 "de la autoridad al backend, y debemos guardar este archivo y volver a cargar "
 "Nginx. ¿Estás seguro de que quieres continuar?"
 "Nginx. ¿Estás seguro de que quieres continuar?"
 
 
-#: src/views/config/config.ts:14
+#: src/views/certificate/Certificate.vue:39 src/views/config/config.ts:14
 msgid "Type"
 msgid "Type"
 msgstr "Tipo"
 msgstr "Tipo"
 
 
-#: src/views/certificate/Certificate.vue:81
 #: src/views/certificate/DNSCredential.vue:26 src/views/config/config.ts:29
 #: src/views/certificate/DNSCredential.vue:26 src/views/config/config.ts:29
 #: src/views/config/ConfigEdit.vue:123
 #: src/views/config/ConfigEdit.vue:123
 #: src/views/domain/components/RightSettings.vue:84
 #: src/views/domain/components/RightSettings.vue:84
@@ -1342,7 +1376,7 @@ msgstr "Actualizado a"
 msgid "Updated successfully"
 msgid "Updated successfully"
 msgstr "Actualización exitosa"
 msgstr "Actualización exitosa"
 
 
-#: src/routes/index.ts:186 src/views/system/Upgrade.vue:143
+#: src/routes/index.ts:203 src/views/system/Upgrade.vue:143
 #: src/views/system/Upgrade.vue:235
 #: src/views/system/Upgrade.vue:235
 msgid "Upgrade"
 msgid "Upgrade"
 msgstr "Actualizar"
 msgstr "Actualizar"
@@ -1375,20 +1409,16 @@ msgstr "Nombre de usuario"
 msgid "Username (*)"
 msgid "Username (*)"
 msgstr "Nombre de usuario (*)"
 msgstr "Nombre de usuario (*)"
 
 
-#: src/language/constants.ts:15
-msgid "Using DNS01 challenge provider"
-msgstr "Usando el proveedor de desafíos DNS01"
-
-#: src/language/constants.ts:14
-msgid "Using HTTP01 challenge provider"
-msgstr "Usando el proveedor de desafíos HTTP01"
+#: src/views/certificate/Certificate.vue:80
+msgid "Valid"
+msgstr ""
 
 
 #: src/views/domain/ngx_conf/config_template/ConfigTemplate.vue:101
 #: src/views/domain/ngx_conf/config_template/ConfigTemplate.vue:101
 msgid "View"
 msgid "View"
 msgstr "Ver"
 msgstr "Ver"
 
 
 #: src/views/config/InspectConfig.vue:36
 #: src/views/config/InspectConfig.vue:36
-#: src/views/domain/cert/components/AutoCertStepOne.vue:21
+#: src/views/domain/cert/components/AutoCertStepOne.vue:23
 #: src/views/domain/DomainAdd.vue:114
 #: src/views/domain/DomainAdd.vue:114
 msgid "Warning"
 msgid "Warning"
 msgstr "Advertencia"
 msgstr "Advertencia"
@@ -1399,7 +1429,7 @@ msgid ""
 "ownership verification."
 "ownership verification."
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:208
+#: src/views/domain/cert/components/ObtainCert.vue:147
 msgid ""
 msgid ""
 "We will remove the HTTPChallenge configuration from this file and reload the "
 "We will remove the HTTPChallenge configuration from this file and reload the "
 "Nginx. Are you sure you want to continue?"
 "Nginx. Are you sure you want to continue?"
@@ -1433,6 +1463,21 @@ msgstr "Estás usando la última versión"
 msgid "You can check Nginx UI upgrade at this page."
 msgid "You can check Nginx UI upgrade at this page."
 msgstr "Puede consultar la actualización de Nginx UI en esta página."
 msgstr "Puede consultar la actualización de Nginx UI en esta página."
 
 
+#, fuzzy
+#~ msgid "Renew certificate"
+#~ msgstr "Obtener certificado"
+
+#, fuzzy
+#~ msgid "Auto Cert is enabled"
+#~ msgstr "Certificado automático"
+
+#, fuzzy
+#~ msgid "Auto Cert Log"
+#~ msgstr "Registro del Certificado automático"
+
+#~ msgid "Config Name"
+#~ msgstr "Nombre de la configuración"
+
 #~ msgid "Auto cert is enabled, please do not modify this certification."
 #~ msgid "Auto cert is enabled, please do not modify this certification."
 #~ msgstr ""
 #~ msgstr ""
 #~ "Está habilitado el Certificado automático, por favor no modifique esta "
 #~ "Está habilitado el Certificado automático, por favor no modifique esta "

+ 126 - 81
app/src/language/fr_FR/app.po

@@ -11,15 +11,15 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Content-Transfer-Encoding: 8bit\n"
 "X-Generator: Poedit 3.3\n"
 "X-Generator: Poedit 3.3\n"
 
 
-#: src/routes/index.ts:182
+#: src/routes/index.ts:199
 msgid "About"
 msgid "About"
 msgstr "À propos"
 msgstr "À propos"
 
 
-#: src/routes/index.ts:134 src/views/domain/ngx_conf/LogEntry.vue:78
+#: src/routes/index.ts:151 src/views/domain/ngx_conf/LogEntry.vue:78
 msgid "Access Logs"
 msgid "Access Logs"
 msgstr "Journaux d'accès"
 msgstr "Journaux d'accès"
 
 
-#: src/views/certificate/Certificate.vue:87
+#: src/views/certificate/Certificate.vue:96
 #: src/views/certificate/DNSCredential.vue:32 src/views/config/config.ts:36
 #: src/views/certificate/DNSCredential.vue:32 src/views/config/config.ts:36
 #: src/views/domain/DomainList.vue:50 src/views/environment/Environment.vue:105
 #: src/views/domain/DomainList.vue:50 src/views/environment/Environment.vue:105
 #: src/views/user/User.vue:46
 #: src/views/user/User.vue:46
@@ -33,6 +33,12 @@ msgstr "Action"
 msgid "Add"
 msgid "Add"
 msgstr "Ajouter"
 msgstr "Ajouter"
 
 
+#: src/routes/index.ts:122 src/views/certificate/Certificate.vue:115
+#: src/views/certificate/CertificateEditor.vue:76
+#, fuzzy
+msgid "Add Certificate"
+msgstr "État du certificat"
+
 #: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:98
 #: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:98
 msgid "Add Directive Below"
 msgid "Add Directive Below"
 msgstr "Ajouter une directive"
 msgstr "Ajouter une directive"
@@ -103,33 +109,23 @@ msgstr ""
 msgid "Author"
 msgid "Author"
 msgstr "Autheur"
 msgstr "Autheur"
 
 
-#: src/views/certificate/Certificate.vue:46
 #: src/views/domain/cert/ChangeCert.vue:37
 #: src/views/domain/cert/ChangeCert.vue:37
 msgid "Auto Cert"
 msgid "Auto Cert"
 msgstr "Auto Cert"
 msgstr "Auto Cert"
 
 
-#: src/views/certificate/Certificate.vue:105
-#, fuzzy
-msgid "Auto Cert is enabled"
-msgstr "Auto Cert"
-
-#: src/views/certificate/Certificate.vue:135
-#, fuzzy
-msgid "Auto Cert Log"
-msgstr "Journal Auto-Cert"
-
 #: src/views/nginx_log/NginxLog.vue:149
 #: src/views/nginx_log/NginxLog.vue:149
 msgid "Auto Refresh"
 msgid "Auto Refresh"
 msgstr "Actualisation automatique"
 msgstr "Actualisation automatique"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:126
+#: src/views/domain/cert/components/ObtainCert.vue:76
 msgid "Auto-renewal disabled for %{name}"
 msgid "Auto-renewal disabled for %{name}"
 msgstr "Renouvellement automatique désactivé pour %{name}"
 msgstr "Renouvellement automatique désactivé pour %{name}"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:119
+#: src/views/domain/cert/components/ObtainCert.vue:69
 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/CertificateEditor.vue:168
 #: src/views/config/Config.vue:75 src/views/config/ConfigEdit.vue:89
 #: src/views/config/Config.vue:75 src/views/config/ConfigEdit.vue:89
 #: src/views/domain/DomainEdit.vue:261 src/views/nginx_log/NginxLog.vue:170
 #: src/views/domain/DomainEdit.vue:261 src/views/nginx_log/NginxLog.vue:170
 msgid "Back"
 msgid "Back"
@@ -171,7 +167,7 @@ msgstr ""
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:58
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:58
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:139
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:139
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:103
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:103
-#: src/views/domain/cert/components/ObtainCert.vue:211
+#: src/views/domain/cert/components/ObtainCert.vue:150
 #: src/views/domain/components/Deploy.vue:24
 #: src/views/domain/components/Deploy.vue:24
 #: src/views/domain/components/RightSettings.vue:52
 #: src/views/domain/components/RightSettings.vue:52
 #: src/views/domain/ngx_conf/NgxConfigEditor.vue:216
 #: src/views/domain/ngx_conf/NgxConfigEditor.vue:216
@@ -187,22 +183,22 @@ msgstr "Le certificat a expiré"
 msgid "Certificate is valid"
 msgid "Certificate is valid"
 msgstr "Le certificat est valide"
 msgstr "Le certificat est valide"
 
 
-#: src/views/certificate/Certificate.vue:145 src/views/domain/cert/Cert.vue:35
+#: src/views/certificate/CertificateEditor.vue:119
+#: src/views/domain/cert/Cert.vue:35
 msgid "Certificate Status"
 msgid "Certificate Status"
 msgstr "État du certificat"
 msgstr "État du certificat"
 
 
-#: src/routes/index.ts:100 src/views/certificate/Certificate.vue:96
+#: src/routes/index.ts:100 src/views/certificate/Certificate.vue:109
 #, fuzzy
 #, fuzzy
 msgid "Certificates"
 msgid "Certificates"
 msgstr "État du certificat"
 msgstr "État du certificat"
 
 
-#: src/routes/index.ts:108
+#: src/routes/index.ts:109
 #, fuzzy
 #, fuzzy
 msgid "Certificates List"
 msgid "Certificates List"
 msgstr "Liste des certifications"
 msgstr "Liste des certifications"
 
 
-#: src/views/certificate/Certificate.vue:150
-#: src/views/domain/cert/components/AutoCertStepOne.vue:63
+#: src/views/domain/cert/components/AutoCertStepOne.vue:65
 msgid "Challenge Method"
 msgid "Challenge Method"
 msgstr "Méthode de challenge"
 msgstr "Méthode de challenge"
 
 
@@ -242,10 +238,6 @@ msgstr "Effacer"
 msgid "Comments"
 msgid "Comments"
 msgstr "Commentaires"
 msgstr "Commentaires"
 
 
-#: src/views/certificate/Certificate.vue:41
-msgid "Config Name"
-msgstr "Nom de la config"
-
 #: src/views/domain/ngx_conf/config_template/ConfigTemplate.vue:82
 #: src/views/domain/ngx_conf/config_template/ConfigTemplate.vue:82
 msgid "Config Templates"
 msgid "Config Templates"
 msgstr "Modèles de configuration"
 msgstr "Modèles de configuration"
@@ -300,7 +292,7 @@ msgstr "Créé le"
 msgid "Creating client facilitates communication with the CA server"
 msgid "Creating client facilitates communication with the CA server"
 msgstr "La création du client facilite la communication avec le serveur CA"
 msgstr "La création du client facilite la communication avec le serveur CA"
 
 
-#: src/views/domain/cert/components/DNSChallenge.vue:89
+#: src/views/domain/cert/components/DNSChallenge.vue:105
 msgid "Credential"
 msgid "Credential"
 msgstr "Identifiant"
 msgstr "Identifiant"
 
 
@@ -385,11 +377,10 @@ msgstr "Directive"
 msgid "Disable"
 msgid "Disable"
 msgstr "Désactivé"
 msgstr "Désactivé"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:128
+#: src/views/domain/cert/components/ObtainCert.vue:78
 msgid "Disable auto-renewal failed for %{name}"
 msgid "Disable auto-renewal failed for %{name}"
 msgstr "La désactivation du renouvellement automatique a échoué pour %{name}"
 msgstr "La désactivation du renouvellement automatique a échoué pour %{name}"
 
 
-#: src/views/certificate/Certificate.vue:57
 #: src/views/domain/cert/ChangeCert.vue:48 src/views/domain/DomainEdit.vue:190
 #: src/views/domain/cert/ChangeCert.vue:48 src/views/domain/DomainEdit.vue:190
 #: src/views/domain/DomainList.vue:123
 #: src/views/domain/DomainList.vue:123
 msgid "Disabled"
 msgid "Disabled"
@@ -404,16 +395,16 @@ msgstr "Désactivé avec succès"
 msgid "Disk IO"
 msgid "Disk IO"
 msgstr "E/S disque"
 msgstr "E/S disque"
 
 
-#: src/routes/index.ts:113 src/views/certificate/DNSCredential.vue:39
+#: src/routes/index.ts:130 src/views/certificate/DNSCredential.vue:39
 msgid "DNS Credentials"
 msgid "DNS Credentials"
 msgstr "Identifiants DNS"
 msgstr "Identifiants DNS"
 
 
 #: src/views/certificate/DNSChallenge.vue:74
 #: src/views/certificate/DNSChallenge.vue:74
-#: src/views/domain/cert/components/DNSChallenge.vue:79
+#: src/views/domain/cert/components/DNSChallenge.vue:95
 msgid "DNS Provider"
 msgid "DNS Provider"
 msgstr "Fournisseur DNS"
 msgstr "Fournisseur DNS"
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:69
+#: src/views/domain/cert/components/AutoCertStepOne.vue:71
 msgid "DNS01"
 msgid "DNS01"
 msgstr "DNS01"
 msgstr "DNS01"
 
 
@@ -424,7 +415,7 @@ msgid_plural "Do you want to deploy this file to remote servers?"
 msgstr[0] "Voulez-vous supprimer ce serveur ?"
 msgstr[0] "Voulez-vous supprimer ce serveur ?"
 msgstr[1] "Voulez-vous supprimer ce serveur ?"
 msgstr[1] "Voulez-vous supprimer ce serveur ?"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:207
+#: src/views/domain/cert/components/ObtainCert.vue:146
 msgid "Do you want to disable auto-cert renewal?"
 msgid "Do you want to disable auto-cert renewal?"
 msgstr "Voulez-vous désactiver le renouvellement automatique des certificats ?"
 msgstr "Voulez-vous désactiver le renouvellement automatique des certificats ?"
 
 
@@ -448,7 +439,7 @@ msgstr "Voulez-vous supprimer ce serveur ?"
 msgid "Domain Config Created Successfully"
 msgid "Domain Config Created Successfully"
 msgstr "La configuration du domaine a été créée avec succès"
 msgstr "La configuration du domaine a été créée avec succès"
 
 
-#: src/views/certificate/Certificate.vue:125
+#: src/views/certificate/CertificateEditor.vue:103
 #, fuzzy
 #, fuzzy
 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 ""
@@ -521,7 +512,7 @@ msgstr ""
 msgid "Enable %{conf_name} in %{node_name} successfully"
 msgid "Enable %{conf_name} in %{node_name} successfully"
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:121
+#: src/views/domain/cert/components/ObtainCert.vue:71
 msgid "Enable auto-renewal failed for %{name}"
 msgid "Enable auto-renewal failed for %{name}"
 msgstr "Échec de l'activation du renouvellement automatique pour %{name}"
 msgstr "Échec de l'activation du renouvellement automatique pour %{name}"
 
 
@@ -538,7 +529,6 @@ msgstr "Activé avec succès"
 msgid "Enable TLS"
 msgid "Enable TLS"
 msgstr "Activer TLS"
 msgstr "Activer TLS"
 
 
-#: src/views/certificate/Certificate.vue:53
 #: src/views/domain/cert/ChangeCert.vue:44
 #: src/views/domain/cert/ChangeCert.vue:44
 #: src/views/domain/components/Deploy.vue:89
 #: src/views/domain/components/Deploy.vue:89
 #: src/views/domain/components/RightSettings.vue:75
 #: src/views/domain/components/RightSettings.vue:75
@@ -556,7 +546,7 @@ msgstr "Activé avec succès"
 msgid "Encrypt website with Let's Encrypt"
 msgid "Encrypt website with Let's Encrypt"
 msgstr "Crypter le site Web avec Let's Encrypt"
 msgstr "Crypter le site Web avec Let's Encrypt"
 
 
-#: src/routes/index.ts:151 src/views/environment/Environment.vue:113
+#: src/routes/index.ts:168 src/views/environment/Environment.vue:113
 msgid "Environment"
 msgid "Environment"
 msgstr ""
 msgstr ""
 
 
@@ -569,7 +559,7 @@ msgstr "Commentaires"
 msgid "Error"
 msgid "Error"
 msgstr "Erreur"
 msgstr "Erreur"
 
 
-#: src/routes/index.ts:138 src/views/domain/ngx_conf/LogEntry.vue:86
+#: src/routes/index.ts:155 src/views/domain/ngx_conf/LogEntry.vue:86
 msgid "Error Logs"
 msgid "Error Logs"
 msgstr "Journaux d'erreurs"
 msgstr "Journaux d'erreurs"
 
 
@@ -577,6 +567,10 @@ msgstr "Journaux d'erreurs"
 msgid "Executable Path"
 msgid "Executable Path"
 msgstr "Chemin exécutable"
 msgstr "Chemin exécutable"
 
 
+#: src/views/certificate/Certificate.vue:84
+msgid "Expired"
+msgstr ""
+
 #: src/views/domain/cert/CertInfo.vue:27
 #: src/views/domain/cert/CertInfo.vue:27
 #, fuzzy
 #, fuzzy
 msgid "Expired At: %{date}"
 msgid "Expired At: %{date}"
@@ -651,7 +645,7 @@ msgstr "Génération de clé privée pour l'enregistrement du compte"
 msgid "Get release information error"
 msgid "Get release information error"
 msgstr "Erreur d'obtention des informations sur la version"
 msgstr "Erreur d'obtention des informations sur la version"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:64
+#: src/views/domain/cert/components/ObtainCertLive.vue:68
 msgid "Getting the certificate, please wait..."
 msgid "Getting the certificate, please wait..."
 msgstr "Obtention du certificat, veuillez patienter..."
 msgstr "Obtention du certificat, veuillez patienter..."
 
 
@@ -692,7 +686,7 @@ msgstr "Host HTTP"
 msgid "HTTP Port"
 msgid "HTTP Port"
 msgstr "Port HTTP"
 msgstr "Port HTTP"
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:66
+#: src/views/domain/cert/components/AutoCertStepOne.vue:68
 msgid "HTTP01"
 msgid "HTTP01"
 msgstr "HTTP01"
 msgstr "HTTP01"
 
 
@@ -704,7 +698,7 @@ msgstr "Erreur du programme de mise à niveau initial du core"
 msgid "Initialing core upgrader"
 msgid "Initialing core upgrader"
 msgstr "Initialisation du programme de mise à niveau du core"
 msgstr "Initialisation du programme de mise à niveau du core"
 
 
-#: src/routes/index.ts:194 src/views/other/Install.vue:139
+#: src/routes/index.ts:211 src/views/other/Install.vue:139
 msgid "Install"
 msgid "Install"
 msgstr "Installer"
 msgstr "Installer"
 
 
@@ -766,7 +760,12 @@ msgstr "Localisation"
 msgid "Locations"
 msgid "Locations"
 msgstr "Localisations"
 msgstr "Localisations"
 
 
-#: src/routes/index.ts:200 src/views/other/Login.vue:147
+#: src/views/certificate/CertificateEditor.vue:156
+#, fuzzy
+msgid "Log"
+msgstr "Connexion"
+
+#: src/routes/index.ts:217 src/views/other/Login.vue:147
 msgid "Login"
 msgid "Login"
 msgstr "Connexion"
 msgstr "Connexion"
 
 
@@ -778,7 +777,7 @@ msgstr "Connexion réussie"
 msgid "Logout successful"
 msgid "Logout successful"
 msgstr "Déconnexion réussie"
 msgstr "Déconnexion réussie"
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:51
+#: src/views/domain/cert/components/AutoCertStepOne.vue:54
 #, fuzzy
 #, fuzzy
 msgid ""
 msgid ""
 "Make sure you have configured a reverse proxy for .well-known directory to "
 "Make sure you have configured a reverse proxy for .well-known directory to "
@@ -795,7 +794,7 @@ msgstr "Gérer les configurations"
 msgid "Manage Sites"
 msgid "Manage Sites"
 msgstr "Gérer les sites"
 msgstr "Gérer les sites"
 
 
-#: src/routes/index.ts:159 src/views/user/User.vue:53
+#: src/routes/index.ts:176 src/views/user/User.vue:53
 msgid "Manage Users"
 msgid "Manage Users"
 msgstr "Gérer les utilisateurs"
 msgstr "Gérer les utilisateurs"
 
 
@@ -810,10 +809,14 @@ msgstr "Mémoire et stockage"
 #: src/components/ChatGPT/ChatGPT.vue:256
 #: src/components/ChatGPT/ChatGPT.vue:256
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:137
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:137
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:336
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:336
-#: src/views/certificate/Certificate.vue:156
 msgid "Modify"
 msgid "Modify"
 msgstr "Modifier"
 msgstr "Modifier"
 
 
+#: src/routes/index.ts:114 src/views/certificate/CertificateEditor.vue:76
+#, fuzzy
+msgid "Modify Certificate"
+msgstr "État du certificat"
+
 #: src/views/domain/DomainAdd.vue:153
 #: src/views/domain/DomainAdd.vue:153
 msgid "Modify Config"
 msgid "Modify Config"
 msgstr "Modifier la configuration"
 msgstr "Modifier la configuration"
@@ -822,7 +825,7 @@ msgstr "Modifier la configuration"
 msgid "Multi-line Directive"
 msgid "Multi-line Directive"
 msgstr "Directive multiligne"
 msgstr "Directive multiligne"
 
 
-#: src/views/certificate/Certificate.vue:24
+#: src/views/certificate/Certificate.vue:22
 #: src/views/certificate/DNSCredential.vue:13 src/views/config/config.ts:9
 #: src/views/certificate/DNSCredential.vue:13 src/views/config/config.ts:9
 #: src/views/domain/cert/ChangeCert.vue:21
 #: src/views/domain/cert/ChangeCert.vue:21
 #: src/views/domain/components/RightSettings.vue:81
 #: src/views/domain/components/RightSettings.vue:81
@@ -851,7 +854,7 @@ msgstr "Envoi total réseau"
 msgid "New version released"
 msgid "New version released"
 msgstr "Nouvelle version publiée"
 msgstr "Nouvelle version publiée"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:281
+#: src/views/domain/cert/components/ObtainCert.vue:216
 #: src/views/domain/DomainAdd.vue:140
 #: src/views/domain/DomainAdd.vue:140
 msgid "Next"
 msgid "Next"
 msgstr "Suivant"
 msgstr "Suivant"
@@ -877,7 +880,7 @@ msgstr "Contrôle Nginx"
 msgid "Nginx Error Log Path"
 msgid "Nginx Error Log Path"
 msgstr "Chemin du journal des erreurs Nginx"
 msgstr "Chemin du journal des erreurs Nginx"
 
 
-#: src/routes/index.ts:128 src/views/nginx_log/NginxLog.vue:145
+#: src/routes/index.ts:145 src/views/nginx_log/NginxLog.vue:145
 msgid "Nginx Log"
 msgid "Nginx Log"
 msgstr "Journal Nginx"
 msgstr "Journal Nginx"
 
 
@@ -902,7 +905,11 @@ msgstr "Non"
 msgid "Node Secret"
 msgid "Node Secret"
 msgstr "Secret Jwt"
 msgstr "Secret Jwt"
 
 
-#: src/routes/index.ts:206 src/routes/index.ts:208
+#: src/views/certificate/Certificate.vue:90
+msgid "Not After"
+msgstr ""
+
+#: src/routes/index.ts:223 src/routes/index.ts:225
 msgid "Not Found"
 msgid "Not Found"
 msgstr "Introuvable"
 msgstr "Introuvable"
 
 
@@ -911,11 +918,11 @@ msgid "Not Valid Before: %{date}"
 msgstr "Non valide avant : %{date}"
 msgstr "Non valide avant : %{date}"
 
 
 #: src/views/certificate/DNSCredential.vue:48
 #: src/views/certificate/DNSCredential.vue:48
-#: src/views/domain/cert/components/AutoCertStepOne.vue:38
+#: src/views/domain/cert/components/AutoCertStepOne.vue:40
 msgid "Note"
 msgid "Note"
 msgstr "Note"
 msgstr "Note"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:252
+#: src/views/domain/cert/components/ObtainCert.vue:191
 msgid "Obtain certificate"
 msgid "Obtain certificate"
 msgstr "Obtenir un certificat"
 msgstr "Obtenir un certificat"
 
 
@@ -934,7 +941,7 @@ msgstr ""
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:140
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:140
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:346
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:346
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:104
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:104
-#: src/views/domain/cert/components/ObtainCert.vue:210
+#: src/views/domain/cert/components/ObtainCert.vue:149
 #: src/views/domain/components/Deploy.vue:23
 #: src/views/domain/components/Deploy.vue:23
 #: src/views/domain/components/RightSettings.vue:51
 #: src/views/domain/components/RightSettings.vue:51
 #: src/views/domain/DomainList.vue:144
 #: src/views/domain/DomainList.vue:144
@@ -1006,7 +1013,7 @@ msgid ""
 "provider."
 "provider."
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:55
+#: src/views/domain/cert/components/AutoCertStepOne.vue:58
 #, fuzzy
 #, fuzzy
 msgid ""
 msgid ""
 "Please first add credentials in Certification > DNS Credentials, and then "
 "Please first add credentials in Certification > DNS Credentials, and then "
@@ -1050,7 +1057,7 @@ msgstr ""
 msgid "Pre-release"
 msgid "Pre-release"
 msgstr ""
 msgstr ""
 
 
-#: src/routes/index.ts:167 src/views/preference/Preference.vue:85
+#: src/routes/index.ts:184 src/views/preference/Preference.vue:85
 msgid "Preference"
 msgid "Preference"
 msgstr "Préférence"
 msgstr "Préférence"
 
 
@@ -1116,6 +1123,17 @@ msgstr "Rechargement"
 msgid "Reloading nginx"
 msgid "Reloading nginx"
 msgstr "Rechargement de nginx"
 msgstr "Rechargement de nginx"
 
 
+#: src/views/certificate/RenewCert.vue:43
+#: src/views/certificate/RenewCert.vue:47
+#, fuzzy
+msgid "Renew Certificate"
+msgstr "Changer de certificat"
+
+#: src/views/certificate/RenewCert.vue:25
+#, fuzzy
+msgid "Renew successfully"
+msgstr "Activé avec succès"
+
 #: src/language/constants.ts:35
 #: src/language/constants.ts:35
 msgid "Requested with wrong parameters"
 msgid "Requested with wrong parameters"
 msgstr ""
 msgstr ""
@@ -1140,8 +1158,9 @@ msgstr "Mode d'exécution"
 msgid "Running"
 msgid "Running"
 msgstr "En cours d'éxécution"
 msgstr "En cours d'éxécution"
 
 
-#: src/components/ChatGPT/ChatGPT.vue:259 src/views/config/ConfigEdit.vue:98
-#: src/views/domain/DomainEdit.vue:268
+#: src/components/ChatGPT/ChatGPT.vue:259
+#: src/views/certificate/CertificateEditor.vue:175
+#: src/views/config/ConfigEdit.vue:98 src/views/domain/DomainEdit.vue:268
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:111
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:111
 #: src/views/preference/Preference.vue:113
 #: src/views/preference/Preference.vue:113
 msgid "Save"
 msgid "Save"
@@ -1157,6 +1176,7 @@ msgid "Save error %{msg}"
 msgstr "Enregistrer l'erreur %{msg}"
 msgstr "Enregistrer l'erreur %{msg}"
 
 
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:42
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:42
+#: src/views/certificate/CertificateEditor.vue:46
 #: src/views/preference/Preference.vue:58
 #: src/views/preference/Preference.vue:58
 msgid "Save successfully"
 msgid "Save successfully"
 msgstr "Sauvegarde réussie"
 msgstr "Sauvegarde réussie"
@@ -1196,24 +1216,34 @@ msgstr "Erreur du serveur"
 msgid "Server Info"
 msgid "Server Info"
 msgstr "Informations sur le serveur"
 msgstr "Informations sur le serveur"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:165
+#: src/views/domain/cert/components/ObtainCert.vue:115
 msgid "server_name not found in directives"
 msgid "server_name not found in directives"
 msgstr "server_name introuvable dans les directives"
 msgstr "server_name introuvable dans les directives"
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:27
+#: src/views/domain/cert/components/AutoCertStepOne.vue:29
 #: src/views/domain/DomainAdd.vue:119
 #: src/views/domain/DomainAdd.vue:119
 msgid "server_name parameter is required"
 msgid "server_name parameter is required"
 msgstr "Le paramètre server_name est obligatoire"
 msgstr "Le paramètre server_name est obligatoire"
 
 
+#: src/language/constants.ts:15
+#, fuzzy
+msgid "Setting DNS01 challenge provider"
+msgstr "Utilisation du fournisseur de challenge DNS01"
+
 #: src/language/constants.ts:16
 #: src/language/constants.ts:16
 msgid "Setting environment variables"
 msgid "Setting environment variables"
 msgstr "Définition des variables d'environnement"
 msgstr "Définition des variables d'environnement"
 
 
+#: src/language/constants.ts:14
+#, fuzzy
+msgid "Setting HTTP01 challenge provider"
+msgstr "Utilisation du fournisseur de challenge HTTP01"
+
 #: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:54
 #: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:54
 msgid "Single Directive"
 msgid "Single Directive"
 msgstr "Directive unique"
 msgstr "Directive unique"
 
 
-#: src/routes/index.ts:142
+#: src/routes/index.ts:159
 msgid "Site Logs"
 msgid "Site Logs"
 msgstr "Journaux du site"
 msgstr "Journaux du site"
 
 
@@ -1221,21 +1251,21 @@ msgstr "Journaux du site"
 msgid "Sites List"
 msgid "Sites List"
 msgstr "Liste des sites"
 msgstr "Liste des sites"
 
 
-#: src/views/certificate/Certificate.vue:164
+#: src/views/certificate/CertificateEditor.vue:135
 #, fuzzy
 #, fuzzy
 msgid "SSL Certificate Content"
 msgid "SSL Certificate Content"
 msgstr "Contenu de la certification SSL"
 msgstr "Contenu de la certification SSL"
 
 
-#: src/views/certificate/Certificate.vue:171
+#: src/views/certificate/CertificateEditor.vue:142
 #, fuzzy
 #, fuzzy
 msgid "SSL Certificate Key Content"
 msgid "SSL Certificate Key Content"
 msgstr "Contenu de la clé de certification SSL"
 msgstr "Contenu de la clé de certification SSL"
 
 
-#: src/views/certificate/Certificate.vue:73
+#: src/views/certificate/Certificate.vue:63
 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/Certificate.vue:65
+#: src/views/certificate/Certificate.vue:55
 msgid "SSL Certificate Path"
 msgid "SSL Certificate Path"
 msgstr "Chemin du certificat SSL"
 msgstr "Chemin du certificat SSL"
 
 
@@ -1249,7 +1279,8 @@ msgstr "Connexion"
 msgid "Stable"
 msgid "Stable"
 msgstr "Tableau"
 msgstr "Tableau"
 
 
-#: src/views/domain/DomainList.vue:25 src/views/environment/Environment.vue:78
+#: src/views/certificate/Certificate.vue:71 src/views/domain/DomainList.vue:25
+#: src/views/environment/Environment.vue:78
 msgid "Status"
 msgid "Status"
 msgstr "Statut"
 msgstr "Statut"
 
 
@@ -1279,7 +1310,7 @@ msgstr ""
 msgid "Switch to light theme"
 msgid "Switch to light theme"
 msgstr ""
 msgstr ""
 
 
-#: src/routes/index.ts:175
+#: src/routes/index.ts:192
 msgid "System"
 msgid "System"
 msgstr "Système"
 msgstr "Système"
 
 
@@ -1291,7 +1322,7 @@ msgstr "Tableau"
 msgid "Target"
 msgid "Target"
 msgstr ""
 msgstr ""
 
 
-#: src/routes/index.ts:120 src/views/pty/Terminal.vue:95
+#: src/routes/index.ts:137 src/views/pty/Terminal.vue:95
 msgid "Terminal"
 msgid "Terminal"
 msgstr "Terminal"
 msgstr "Terminal"
 
 
@@ -1299,7 +1330,7 @@ msgstr "Terminal"
 msgid "Terminal Start Command"
 msgid "Terminal Start Command"
 msgstr "Commande de démarrage du terminal"
 msgstr "Commande de démarrage du terminal"
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:47
+#: src/views/domain/cert/components/AutoCertStepOne.vue:50
 #, fuzzy
 #, fuzzy
 msgid ""
 msgid ""
 "The certificate for the domain will be checked 5 minutes, and will be "
 "The certificate for the domain will be checked 5 minutes, and will be "
@@ -1312,7 +1343,7 @@ msgstr ""
 msgid "The filename cannot contain the following characters: %{c}"
 msgid "The filename cannot contain the following characters: %{c}"
 msgstr "Le nom de fichier ne peut pas contenir les caractères suivants : %{c}"
 msgstr "Le nom de fichier ne peut pas contenir les caractères suivants : %{c}"
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:42
+#: src/views/domain/cert/components/AutoCertStepOne.vue:45
 #, fuzzy
 #, fuzzy
 msgid ""
 msgid ""
 "The server_name in the current configuration must be the domain name you "
 "The server_name in the current configuration must be the domain name you "
@@ -1326,13 +1357,17 @@ msgstr ""
 msgid "The username or password is incorrect"
 msgid "The username or password is incorrect"
 msgstr "Le pseudo ou mot de passe est incorect"
 msgstr "Le pseudo ou mot de passe est incorect"
 
 
-#: src/views/certificate/Certificate.vue:115
+#: src/views/certificate/CertificateEditor.vue:93
 #, fuzzy
 #, fuzzy
 msgid "This Auto Cert item is invalid, please remove it."
 msgid "This Auto Cert item is invalid, please remove it."
 msgstr ""
 msgstr ""
 "Cet élément de certification automatique n'est pas valide, veuillez le "
 "Cet élément de certification automatique n'est pas valide, veuillez le "
 "supprimer."
 "supprimer."
 
 
+#: src/views/certificate/CertificateEditor.vue:83
+msgid "This certificate is managed by Nginx UI"
+msgstr ""
+
 #: src/components/StdDesign/StdDataEntry/StdFormItem.vue:31
 #: src/components/StdDesign/StdDataEntry/StdFormItem.vue:31
 msgid "This field should not be empty"
 msgid "This field should not be empty"
 msgstr ""
 msgstr ""
@@ -1349,11 +1384,10 @@ msgstr ""
 "transmettre la demande de l'autorité au backend, et nous devons enregistrer "
 "transmettre la demande de l'autorité au backend, et nous devons enregistrer "
 "ce fichier et recharger le Nginx. Êtes-vous sûr de vouloir continuer?"
 "ce fichier et recharger le Nginx. Êtes-vous sûr de vouloir continuer?"
 
 
-#: src/views/config/config.ts:14
+#: src/views/certificate/Certificate.vue:39 src/views/config/config.ts:14
 msgid "Type"
 msgid "Type"
 msgstr "Type"
 msgstr "Type"
 
 
-#: src/views/certificate/Certificate.vue:81
 #: src/views/certificate/DNSCredential.vue:26 src/views/config/config.ts:29
 #: src/views/certificate/DNSCredential.vue:26 src/views/config/config.ts:29
 #: src/views/config/ConfigEdit.vue:123
 #: src/views/config/ConfigEdit.vue:123
 #: src/views/domain/components/RightSettings.vue:84
 #: src/views/domain/components/RightSettings.vue:84
@@ -1366,7 +1400,7 @@ msgstr "Mis à jour le"
 msgid "Updated successfully"
 msgid "Updated successfully"
 msgstr "Mis à jour avec succés"
 msgstr "Mis à jour avec succés"
 
 
-#: src/routes/index.ts:186 src/views/system/Upgrade.vue:143
+#: src/routes/index.ts:203 src/views/system/Upgrade.vue:143
 #: src/views/system/Upgrade.vue:235
 #: src/views/system/Upgrade.vue:235
 msgid "Upgrade"
 msgid "Upgrade"
 msgstr "Mettre à niveau"
 msgstr "Mettre à niveau"
@@ -1400,20 +1434,16 @@ msgstr "Nom d'utilisateur"
 msgid "Username (*)"
 msgid "Username (*)"
 msgstr "Nom d'utilisateur (*)"
 msgstr "Nom d'utilisateur (*)"
 
 
-#: src/language/constants.ts:15
-msgid "Using DNS01 challenge provider"
-msgstr "Utilisation du fournisseur de challenge DNS01"
-
-#: src/language/constants.ts:14
-msgid "Using HTTP01 challenge provider"
-msgstr "Utilisation du fournisseur de challenge HTTP01"
+#: src/views/certificate/Certificate.vue:80
+msgid "Valid"
+msgstr ""
 
 
 #: src/views/domain/ngx_conf/config_template/ConfigTemplate.vue:101
 #: src/views/domain/ngx_conf/config_template/ConfigTemplate.vue:101
 msgid "View"
 msgid "View"
 msgstr "Voir"
 msgstr "Voir"
 
 
 #: src/views/config/InspectConfig.vue:36
 #: src/views/config/InspectConfig.vue:36
-#: src/views/domain/cert/components/AutoCertStepOne.vue:21
+#: src/views/domain/cert/components/AutoCertStepOne.vue:23
 #: src/views/domain/DomainAdd.vue:114
 #: src/views/domain/DomainAdd.vue:114
 msgid "Warning"
 msgid "Warning"
 msgstr "Avertissement"
 msgstr "Avertissement"
@@ -1424,7 +1454,7 @@ msgid ""
 "ownership verification."
 "ownership verification."
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:208
+#: src/views/domain/cert/components/ObtainCert.vue:147
 msgid ""
 msgid ""
 "We will remove the HTTPChallenge configuration from this file and reload the "
 "We will remove the HTTPChallenge configuration from this file and reload the "
 "Nginx. Are you sure you want to continue?"
 "Nginx. Are you sure you want to continue?"
@@ -1458,6 +1488,21 @@ msgstr "Vous utilisez la dernière version"
 msgid "You can check Nginx UI upgrade at this page."
 msgid "You can check Nginx UI upgrade at this page."
 msgstr "Vous pouvez vérifier la mise à niveau de Nginx UI sur cette page."
 msgstr "Vous pouvez vérifier la mise à niveau de Nginx UI sur cette page."
 
 
+#, fuzzy
+#~ msgid "Renew certificate"
+#~ msgstr "Obtenir un certificat"
+
+#, fuzzy
+#~ msgid "Auto Cert is enabled"
+#~ msgstr "Auto Cert"
+
+#, fuzzy
+#~ msgid "Auto Cert Log"
+#~ msgstr "Journal Auto-Cert"
+
+#~ msgid "Config Name"
+#~ msgstr "Nom de la config"
+
 #~ msgid "Auto cert is enabled, please do not modify this certification."
 #~ msgid "Auto cert is enabled, please do not modify this certification."
 #~ msgstr ""
 #~ msgstr ""
 #~ "La certification automatique est activée, veuillez ne pas modifier cette "
 #~ "La certification automatique est activée, veuillez ne pas modifier cette "

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

@@ -2,16 +2,16 @@ msgid ""
 msgstr ""
 msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 
 
-#: src/routes/index.ts:182
+#: src/routes/index.ts:199
 msgid "About"
 msgid "About"
 msgstr ""
 msgstr ""
 
 
-#: src/routes/index.ts:134
+#: src/routes/index.ts:151
 #: src/views/domain/ngx_conf/LogEntry.vue:78
 #: src/views/domain/ngx_conf/LogEntry.vue:78
 msgid "Access Logs"
 msgid "Access Logs"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/Certificate.vue:87
+#: src/views/certificate/Certificate.vue:96
 #: src/views/certificate/DNSCredential.vue:32
 #: src/views/certificate/DNSCredential.vue:32
 #: src/views/config/config.ts:36
 #: src/views/config/config.ts:36
 #: src/views/domain/DomainList.vue:50
 #: src/views/domain/DomainList.vue:50
@@ -27,6 +27,12 @@ msgstr ""
 msgid "Add"
 msgid "Add"
 msgstr ""
 msgstr ""
 
 
+#: src/routes/index.ts:122
+#: src/views/certificate/Certificate.vue:115
+#: src/views/certificate/CertificateEditor.vue:76
+msgid "Add Certificate"
+msgstr ""
+
 #: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:98
 #: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:98
 msgid "Add Directive Below"
 msgid "Add Directive Below"
 msgstr ""
 msgstr ""
@@ -95,31 +101,23 @@ msgstr ""
 msgid "Author"
 msgid "Author"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/Certificate.vue:46
 #: src/views/domain/cert/ChangeCert.vue:37
 #: src/views/domain/cert/ChangeCert.vue:37
 msgid "Auto Cert"
 msgid "Auto Cert"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/Certificate.vue:105
-msgid "Auto Cert is enabled"
-msgstr ""
-
-#: src/views/certificate/Certificate.vue:135
-msgid "Auto Cert Log"
-msgstr ""
-
 #: src/views/nginx_log/NginxLog.vue:149
 #: src/views/nginx_log/NginxLog.vue:149
 msgid "Auto Refresh"
 msgid "Auto Refresh"
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:126
+#: src/views/domain/cert/components/ObtainCert.vue:76
 msgid "Auto-renewal disabled for %{name}"
 msgid "Auto-renewal disabled for %{name}"
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:119
+#: src/views/domain/cert/components/ObtainCert.vue:69
 msgid "Auto-renewal enabled for %{name}"
 msgid "Auto-renewal enabled for %{name}"
 msgstr ""
 msgstr ""
 
 
+#: src/views/certificate/CertificateEditor.vue:168
 #: src/views/config/Config.vue:75
 #: src/views/config/Config.vue:75
 #: src/views/config/ConfigEdit.vue:89
 #: src/views/config/ConfigEdit.vue:89
 #: src/views/domain/DomainEdit.vue:261
 #: src/views/domain/DomainEdit.vue:261
@@ -162,7 +160,7 @@ msgstr ""
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:58
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:58
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:139
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:139
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:103
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:103
-#: src/views/domain/cert/components/ObtainCert.vue:211
+#: src/views/domain/cert/components/ObtainCert.vue:150
 #: src/views/domain/components/Deploy.vue:24
 #: src/views/domain/components/Deploy.vue:24
 #: src/views/domain/components/RightSettings.vue:52
 #: src/views/domain/components/RightSettings.vue:52
 #: src/views/domain/ngx_conf/NgxConfigEditor.vue:216
 #: src/views/domain/ngx_conf/NgxConfigEditor.vue:216
@@ -178,22 +176,21 @@ msgstr ""
 msgid "Certificate is valid"
 msgid "Certificate is valid"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/Certificate.vue:145
+#: src/views/certificate/CertificateEditor.vue:119
 #: src/views/domain/cert/Cert.vue:35
 #: src/views/domain/cert/Cert.vue:35
 msgid "Certificate Status"
 msgid "Certificate Status"
 msgstr ""
 msgstr ""
 
 
 #: src/routes/index.ts:100
 #: src/routes/index.ts:100
-#: src/views/certificate/Certificate.vue:96
+#: src/views/certificate/Certificate.vue:109
 msgid "Certificates"
 msgid "Certificates"
 msgstr ""
 msgstr ""
 
 
-#: src/routes/index.ts:108
+#: src/routes/index.ts:109
 msgid "Certificates List"
 msgid "Certificates List"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/Certificate.vue:150
-#: src/views/domain/cert/components/AutoCertStepOne.vue:63
+#: src/views/domain/cert/components/AutoCertStepOne.vue:65
 msgid "Challenge Method"
 msgid "Challenge Method"
 msgstr ""
 msgstr ""
 
 
@@ -233,10 +230,6 @@ msgstr ""
 msgid "Comments"
 msgid "Comments"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/Certificate.vue:41
-msgid "Config Name"
-msgstr ""
-
 #: src/views/domain/ngx_conf/config_template/ConfigTemplate.vue:82
 #: src/views/domain/ngx_conf/config_template/ConfigTemplate.vue:82
 msgid "Config Templates"
 msgid "Config Templates"
 msgstr ""
 msgstr ""
@@ -291,7 +284,7 @@ msgstr ""
 msgid "Creating client facilitates communication with the CA server"
 msgid "Creating client facilitates communication with the CA server"
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/cert/components/DNSChallenge.vue:89
+#: src/views/domain/cert/components/DNSChallenge.vue:105
 msgid "Credential"
 msgid "Credential"
 msgstr ""
 msgstr ""
 
 
@@ -372,11 +365,10 @@ msgstr ""
 msgid "Disable"
 msgid "Disable"
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:128
+#: src/views/domain/cert/components/ObtainCert.vue:78
 msgid "Disable auto-renewal failed for %{name}"
 msgid "Disable auto-renewal failed for %{name}"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/Certificate.vue:57
 #: src/views/domain/cert/ChangeCert.vue:48
 #: src/views/domain/cert/ChangeCert.vue:48
 #: src/views/domain/DomainEdit.vue:190
 #: src/views/domain/DomainEdit.vue:190
 #: src/views/domain/DomainList.vue:123
 #: src/views/domain/DomainList.vue:123
@@ -392,17 +384,17 @@ msgstr ""
 msgid "Disk IO"
 msgid "Disk IO"
 msgstr ""
 msgstr ""
 
 
-#: src/routes/index.ts:113
+#: src/routes/index.ts:130
 #: src/views/certificate/DNSCredential.vue:39
 #: src/views/certificate/DNSCredential.vue:39
 msgid "DNS Credentials"
 msgid "DNS Credentials"
 msgstr ""
 msgstr ""
 
 
 #: src/views/certificate/DNSChallenge.vue:74
 #: src/views/certificate/DNSChallenge.vue:74
-#: src/views/domain/cert/components/DNSChallenge.vue:79
+#: src/views/domain/cert/components/DNSChallenge.vue:95
 msgid "DNS Provider"
 msgid "DNS Provider"
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:69
+#: src/views/domain/cert/components/AutoCertStepOne.vue:71
 msgid "DNS01"
 msgid "DNS01"
 msgstr ""
 msgstr ""
 
 
@@ -412,7 +404,7 @@ msgid_plural "Do you want to deploy this file to remote servers?"
 msgstr[0] ""
 msgstr[0] ""
 msgstr[1] ""
 msgstr[1] ""
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:207
+#: src/views/domain/cert/components/ObtainCert.vue:146
 msgid "Do you want to disable auto-cert renewal?"
 msgid "Do you want to disable auto-cert renewal?"
 msgstr ""
 msgstr ""
 
 
@@ -436,7 +428,7 @@ msgstr ""
 msgid "Domain Config Created Successfully"
 msgid "Domain Config Created Successfully"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/Certificate.vue:125
+#: src/views/certificate/CertificateEditor.vue:103
 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 ""
 
 
@@ -502,7 +494,7 @@ msgstr ""
 msgid "Enable %{conf_name} in %{node_name} successfully"
 msgid "Enable %{conf_name} in %{node_name} successfully"
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:121
+#: src/views/domain/cert/components/ObtainCert.vue:71
 msgid "Enable auto-renewal failed for %{name}"
 msgid "Enable auto-renewal failed for %{name}"
 msgstr ""
 msgstr ""
 
 
@@ -518,7 +510,6 @@ msgstr ""
 msgid "Enable TLS"
 msgid "Enable TLS"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/Certificate.vue:53
 #: src/views/domain/cert/ChangeCert.vue:44
 #: src/views/domain/cert/ChangeCert.vue:44
 #: src/views/domain/components/Deploy.vue:89
 #: src/views/domain/components/Deploy.vue:89
 #: src/views/domain/components/RightSettings.vue:75
 #: src/views/domain/components/RightSettings.vue:75
@@ -538,7 +529,7 @@ msgstr ""
 msgid "Encrypt website with Let's Encrypt"
 msgid "Encrypt website with Let's Encrypt"
 msgstr ""
 msgstr ""
 
 
-#: src/routes/index.ts:151
+#: src/routes/index.ts:168
 #: src/views/environment/Environment.vue:113
 #: src/views/environment/Environment.vue:113
 msgid "Environment"
 msgid "Environment"
 msgstr ""
 msgstr ""
@@ -551,7 +542,7 @@ msgstr ""
 msgid "Error"
 msgid "Error"
 msgstr ""
 msgstr ""
 
 
-#: src/routes/index.ts:138
+#: src/routes/index.ts:155
 #: src/views/domain/ngx_conf/LogEntry.vue:86
 #: src/views/domain/ngx_conf/LogEntry.vue:86
 msgid "Error Logs"
 msgid "Error Logs"
 msgstr ""
 msgstr ""
@@ -560,6 +551,10 @@ msgstr ""
 msgid "Executable Path"
 msgid "Executable Path"
 msgstr ""
 msgstr ""
 
 
+#: src/views/certificate/Certificate.vue:84
+msgid "Expired"
+msgstr ""
+
 #: src/views/domain/cert/CertInfo.vue:27
 #: src/views/domain/cert/CertInfo.vue:27
 msgid "Expired At: %{date}"
 msgid "Expired At: %{date}"
 msgstr ""
 msgstr ""
@@ -632,7 +627,7 @@ msgstr ""
 msgid "Get release information error"
 msgid "Get release information error"
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:64
+#: src/views/domain/cert/components/ObtainCertLive.vue:68
 msgid "Getting the certificate, please wait..."
 msgid "Getting the certificate, please wait..."
 msgstr ""
 msgstr ""
 
 
@@ -672,7 +667,7 @@ msgstr ""
 msgid "HTTP Port"
 msgid "HTTP Port"
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:66
+#: src/views/domain/cert/components/AutoCertStepOne.vue:68
 msgid "HTTP01"
 msgid "HTTP01"
 msgstr ""
 msgstr ""
 
 
@@ -684,7 +679,7 @@ msgstr ""
 msgid "Initialing core upgrader"
 msgid "Initialing core upgrader"
 msgstr ""
 msgstr ""
 
 
-#: src/routes/index.ts:194
+#: src/routes/index.ts:211
 #: src/views/other/Install.vue:139
 #: src/views/other/Install.vue:139
 msgid "Install"
 msgid "Install"
 msgstr ""
 msgstr ""
@@ -742,7 +737,11 @@ msgstr ""
 msgid "Locations"
 msgid "Locations"
 msgstr ""
 msgstr ""
 
 
-#: src/routes/index.ts:200
+#: src/views/certificate/CertificateEditor.vue:156
+msgid "Log"
+msgstr ""
+
+#: src/routes/index.ts:217
 #: src/views/other/Login.vue:147
 #: src/views/other/Login.vue:147
 msgid "Login"
 msgid "Login"
 msgstr ""
 msgstr ""
@@ -756,7 +755,7 @@ msgstr ""
 msgid "Logout successful"
 msgid "Logout successful"
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:51
+#: src/views/domain/cert/components/AutoCertStepOne.vue:54
 msgid "Make sure you have configured a reverse proxy for .well-known directory to HTTPChallengePort before obtaining the certificate."
 msgid "Make sure you have configured a reverse proxy for .well-known directory to HTTPChallengePort before obtaining the certificate."
 msgstr ""
 msgstr ""
 
 
@@ -769,7 +768,7 @@ msgstr ""
 msgid "Manage Sites"
 msgid "Manage Sites"
 msgstr ""
 msgstr ""
 
 
-#: src/routes/index.ts:159
+#: src/routes/index.ts:176
 #: src/views/user/User.vue:53
 #: src/views/user/User.vue:53
 msgid "Manage Users"
 msgid "Manage Users"
 msgstr ""
 msgstr ""
@@ -785,10 +784,14 @@ msgstr ""
 #: src/components/ChatGPT/ChatGPT.vue:256
 #: src/components/ChatGPT/ChatGPT.vue:256
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:137
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:137
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:336
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:336
-#: src/views/certificate/Certificate.vue:156
 msgid "Modify"
 msgid "Modify"
 msgstr ""
 msgstr ""
 
 
+#: src/routes/index.ts:114
+#: src/views/certificate/CertificateEditor.vue:76
+msgid "Modify Certificate"
+msgstr ""
+
 #: src/views/domain/DomainAdd.vue:153
 #: src/views/domain/DomainAdd.vue:153
 msgid "Modify Config"
 msgid "Modify Config"
 msgstr ""
 msgstr ""
@@ -797,7 +800,7 @@ msgstr ""
 msgid "Multi-line Directive"
 msgid "Multi-line Directive"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/Certificate.vue:24
+#: src/views/certificate/Certificate.vue:22
 #: src/views/certificate/DNSCredential.vue:13
 #: src/views/certificate/DNSCredential.vue:13
 #: src/views/config/config.ts:9
 #: src/views/config/config.ts:9
 #: src/views/domain/cert/ChangeCert.vue:21
 #: src/views/domain/cert/ChangeCert.vue:21
@@ -828,7 +831,7 @@ msgstr ""
 msgid "New version released"
 msgid "New version released"
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:281
+#: src/views/domain/cert/components/ObtainCert.vue:216
 #: src/views/domain/DomainAdd.vue:140
 #: src/views/domain/DomainAdd.vue:140
 msgid "Next"
 msgid "Next"
 msgstr ""
 msgstr ""
@@ -853,7 +856,7 @@ msgstr ""
 msgid "Nginx Error Log Path"
 msgid "Nginx Error Log Path"
 msgstr ""
 msgstr ""
 
 
-#: src/routes/index.ts:128
+#: src/routes/index.ts:145
 #: src/views/nginx_log/NginxLog.vue:145
 #: src/views/nginx_log/NginxLog.vue:145
 msgid "Nginx Log"
 msgid "Nginx Log"
 msgstr ""
 msgstr ""
@@ -878,8 +881,12 @@ msgstr ""
 msgid "Node Secret"
 msgid "Node Secret"
 msgstr ""
 msgstr ""
 
 
-#: src/routes/index.ts:206
-#: src/routes/index.ts:208
+#: src/views/certificate/Certificate.vue:90
+msgid "Not After"
+msgstr ""
+
+#: src/routes/index.ts:223
+#: src/routes/index.ts:225
 msgid "Not Found"
 msgid "Not Found"
 msgstr ""
 msgstr ""
 
 
@@ -888,11 +895,11 @@ msgid "Not Valid Before: %{date}"
 msgstr ""
 msgstr ""
 
 
 #: src/views/certificate/DNSCredential.vue:48
 #: src/views/certificate/DNSCredential.vue:48
-#: src/views/domain/cert/components/AutoCertStepOne.vue:38
+#: src/views/domain/cert/components/AutoCertStepOne.vue:40
 msgid "Note"
 msgid "Note"
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:252
+#: src/views/domain/cert/components/ObtainCert.vue:191
 msgid "Obtain certificate"
 msgid "Obtain certificate"
 msgstr ""
 msgstr ""
 
 
@@ -911,7 +918,7 @@ msgstr ""
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:140
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:140
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:346
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:346
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:104
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:104
-#: src/views/domain/cert/components/ObtainCert.vue:210
+#: src/views/domain/cert/components/ObtainCert.vue:149
 #: src/views/domain/components/Deploy.vue:23
 #: src/views/domain/components/Deploy.vue:23
 #: src/views/domain/components/RightSettings.vue:51
 #: src/views/domain/components/RightSettings.vue:51
 #: src/views/domain/DomainList.vue:144
 #: src/views/domain/DomainList.vue:144
@@ -982,7 +989,7 @@ msgstr ""
 msgid "Please fill in the API authentication credentials provided by your DNS provider."
 msgid "Please fill in the API authentication credentials provided by your DNS provider."
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:55
+#: src/views/domain/cert/components/AutoCertStepOne.vue:58
 msgid "Please first add credentials in Certification > DNS Credentials, and then select one of the credentialsbelow to request the API of the DNS provider."
 msgid "Please first add credentials in Certification > DNS Credentials, and then select one of the credentialsbelow to request the API of the DNS provider."
 msgstr ""
 msgstr ""
 
 
@@ -1017,7 +1024,7 @@ msgstr ""
 msgid "Pre-release"
 msgid "Pre-release"
 msgstr ""
 msgstr ""
 
 
-#: src/routes/index.ts:167
+#: src/routes/index.ts:184
 #: src/views/preference/Preference.vue:85
 #: src/views/preference/Preference.vue:85
 msgid "Preference"
 msgid "Preference"
 msgstr ""
 msgstr ""
@@ -1081,6 +1088,15 @@ msgstr ""
 msgid "Reloading nginx"
 msgid "Reloading nginx"
 msgstr ""
 msgstr ""
 
 
+#: src/views/certificate/RenewCert.vue:43
+#: src/views/certificate/RenewCert.vue:47
+msgid "Renew Certificate"
+msgstr ""
+
+#: src/views/certificate/RenewCert.vue:25
+msgid "Renew successfully"
+msgstr ""
+
 #: src/language/constants.ts:35
 #: src/language/constants.ts:35
 msgid "Requested with wrong parameters"
 msgid "Requested with wrong parameters"
 msgstr ""
 msgstr ""
@@ -1106,6 +1122,7 @@ msgid "Running"
 msgstr ""
 msgstr ""
 
 
 #: src/components/ChatGPT/ChatGPT.vue:259
 #: src/components/ChatGPT/ChatGPT.vue:259
+#: src/views/certificate/CertificateEditor.vue:175
 #: src/views/config/ConfigEdit.vue:98
 #: src/views/config/ConfigEdit.vue:98
 #: src/views/domain/DomainEdit.vue:268
 #: src/views/domain/DomainEdit.vue:268
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:111
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:111
@@ -1124,6 +1141,7 @@ msgid "Save error %{msg}"
 msgstr ""
 msgstr ""
 
 
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:42
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:42
+#: src/views/certificate/CertificateEditor.vue:46
 #: src/views/preference/Preference.vue:58
 #: src/views/preference/Preference.vue:58
 msgid "Save successfully"
 msgid "Save successfully"
 msgstr ""
 msgstr ""
@@ -1166,24 +1184,32 @@ msgstr ""
 msgid "Server Info"
 msgid "Server Info"
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:165
+#: src/views/domain/cert/components/ObtainCert.vue:115
 msgid "server_name not found in directives"
 msgid "server_name not found in directives"
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:27
+#: src/views/domain/cert/components/AutoCertStepOne.vue:29
 #: src/views/domain/DomainAdd.vue:119
 #: src/views/domain/DomainAdd.vue:119
 msgid "server_name parameter is required"
 msgid "server_name parameter is required"
 msgstr ""
 msgstr ""
 
 
+#: src/language/constants.ts:15
+msgid "Setting DNS01 challenge provider"
+msgstr ""
+
 #: src/language/constants.ts:16
 #: src/language/constants.ts:16
 msgid "Setting environment variables"
 msgid "Setting environment variables"
 msgstr ""
 msgstr ""
 
 
+#: src/language/constants.ts:14
+msgid "Setting HTTP01 challenge provider"
+msgstr ""
+
 #: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:54
 #: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:54
 msgid "Single Directive"
 msgid "Single Directive"
 msgstr ""
 msgstr ""
 
 
-#: src/routes/index.ts:142
+#: src/routes/index.ts:159
 msgid "Site Logs"
 msgid "Site Logs"
 msgstr ""
 msgstr ""
 
 
@@ -1191,19 +1217,19 @@ msgstr ""
 msgid "Sites List"
 msgid "Sites List"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/Certificate.vue:164
+#: src/views/certificate/CertificateEditor.vue:135
 msgid "SSL Certificate Content"
 msgid "SSL Certificate Content"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/Certificate.vue:171
+#: src/views/certificate/CertificateEditor.vue:142
 msgid "SSL Certificate Key Content"
 msgid "SSL Certificate Key Content"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/Certificate.vue:73
+#: src/views/certificate/Certificate.vue:63
 msgid "SSL Certificate Key Path"
 msgid "SSL Certificate Key Path"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/Certificate.vue:65
+#: src/views/certificate/Certificate.vue:55
 msgid "SSL Certificate Path"
 msgid "SSL Certificate Path"
 msgstr ""
 msgstr ""
 
 
@@ -1216,6 +1242,7 @@ msgstr ""
 msgid "Stable"
 msgid "Stable"
 msgstr ""
 msgstr ""
 
 
+#: src/views/certificate/Certificate.vue:71
 #: src/views/domain/DomainList.vue:25
 #: src/views/domain/DomainList.vue:25
 #: src/views/environment/Environment.vue:78
 #: src/views/environment/Environment.vue:78
 msgid "Status"
 msgid "Status"
@@ -1245,7 +1272,7 @@ msgstr ""
 msgid "Switch to light theme"
 msgid "Switch to light theme"
 msgstr ""
 msgstr ""
 
 
-#: src/routes/index.ts:175
+#: src/routes/index.ts:192
 msgid "System"
 msgid "System"
 msgstr ""
 msgstr ""
 
 
@@ -1257,7 +1284,7 @@ msgstr ""
 msgid "Target"
 msgid "Target"
 msgstr ""
 msgstr ""
 
 
-#: src/routes/index.ts:120
+#: src/routes/index.ts:137
 #: src/views/pty/Terminal.vue:95
 #: src/views/pty/Terminal.vue:95
 msgid "Terminal"
 msgid "Terminal"
 msgstr ""
 msgstr ""
@@ -1266,7 +1293,7 @@ msgstr ""
 msgid "Terminal Start Command"
 msgid "Terminal Start Command"
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:47
+#: src/views/domain/cert/components/AutoCertStepOne.vue:50
 msgid "The certificate for the domain will be checked 5 minutes, and will be renewed if it has been more than 1 week since it was last issued."
 msgid "The certificate for the domain will be checked 5 minutes, and will be renewed if it has been more than 1 week since it was last issued."
 msgstr ""
 msgstr ""
 
 
@@ -1274,7 +1301,7 @@ msgstr ""
 msgid "The filename cannot contain the following characters: %{c}"
 msgid "The filename cannot contain the following characters: %{c}"
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:42
+#: src/views/domain/cert/components/AutoCertStepOne.vue:45
 msgid "The server_name in the current configuration must be the domain name you need to get the certificate, supportmultiple domains."
 msgid "The server_name in the current configuration must be the domain name you need to get the certificate, supportmultiple domains."
 msgstr ""
 msgstr ""
 
 
@@ -1282,10 +1309,14 @@ msgstr ""
 msgid "The username or password is incorrect"
 msgid "The username or password is incorrect"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/Certificate.vue:115
+#: src/views/certificate/CertificateEditor.vue:93
 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:83
+msgid "This certificate is managed by Nginx UI"
+msgstr ""
+
 #: src/components/StdDesign/StdDataEntry/StdFormItem.vue:31
 #: src/components/StdDesign/StdDataEntry/StdFormItem.vue:31
 msgid "This field should not be empty"
 msgid "This field should not be empty"
 msgstr ""
 msgstr ""
@@ -1294,11 +1325,11 @@ msgstr ""
 msgid "To make sure the certification auto-renewal can work normally, we need to add a location which can proxy the request from authority to backend, and we need to save this file and reload the Nginx. Are you sure you want to continue?"
 msgid "To make sure the certification auto-renewal can work normally, we need to add a location which can proxy the request from authority to backend, and we need to save this file and reload the Nginx. Are you sure you want to continue?"
 msgstr ""
 msgstr ""
 
 
+#: src/views/certificate/Certificate.vue:39
 #: src/views/config/config.ts:14
 #: src/views/config/config.ts:14
 msgid "Type"
 msgid "Type"
 msgstr ""
 msgstr ""
 
 
-#: src/views/certificate/Certificate.vue:81
 #: src/views/certificate/DNSCredential.vue:26
 #: src/views/certificate/DNSCredential.vue:26
 #: src/views/config/config.ts:29
 #: src/views/config/config.ts:29
 #: src/views/config/ConfigEdit.vue:123
 #: src/views/config/ConfigEdit.vue:123
@@ -1313,7 +1344,7 @@ msgstr ""
 msgid "Updated successfully"
 msgid "Updated successfully"
 msgstr ""
 msgstr ""
 
 
-#: src/routes/index.ts:186
+#: src/routes/index.ts:203
 #: src/views/system/Upgrade.vue:143
 #: src/views/system/Upgrade.vue:143
 #: src/views/system/Upgrade.vue:235
 #: src/views/system/Upgrade.vue:235
 msgid "Upgrade"
 msgid "Upgrade"
@@ -1348,12 +1379,8 @@ msgstr ""
 msgid "Username (*)"
 msgid "Username (*)"
 msgstr ""
 msgstr ""
 
 
-#: src/language/constants.ts:15
-msgid "Using DNS01 challenge provider"
-msgstr ""
-
-#: src/language/constants.ts:14
-msgid "Using HTTP01 challenge provider"
+#: src/views/certificate/Certificate.vue:80
+msgid "Valid"
 msgstr ""
 msgstr ""
 
 
 #: src/views/domain/ngx_conf/config_template/ConfigTemplate.vue:101
 #: src/views/domain/ngx_conf/config_template/ConfigTemplate.vue:101
@@ -1361,7 +1388,7 @@ msgid "View"
 msgstr ""
 msgstr ""
 
 
 #: src/views/config/InspectConfig.vue:36
 #: src/views/config/InspectConfig.vue:36
-#: src/views/domain/cert/components/AutoCertStepOne.vue:21
+#: src/views/domain/cert/components/AutoCertStepOne.vue:23
 #: src/views/domain/DomainAdd.vue:114
 #: src/views/domain/DomainAdd.vue:114
 msgid "Warning"
 msgid "Warning"
 msgstr ""
 msgstr ""
@@ -1370,7 +1397,7 @@ msgstr ""
 msgid "We will add one or more TXT records to the DNS records of your domain for ownership verification."
 msgid "We will add one or more TXT records to the DNS records of your domain for ownership verification."
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:208
+#: src/views/domain/cert/components/ObtainCert.vue:147
 msgid "We will remove the HTTPChallenge configuration from this file and reload the Nginx. Are you sure you want to continue?"
 msgid "We will remove the HTTPChallenge configuration from this file and reload the Nginx. Are you sure you want to continue?"
 msgstr ""
 msgstr ""
 
 

+ 124 - 81
app/src/language/ru_RU/app.po

@@ -9,15 +9,15 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
 
-#: src/routes/index.ts:182
+#: src/routes/index.ts:199
 msgid "About"
 msgid "About"
 msgstr "О проекте"
 msgstr "О проекте"
 
 
-#: src/routes/index.ts:134 src/views/domain/ngx_conf/LogEntry.vue:78
+#: src/routes/index.ts:151 src/views/domain/ngx_conf/LogEntry.vue:78
 msgid "Access Logs"
 msgid "Access Logs"
 msgstr "Журнал доступа"
 msgstr "Журнал доступа"
 
 
-#: src/views/certificate/Certificate.vue:87
+#: src/views/certificate/Certificate.vue:96
 #: src/views/certificate/DNSCredential.vue:32 src/views/config/config.ts:36
 #: src/views/certificate/DNSCredential.vue:32 src/views/config/config.ts:36
 #: src/views/domain/DomainList.vue:50 src/views/environment/Environment.vue:105
 #: src/views/domain/DomainList.vue:50 src/views/environment/Environment.vue:105
 #: src/views/user/User.vue:46
 #: src/views/user/User.vue:46
@@ -31,6 +31,12 @@ msgstr "Действие"
 msgid "Add"
 msgid "Add"
 msgstr "Добавить"
 msgstr "Добавить"
 
 
+#: src/routes/index.ts:122 src/views/certificate/Certificate.vue:115
+#: src/views/certificate/CertificateEditor.vue:76
+#, fuzzy
+msgid "Add Certificate"
+msgstr "Статус сертификата"
+
 #: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:98
 #: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:98
 msgid "Add Directive Below"
 msgid "Add Directive Below"
 msgstr "Добавить директиву ниже"
 msgstr "Добавить директиву ниже"
@@ -102,33 +108,23 @@ msgstr ""
 msgid "Author"
 msgid "Author"
 msgstr "Автор"
 msgstr "Автор"
 
 
-#: src/views/certificate/Certificate.vue:46
 #: src/views/domain/cert/ChangeCert.vue:37
 #: src/views/domain/cert/ChangeCert.vue:37
 msgid "Auto Cert"
 msgid "Auto Cert"
 msgstr "Авто Сертификат"
 msgstr "Авто Сертификат"
 
 
-#: src/views/certificate/Certificate.vue:105
-#, fuzzy
-msgid "Auto Cert is enabled"
-msgstr "Авто Сертификат"
-
-#: src/views/certificate/Certificate.vue:135
-#, fuzzy
-msgid "Auto Cert Log"
-msgstr "Логирование авто-сертификата"
-
 #: src/views/nginx_log/NginxLog.vue:149
 #: src/views/nginx_log/NginxLog.vue:149
 msgid "Auto Refresh"
 msgid "Auto Refresh"
 msgstr "Автообновление"
 msgstr "Автообновление"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:126
+#: src/views/domain/cert/components/ObtainCert.vue:76
 msgid "Auto-renewal disabled for %{name}"
 msgid "Auto-renewal disabled for %{name}"
 msgstr "Автообновление отключено для %{name}"
 msgstr "Автообновление отключено для %{name}"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:119
+#: src/views/domain/cert/components/ObtainCert.vue:69
 msgid "Auto-renewal enabled for %{name}"
 msgid "Auto-renewal enabled for %{name}"
 msgstr "Автообновление включено для %{name}"
 msgstr "Автообновление включено для %{name}"
 
 
+#: src/views/certificate/CertificateEditor.vue:168
 #: src/views/config/Config.vue:75 src/views/config/ConfigEdit.vue:89
 #: src/views/config/Config.vue:75 src/views/config/ConfigEdit.vue:89
 #: src/views/domain/DomainEdit.vue:261 src/views/nginx_log/NginxLog.vue:170
 #: src/views/domain/DomainEdit.vue:261 src/views/nginx_log/NginxLog.vue:170
 msgid "Back"
 msgid "Back"
@@ -172,7 +168,7 @@ msgstr ""
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:58
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:58
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:139
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:139
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:103
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:103
-#: src/views/domain/cert/components/ObtainCert.vue:211
+#: src/views/domain/cert/components/ObtainCert.vue:150
 #: src/views/domain/components/Deploy.vue:24
 #: src/views/domain/components/Deploy.vue:24
 #: src/views/domain/components/RightSettings.vue:52
 #: src/views/domain/components/RightSettings.vue:52
 #: src/views/domain/ngx_conf/NgxConfigEditor.vue:216
 #: src/views/domain/ngx_conf/NgxConfigEditor.vue:216
@@ -188,22 +184,22 @@ msgstr "Срок действия сертификата истек"
 msgid "Certificate is valid"
 msgid "Certificate is valid"
 msgstr "Сертификат действителен"
 msgstr "Сертификат действителен"
 
 
-#: src/views/certificate/Certificate.vue:145 src/views/domain/cert/Cert.vue:35
+#: src/views/certificate/CertificateEditor.vue:119
+#: src/views/domain/cert/Cert.vue:35
 msgid "Certificate Status"
 msgid "Certificate Status"
 msgstr "Статус сертификата"
 msgstr "Статус сертификата"
 
 
-#: src/routes/index.ts:100 src/views/certificate/Certificate.vue:96
+#: src/routes/index.ts:100 src/views/certificate/Certificate.vue:109
 #, fuzzy
 #, fuzzy
 msgid "Certificates"
 msgid "Certificates"
 msgstr "Статус сертификата"
 msgstr "Статус сертификата"
 
 
-#: src/routes/index.ts:108
+#: src/routes/index.ts:109
 #, fuzzy
 #, fuzzy
 msgid "Certificates List"
 msgid "Certificates List"
 msgstr "Список"
 msgstr "Список"
 
 
-#: src/views/certificate/Certificate.vue:150
-#: src/views/domain/cert/components/AutoCertStepOne.vue:63
+#: src/views/domain/cert/components/AutoCertStepOne.vue:65
 msgid "Challenge Method"
 msgid "Challenge Method"
 msgstr "Метод Challenge"
 msgstr "Метод Challenge"
 
 
@@ -244,11 +240,6 @@ msgstr "Очистить"
 msgid "Comments"
 msgid "Comments"
 msgstr "Комментарии"
 msgstr "Комментарии"
 
 
-#: src/views/certificate/Certificate.vue:41
-#, fuzzy
-msgid "Config Name"
-msgstr "Название конфигурации"
-
 #: src/views/domain/ngx_conf/config_template/ConfigTemplate.vue:82
 #: src/views/domain/ngx_conf/config_template/ConfigTemplate.vue:82
 #, fuzzy
 #, fuzzy
 msgid "Config Templates"
 msgid "Config Templates"
@@ -304,7 +295,7 @@ msgstr "Создан в"
 msgid "Creating client facilitates communication with the CA server"
 msgid "Creating client facilitates communication with the CA server"
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/cert/components/DNSChallenge.vue:89
+#: src/views/domain/cert/components/DNSChallenge.vue:105
 msgid "Credential"
 msgid "Credential"
 msgstr "Учетные данные"
 msgstr "Учетные данные"
 
 
@@ -389,11 +380,10 @@ msgstr "Деректива"
 msgid "Disable"
 msgid "Disable"
 msgstr "Отключить"
 msgstr "Отключить"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:128
+#: src/views/domain/cert/components/ObtainCert.vue:78
 msgid "Disable auto-renewal failed for %{name}"
 msgid "Disable auto-renewal failed for %{name}"
 msgstr "Не удалось отключить автоматическое продление для %{name}"
 msgstr "Не удалось отключить автоматическое продление для %{name}"
 
 
-#: src/views/certificate/Certificate.vue:57
 #: src/views/domain/cert/ChangeCert.vue:48 src/views/domain/DomainEdit.vue:190
 #: src/views/domain/cert/ChangeCert.vue:48 src/views/domain/DomainEdit.vue:190
 #: src/views/domain/DomainList.vue:123
 #: src/views/domain/DomainList.vue:123
 msgid "Disabled"
 msgid "Disabled"
@@ -408,16 +398,16 @@ msgstr "Отключено успешно"
 msgid "Disk IO"
 msgid "Disk IO"
 msgstr "Нагрузка на Диск IO"
 msgstr "Нагрузка на Диск IO"
 
 
-#: src/routes/index.ts:113 src/views/certificate/DNSCredential.vue:39
+#: src/routes/index.ts:130 src/views/certificate/DNSCredential.vue:39
 msgid "DNS Credentials"
 msgid "DNS Credentials"
 msgstr ""
 msgstr ""
 
 
 #: src/views/certificate/DNSChallenge.vue:74
 #: src/views/certificate/DNSChallenge.vue:74
-#: src/views/domain/cert/components/DNSChallenge.vue:79
+#: src/views/domain/cert/components/DNSChallenge.vue:95
 msgid "DNS Provider"
 msgid "DNS Provider"
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:69
+#: src/views/domain/cert/components/AutoCertStepOne.vue:71
 msgid "DNS01"
 msgid "DNS01"
 msgstr ""
 msgstr ""
 
 
@@ -428,7 +418,7 @@ msgid_plural "Do you want to deploy this file to remote servers?"
 msgstr[0] "Are you sure you want to remove this directive?"
 msgstr[0] "Are you sure you want to remove this directive?"
 msgstr[1] "Are you sure you want to remove this directive?"
 msgstr[1] "Are you sure you want to remove this directive?"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:207
+#: src/views/domain/cert/components/ObtainCert.vue:146
 msgid "Do you want to disable auto-cert renewal?"
 msgid "Do you want to disable auto-cert renewal?"
 msgstr "Вы хотите отключить автоматическое обновление сертификата?"
 msgstr "Вы хотите отключить автоматическое обновление сертификата?"
 
 
@@ -456,7 +446,7 @@ msgstr "Вы хотите удалить этот сервер?"
 msgid "Domain Config Created Successfully"
 msgid "Domain Config Created Successfully"
 msgstr "Конфигурация домена успешно создана"
 msgstr "Конфигурация домена успешно создана"
 
 
-#: src/views/certificate/Certificate.vue:125
+#: src/views/certificate/CertificateEditor.vue:103
 #, fuzzy
 #, fuzzy
 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 ""
@@ -528,7 +518,7 @@ msgstr "Включение %{conf_name} in %{node_name} нипалучилася
 msgid "Enable %{conf_name} in %{node_name} successfully"
 msgid "Enable %{conf_name} in %{node_name} successfully"
 msgstr "Включение %{conf_name} in %{node_name} успешно"
 msgstr "Включение %{conf_name} in %{node_name} успешно"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:121
+#: src/views/domain/cert/components/ObtainCert.vue:71
 msgid "Enable auto-renewal failed for %{name}"
 msgid "Enable auto-renewal failed for %{name}"
 msgstr "Не удалось включить автоматическое продление для %{name}"
 msgstr "Не удалось включить автоматическое продление для %{name}"
 
 
@@ -545,7 +535,6 @@ msgstr "Активировано успешно"
 msgid "Enable TLS"
 msgid "Enable TLS"
 msgstr "Включить TLS"
 msgstr "Включить TLS"
 
 
-#: src/views/certificate/Certificate.vue:53
 #: src/views/domain/cert/ChangeCert.vue:44
 #: src/views/domain/cert/ChangeCert.vue:44
 #: src/views/domain/components/Deploy.vue:89
 #: src/views/domain/components/Deploy.vue:89
 #: src/views/domain/components/RightSettings.vue:75
 #: src/views/domain/components/RightSettings.vue:75
@@ -563,7 +552,7 @@ msgstr "Активировано успешно"
 msgid "Encrypt website with Let's Encrypt"
 msgid "Encrypt website with Let's Encrypt"
 msgstr "Использовать для сайта Let's Encrypt"
 msgstr "Использовать для сайта Let's Encrypt"
 
 
-#: src/routes/index.ts:151 src/views/environment/Environment.vue:113
+#: src/routes/index.ts:168 src/views/environment/Environment.vue:113
 msgid "Environment"
 msgid "Environment"
 msgstr "Окружение"
 msgstr "Окружение"
 
 
@@ -576,7 +565,7 @@ msgstr "Комментарии"
 msgid "Error"
 msgid "Error"
 msgstr "Ошибка"
 msgstr "Ошибка"
 
 
-#: src/routes/index.ts:138 src/views/domain/ngx_conf/LogEntry.vue:86
+#: src/routes/index.ts:155 src/views/domain/ngx_conf/LogEntry.vue:86
 msgid "Error Logs"
 msgid "Error Logs"
 msgstr "Ошибка логирования"
 msgstr "Ошибка логирования"
 
 
@@ -584,6 +573,10 @@ msgstr "Ошибка логирования"
 msgid "Executable Path"
 msgid "Executable Path"
 msgstr "Исполняемый путь"
 msgstr "Исполняемый путь"
 
 
+#: src/views/certificate/Certificate.vue:84
+msgid "Expired"
+msgstr ""
+
 #: src/views/domain/cert/CertInfo.vue:27
 #: src/views/domain/cert/CertInfo.vue:27
 #, fuzzy
 #, fuzzy
 msgid "Expired At: %{date}"
 msgid "Expired At: %{date}"
@@ -659,7 +652,7 @@ msgstr "Генерация приватного ключа для регистр
 msgid "Get release information error"
 msgid "Get release information error"
 msgstr "Ошибка получения информации о релизе"
 msgstr "Ошибка получения информации о релизе"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:64
+#: src/views/domain/cert/components/ObtainCertLive.vue:68
 msgid "Getting the certificate, please wait..."
 msgid "Getting the certificate, please wait..."
 msgstr "Получение сертификата, пожалуйста, подождите..."
 msgstr "Получение сертификата, пожалуйста, подождите..."
 
 
@@ -699,7 +692,7 @@ msgstr "Хостинг HTTP"
 msgid "HTTP Port"
 msgid "HTTP Port"
 msgstr "Порт HTTP"
 msgstr "Порт HTTP"
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:66
+#: src/views/domain/cert/components/AutoCertStepOne.vue:68
 msgid "HTTP01"
 msgid "HTTP01"
 msgstr ""
 msgstr ""
 
 
@@ -711,7 +704,7 @@ msgstr "Ошибка первоначального обновления ядр
 msgid "Initialing core upgrader"
 msgid "Initialing core upgrader"
 msgstr "Инициализация программы обновления ядра"
 msgstr "Инициализация программы обновления ядра"
 
 
-#: src/routes/index.ts:194 src/views/other/Install.vue:139
+#: src/routes/index.ts:211 src/views/other/Install.vue:139
 msgid "Install"
 msgid "Install"
 msgstr "Установить"
 msgstr "Установить"
 
 
@@ -773,7 +766,12 @@ msgstr "Location"
 msgid "Locations"
 msgid "Locations"
 msgstr "Locations"
 msgstr "Locations"
 
 
-#: src/routes/index.ts:200 src/views/other/Login.vue:147
+#: src/views/certificate/CertificateEditor.vue:156
+#, fuzzy
+msgid "Log"
+msgstr "Логин"
+
+#: src/routes/index.ts:217 src/views/other/Login.vue:147
 msgid "Login"
 msgid "Login"
 msgstr "Логин"
 msgstr "Логин"
 
 
@@ -785,7 +783,7 @@ msgstr "Авторизация успешна"
 msgid "Logout successful"
 msgid "Logout successful"
 msgstr "Выход выполнен успешно"
 msgstr "Выход выполнен успешно"
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:51
+#: src/views/domain/cert/components/AutoCertStepOne.vue:54
 #, fuzzy
 #, fuzzy
 msgid ""
 msgid ""
 "Make sure you have configured a reverse proxy for .well-known directory to "
 "Make sure you have configured a reverse proxy for .well-known directory to "
@@ -802,7 +800,7 @@ msgstr "Конфигурации"
 msgid "Manage Sites"
 msgid "Manage Sites"
 msgstr "Сайты"
 msgstr "Сайты"
 
 
-#: src/routes/index.ts:159 src/views/user/User.vue:53
+#: src/routes/index.ts:176 src/views/user/User.vue:53
 msgid "Manage Users"
 msgid "Manage Users"
 msgstr "Пользователи"
 msgstr "Пользователи"
 
 
@@ -817,11 +815,15 @@ msgstr "Память и хранилище"
 #: src/components/ChatGPT/ChatGPT.vue:256
 #: src/components/ChatGPT/ChatGPT.vue:256
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:137
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:137
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:336
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:336
-#: src/views/certificate/Certificate.vue:156
 #, fuzzy
 #, fuzzy
 msgid "Modify"
 msgid "Modify"
 msgstr "Изменить"
 msgstr "Изменить"
 
 
+#: src/routes/index.ts:114 src/views/certificate/CertificateEditor.vue:76
+#, fuzzy
+msgid "Modify Certificate"
+msgstr "Статус сертификата"
+
 #: src/views/domain/DomainAdd.vue:153
 #: src/views/domain/DomainAdd.vue:153
 msgid "Modify Config"
 msgid "Modify Config"
 msgstr "Изменить конфигурацию"
 msgstr "Изменить конфигурацию"
@@ -831,7 +833,7 @@ msgstr "Изменить конфигурацию"
 msgid "Multi-line Directive"
 msgid "Multi-line Directive"
 msgstr "Одиночная директива"
 msgstr "Одиночная директива"
 
 
-#: src/views/certificate/Certificate.vue:24
+#: src/views/certificate/Certificate.vue:22
 #: src/views/certificate/DNSCredential.vue:13 src/views/config/config.ts:9
 #: src/views/certificate/DNSCredential.vue:13 src/views/config/config.ts:9
 #: src/views/domain/cert/ChangeCert.vue:21
 #: src/views/domain/cert/ChangeCert.vue:21
 #: src/views/domain/components/RightSettings.vue:81
 #: src/views/domain/components/RightSettings.vue:81
@@ -860,7 +862,7 @@ msgstr "Всего отправлено"
 msgid "New version released"
 msgid "New version released"
 msgstr "Вышла новая версия"
 msgstr "Вышла новая версия"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:281
+#: src/views/domain/cert/components/ObtainCert.vue:216
 #: src/views/domain/DomainAdd.vue:140
 #: src/views/domain/DomainAdd.vue:140
 msgid "Next"
 msgid "Next"
 msgstr "Дальше"
 msgstr "Дальше"
@@ -887,7 +889,7 @@ msgstr "Управление Nginx"
 msgid "Nginx Error Log Path"
 msgid "Nginx Error Log Path"
 msgstr "Путь для Nginx Error Log"
 msgstr "Путь для Nginx Error Log"
 
 
-#: src/routes/index.ts:128 src/views/nginx_log/NginxLog.vue:145
+#: src/routes/index.ts:145 src/views/nginx_log/NginxLog.vue:145
 msgid "Nginx Log"
 msgid "Nginx Log"
 msgstr "Журнал"
 msgstr "Журнал"
 
 
@@ -913,7 +915,11 @@ msgstr "Нет"
 msgid "Node Secret"
 msgid "Node Secret"
 msgstr ""
 msgstr ""
 
 
-#: src/routes/index.ts:206 src/routes/index.ts:208
+#: src/views/certificate/Certificate.vue:90
+msgid "Not After"
+msgstr ""
+
+#: src/routes/index.ts:223 src/routes/index.ts:225
 msgid "Not Found"
 msgid "Not Found"
 msgstr "Не найден"
 msgstr "Не найден"
 
 
@@ -922,11 +928,11 @@ msgid "Not Valid Before: %{date}"
 msgstr "Недействительно до: %{date}"
 msgstr "Недействительно до: %{date}"
 
 
 #: src/views/certificate/DNSCredential.vue:48
 #: src/views/certificate/DNSCredential.vue:48
-#: src/views/domain/cert/components/AutoCertStepOne.vue:38
+#: src/views/domain/cert/components/AutoCertStepOne.vue:40
 msgid "Note"
 msgid "Note"
 msgstr "Заметка"
 msgstr "Заметка"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:252
+#: src/views/domain/cert/components/ObtainCert.vue:191
 #, fuzzy
 #, fuzzy
 msgid "Obtain certificate"
 msgid "Obtain certificate"
 msgstr "Получить сертификат"
 msgstr "Получить сертификат"
@@ -946,7 +952,7 @@ msgstr ""
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:140
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:140
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:346
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:346
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:104
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:104
-#: src/views/domain/cert/components/ObtainCert.vue:210
+#: src/views/domain/cert/components/ObtainCert.vue:149
 #: src/views/domain/components/Deploy.vue:23
 #: src/views/domain/components/Deploy.vue:23
 #: src/views/domain/components/RightSettings.vue:51
 #: src/views/domain/components/RightSettings.vue:51
 #: src/views/domain/DomainList.vue:144
 #: src/views/domain/DomainList.vue:144
@@ -1019,7 +1025,7 @@ msgid ""
 "provider."
 "provider."
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:55
+#: src/views/domain/cert/components/AutoCertStepOne.vue:58
 msgid ""
 msgid ""
 "Please first add credentials in Certification > DNS Credentials, and then "
 "Please first add credentials in Certification > DNS Credentials, and then "
 "select one of the credentialsbelow to request the API of the DNS provider."
 "select one of the credentialsbelow to request the API of the DNS provider."
@@ -1058,7 +1064,7 @@ msgstr ""
 msgid "Pre-release"
 msgid "Pre-release"
 msgstr ""
 msgstr ""
 
 
-#: src/routes/index.ts:167 src/views/preference/Preference.vue:85
+#: src/routes/index.ts:184 src/views/preference/Preference.vue:85
 msgid "Preference"
 msgid "Preference"
 msgstr "Настройки"
 msgstr "Настройки"
 
 
@@ -1123,6 +1129,17 @@ msgstr "Перезагружается"
 msgid "Reloading nginx"
 msgid "Reloading nginx"
 msgstr "Перезагружается nginx"
 msgstr "Перезагружается nginx"
 
 
+#: src/views/certificate/RenewCert.vue:43
+#: src/views/certificate/RenewCert.vue:47
+#, fuzzy
+msgid "Renew Certificate"
+msgstr "Сертификат действителен"
+
+#: src/views/certificate/RenewCert.vue:25
+#, fuzzy
+msgid "Renew successfully"
+msgstr "Активировано успешно"
+
 #: src/language/constants.ts:35
 #: src/language/constants.ts:35
 msgid "Requested with wrong parameters"
 msgid "Requested with wrong parameters"
 msgstr "Запрос с неправильными параметрами"
 msgstr "Запрос с неправильными параметрами"
@@ -1148,8 +1165,9 @@ msgstr "Расширенный режим"
 msgid "Running"
 msgid "Running"
 msgstr "Выполняется"
 msgstr "Выполняется"
 
 
-#: src/components/ChatGPT/ChatGPT.vue:259 src/views/config/ConfigEdit.vue:98
-#: src/views/domain/DomainEdit.vue:268
+#: src/components/ChatGPT/ChatGPT.vue:259
+#: src/views/certificate/CertificateEditor.vue:175
+#: src/views/config/ConfigEdit.vue:98 src/views/domain/DomainEdit.vue:268
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:111
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:111
 #: src/views/preference/Preference.vue:113
 #: src/views/preference/Preference.vue:113
 msgid "Save"
 msgid "Save"
@@ -1165,6 +1183,7 @@ msgid "Save error %{msg}"
 msgstr "Ошибка сохранения %{msg}"
 msgstr "Ошибка сохранения %{msg}"
 
 
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:42
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:42
+#: src/views/certificate/CertificateEditor.vue:46
 #: src/views/preference/Preference.vue:58
 #: src/views/preference/Preference.vue:58
 #, fuzzy
 #, fuzzy
 msgid "Save successfully"
 msgid "Save successfully"
@@ -1206,24 +1225,32 @@ msgstr "Ошибка сервера"
 msgid "Server Info"
 msgid "Server Info"
 msgstr "Информация о сервере"
 msgstr "Информация о сервере"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:165
+#: src/views/domain/cert/components/ObtainCert.vue:115
 msgid "server_name not found in directives"
 msgid "server_name not found in directives"
 msgstr "server_name не нашел в директивах"
 msgstr "server_name не нашел в директивах"
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:27
+#: src/views/domain/cert/components/AutoCertStepOne.vue:29
 #: src/views/domain/DomainAdd.vue:119
 #: src/views/domain/DomainAdd.vue:119
 msgid "server_name parameter is required"
 msgid "server_name parameter is required"
 msgstr "server_name параметр обязателен"
 msgstr "server_name параметр обязателен"
 
 
+#: src/language/constants.ts:15
+msgid "Setting DNS01 challenge provider"
+msgstr ""
+
 #: src/language/constants.ts:16
 #: src/language/constants.ts:16
 msgid "Setting environment variables"
 msgid "Setting environment variables"
 msgstr "Настройка переменных сред"
 msgstr "Настройка переменных сред"
 
 
+#: src/language/constants.ts:14
+msgid "Setting HTTP01 challenge provider"
+msgstr ""
+
 #: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:54
 #: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:54
 msgid "Single Directive"
 msgid "Single Directive"
 msgstr "Одиночная Директива"
 msgstr "Одиночная Директива"
 
 
-#: src/routes/index.ts:142
+#: src/routes/index.ts:159
 #, fuzzy
 #, fuzzy
 msgid "Site Logs"
 msgid "Site Logs"
 msgstr "Логи сайтов"
 msgstr "Логи сайтов"
@@ -1232,22 +1259,22 @@ msgstr "Логи сайтов"
 msgid "Sites List"
 msgid "Sites List"
 msgstr "Список сайтов"
 msgstr "Список сайтов"
 
 
-#: src/views/certificate/Certificate.vue:164
+#: src/views/certificate/CertificateEditor.vue:135
 #, fuzzy
 #, fuzzy
 msgid "SSL Certificate Content"
 msgid "SSL Certificate Content"
 msgstr "Содержание сертификата SSL"
 msgstr "Содержание сертификата SSL"
 
 
-#: src/views/certificate/Certificate.vue:171
+#: src/views/certificate/CertificateEditor.vue:142
 #, fuzzy
 #, fuzzy
 msgid "SSL Certificate Key Content"
 msgid "SSL Certificate Key Content"
 msgstr "Содержание ключа сертификата SSL"
 msgstr "Содержание ключа сертификата SSL"
 
 
-#: src/views/certificate/Certificate.vue:73
+#: src/views/certificate/Certificate.vue:63
 #, fuzzy
 #, fuzzy
 msgid "SSL Certificate Key Path"
 msgid "SSL Certificate Key Path"
 msgstr "Путь к ключу сертификата SSL"
 msgstr "Путь к ключу сертификата SSL"
 
 
-#: src/views/certificate/Certificate.vue:65
+#: src/views/certificate/Certificate.vue:55
 #, fuzzy
 #, fuzzy
 msgid "SSL Certificate Path"
 msgid "SSL Certificate Path"
 msgstr "Путь к сертификату SSL"
 msgstr "Путь к сертификату SSL"
@@ -1262,7 +1289,8 @@ msgstr "Логин"
 msgid "Stable"
 msgid "Stable"
 msgstr "Таблица"
 msgstr "Таблица"
 
 
-#: src/views/domain/DomainList.vue:25 src/views/environment/Environment.vue:78
+#: src/views/certificate/Certificate.vue:71 src/views/domain/DomainList.vue:25
+#: src/views/environment/Environment.vue:78
 msgid "Status"
 msgid "Status"
 msgstr "Статус"
 msgstr "Статус"
 
 
@@ -1291,7 +1319,7 @@ msgstr ""
 msgid "Switch to light theme"
 msgid "Switch to light theme"
 msgstr ""
 msgstr ""
 
 
-#: src/routes/index.ts:175
+#: src/routes/index.ts:192
 msgid "System"
 msgid "System"
 msgstr "Система"
 msgstr "Система"
 
 
@@ -1304,7 +1332,7 @@ msgstr "Таблица"
 msgid "Target"
 msgid "Target"
 msgstr ""
 msgstr ""
 
 
-#: src/routes/index.ts:120 src/views/pty/Terminal.vue:95
+#: src/routes/index.ts:137 src/views/pty/Terminal.vue:95
 msgid "Terminal"
 msgid "Terminal"
 msgstr "Терминал"
 msgstr "Терминал"
 
 
@@ -1312,7 +1340,7 @@ msgstr "Терминал"
 msgid "Terminal Start Command"
 msgid "Terminal Start Command"
 msgstr "Терминальная команда запуска"
 msgstr "Терминальная команда запуска"
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:47
+#: src/views/domain/cert/components/AutoCertStepOne.vue:50
 #, fuzzy
 #, fuzzy
 msgid ""
 msgid ""
 "The certificate for the domain will be checked 5 minutes, and will be "
 "The certificate for the domain will be checked 5 minutes, and will be "
@@ -1325,7 +1353,7 @@ msgstr ""
 msgid "The filename cannot contain the following characters: %{c}"
 msgid "The filename cannot contain the following characters: %{c}"
 msgstr "The filename cannot contain the following characters: %{c}"
 msgstr "The filename cannot contain the following characters: %{c}"
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:42
+#: src/views/domain/cert/components/AutoCertStepOne.vue:45
 #, fuzzy
 #, fuzzy
 msgid ""
 msgid ""
 "The server_name in the current configuration must be the domain name you "
 "The server_name in the current configuration must be the domain name you "
@@ -1338,11 +1366,15 @@ msgstr ""
 msgid "The username or password is incorrect"
 msgid "The username or password is incorrect"
 msgstr "Имя пользователя или пароль неверны"
 msgstr "Имя пользователя или пароль неверны"
 
 
-#: src/views/certificate/Certificate.vue:115
+#: src/views/certificate/CertificateEditor.vue:93
 #, fuzzy
 #, fuzzy
 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:83
+msgid "This certificate is managed by Nginx UI"
+msgstr ""
+
 #: src/components/StdDesign/StdDataEntry/StdFormItem.vue:31
 #: src/components/StdDesign/StdDataEntry/StdFormItem.vue:31
 msgid "This field should not be empty"
 msgid "This field should not be empty"
 msgstr ""
 msgstr ""
@@ -1355,11 +1387,10 @@ msgid ""
 "continue?"
 "continue?"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/config.ts:14
+#: src/views/certificate/Certificate.vue:39 src/views/config/config.ts:14
 msgid "Type"
 msgid "Type"
 msgstr "Тип"
 msgstr "Тип"
 
 
-#: src/views/certificate/Certificate.vue:81
 #: src/views/certificate/DNSCredential.vue:26 src/views/config/config.ts:29
 #: src/views/certificate/DNSCredential.vue:26 src/views/config/config.ts:29
 #: src/views/config/ConfigEdit.vue:123
 #: src/views/config/ConfigEdit.vue:123
 #: src/views/domain/components/RightSettings.vue:84
 #: src/views/domain/components/RightSettings.vue:84
@@ -1373,7 +1404,7 @@ msgstr "Обновлено в"
 msgid "Updated successfully"
 msgid "Updated successfully"
 msgstr "Обновлено успешно"
 msgstr "Обновлено успешно"
 
 
-#: src/routes/index.ts:186 src/views/system/Upgrade.vue:143
+#: src/routes/index.ts:203 src/views/system/Upgrade.vue:143
 #: src/views/system/Upgrade.vue:235
 #: src/views/system/Upgrade.vue:235
 msgid "Upgrade"
 msgid "Upgrade"
 msgstr "Обновление"
 msgstr "Обновление"
@@ -1408,12 +1439,8 @@ msgstr "Имя пользователя"
 msgid "Username (*)"
 msgid "Username (*)"
 msgstr "Имя пользователя (*)"
 msgstr "Имя пользователя (*)"
 
 
-#: src/language/constants.ts:15
-msgid "Using DNS01 challenge provider"
-msgstr ""
-
-#: src/language/constants.ts:14
-msgid "Using HTTP01 challenge provider"
+#: src/views/certificate/Certificate.vue:80
+msgid "Valid"
 msgstr ""
 msgstr ""
 
 
 #: src/views/domain/ngx_conf/config_template/ConfigTemplate.vue:101
 #: src/views/domain/ngx_conf/config_template/ConfigTemplate.vue:101
@@ -1421,7 +1448,7 @@ msgid "View"
 msgstr "Просмотр"
 msgstr "Просмотр"
 
 
 #: src/views/config/InspectConfig.vue:36
 #: src/views/config/InspectConfig.vue:36
-#: src/views/domain/cert/components/AutoCertStepOne.vue:21
+#: src/views/domain/cert/components/AutoCertStepOne.vue:23
 #: src/views/domain/DomainAdd.vue:114
 #: src/views/domain/DomainAdd.vue:114
 msgid "Warning"
 msgid "Warning"
 msgstr "Внимание"
 msgstr "Внимание"
@@ -1432,7 +1459,7 @@ msgid ""
 "ownership verification."
 "ownership verification."
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:208
+#: src/views/domain/cert/components/ObtainCert.vue:147
 msgid ""
 msgid ""
 "We will remove the HTTPChallenge configuration from this file and reload the "
 "We will remove the HTTPChallenge configuration from this file and reload the "
 "Nginx. Are you sure you want to continue?"
 "Nginx. Are you sure you want to continue?"
@@ -1464,6 +1491,22 @@ msgstr "Вы используете последнюю версию"
 msgid "You can check Nginx UI upgrade at this page."
 msgid "You can check Nginx UI upgrade at this page."
 msgstr "Вы можете проверить обновление Nginx UI на этой странице."
 msgstr "Вы можете проверить обновление Nginx UI на этой странице."
 
 
+#, fuzzy
+#~ msgid "Renew certificate"
+#~ msgstr "Получить сертификат"
+
+#, fuzzy
+#~ msgid "Auto Cert is enabled"
+#~ msgstr "Авто Сертификат"
+
+#, fuzzy
+#~ msgid "Auto Cert Log"
+#~ msgstr "Логирование авто-сертификата"
+
+#, fuzzy
+#~ msgid "Config Name"
+#~ msgstr "Название конфигурации"
+
 #~ msgid "Auto cert is enabled, please do not modify this certification."
 #~ msgid "Auto cert is enabled, please do not modify this certification."
 #~ msgstr "Включено автомотическое получения сертификата. Не правте руками."
 #~ msgstr "Включено автомотическое получения сертификата. Не правте руками."
 
 

BIN
app/src/language/zh_CN/app.mo


+ 116 - 79
app/src/language/zh_CN/app.po

@@ -13,15 +13,15 @@ msgstr ""
 "Generated-By: easygettext\n"
 "Generated-By: easygettext\n"
 "X-Generator: Poedit 3.4.1\n"
 "X-Generator: Poedit 3.4.1\n"
 
 
-#: src/routes/index.ts:182
+#: src/routes/index.ts:199
 msgid "About"
 msgid "About"
 msgstr "关于"
 msgstr "关于"
 
 
-#: src/routes/index.ts:134 src/views/domain/ngx_conf/LogEntry.vue:78
+#: src/routes/index.ts:151 src/views/domain/ngx_conf/LogEntry.vue:78
 msgid "Access Logs"
 msgid "Access Logs"
 msgstr "访问日志"
 msgstr "访问日志"
 
 
-#: src/views/certificate/Certificate.vue:87
+#: src/views/certificate/Certificate.vue:96
 #: src/views/certificate/DNSCredential.vue:32 src/views/config/config.ts:36
 #: src/views/certificate/DNSCredential.vue:32 src/views/config/config.ts:36
 #: src/views/domain/DomainList.vue:50 src/views/environment/Environment.vue:105
 #: src/views/domain/DomainList.vue:50 src/views/environment/Environment.vue:105
 #: src/views/user/User.vue:46
 #: src/views/user/User.vue:46
@@ -35,6 +35,11 @@ msgstr "操作"
 msgid "Add"
 msgid "Add"
 msgstr "添加"
 msgstr "添加"
 
 
+#: src/routes/index.ts:122 src/views/certificate/Certificate.vue:115
+#: src/views/certificate/CertificateEditor.vue:76
+msgid "Add Certificate"
+msgstr "添加证书"
+
 #: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:98
 #: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:98
 msgid "Add Directive Below"
 msgid "Add Directive Below"
 msgstr "在下面添加指令"
 msgstr "在下面添加指令"
@@ -102,31 +107,23 @@ msgstr "助手"
 msgid "Author"
 msgid "Author"
 msgstr "作者"
 msgstr "作者"
 
 
-#: src/views/certificate/Certificate.vue:46
 #: src/views/domain/cert/ChangeCert.vue:37
 #: src/views/domain/cert/ChangeCert.vue:37
 msgid "Auto Cert"
 msgid "Auto Cert"
 msgstr "自动更新"
 msgstr "自动更新"
 
 
-#: src/views/certificate/Certificate.vue:105
-msgid "Auto Cert is enabled"
-msgstr "自动更新已启用"
-
-#: src/views/certificate/Certificate.vue:135
-msgid "Auto Cert Log"
-msgstr "证书自动续期日志"
-
 #: src/views/nginx_log/NginxLog.vue:149
 #: src/views/nginx_log/NginxLog.vue:149
 msgid "Auto Refresh"
 msgid "Auto Refresh"
 msgstr "自动刷新"
 msgstr "自动刷新"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:126
+#: src/views/domain/cert/components/ObtainCert.vue:76
 msgid "Auto-renewal disabled for %{name}"
 msgid "Auto-renewal disabled for %{name}"
 msgstr "成功关闭 %{name} 自动续签"
 msgstr "成功关闭 %{name} 自动续签"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:119
+#: src/views/domain/cert/components/ObtainCert.vue:69
 msgid "Auto-renewal enabled for %{name}"
 msgid "Auto-renewal enabled for %{name}"
 msgstr "成功启用 %{name} 自动续签"
 msgstr "成功启用 %{name} 自动续签"
 
 
+#: src/views/certificate/CertificateEditor.vue:168
 #: src/views/config/Config.vue:75 src/views/config/ConfigEdit.vue:89
 #: src/views/config/Config.vue:75 src/views/config/ConfigEdit.vue:89
 #: src/views/domain/DomainEdit.vue:261 src/views/nginx_log/NginxLog.vue:170
 #: src/views/domain/DomainEdit.vue:261 src/views/nginx_log/NginxLog.vue:170
 msgid "Back"
 msgid "Back"
@@ -167,7 +164,7 @@ msgstr "CADir"
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:58
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:58
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:139
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:139
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:103
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:103
-#: src/views/domain/cert/components/ObtainCert.vue:211
+#: src/views/domain/cert/components/ObtainCert.vue:150
 #: src/views/domain/components/Deploy.vue:24
 #: src/views/domain/components/Deploy.vue:24
 #: src/views/domain/components/RightSettings.vue:52
 #: src/views/domain/components/RightSettings.vue:52
 #: src/views/domain/ngx_conf/NgxConfigEditor.vue:216
 #: src/views/domain/ngx_conf/NgxConfigEditor.vue:216
@@ -183,20 +180,20 @@ msgstr "此证书已过期"
 msgid "Certificate is valid"
 msgid "Certificate is valid"
 msgstr "此证书有效"
 msgstr "此证书有效"
 
 
-#: src/views/certificate/Certificate.vue:145 src/views/domain/cert/Cert.vue:35
+#: src/views/certificate/CertificateEditor.vue:119
+#: src/views/domain/cert/Cert.vue:35
 msgid "Certificate Status"
 msgid "Certificate Status"
 msgstr "证书状态"
 msgstr "证书状态"
 
 
-#: src/routes/index.ts:100 src/views/certificate/Certificate.vue:96
+#: src/routes/index.ts:100 src/views/certificate/Certificate.vue:109
 msgid "Certificates"
 msgid "Certificates"
 msgstr "证书"
 msgstr "证书"
 
 
-#: src/routes/index.ts:108
+#: src/routes/index.ts:109
 msgid "Certificates List"
 msgid "Certificates List"
 msgstr "证书列表"
 msgstr "证书列表"
 
 
-#: src/views/certificate/Certificate.vue:150
-#: src/views/domain/cert/components/AutoCertStepOne.vue:63
+#: src/views/domain/cert/components/AutoCertStepOne.vue:65
 msgid "Challenge Method"
 msgid "Challenge Method"
 msgstr "挑战方法"
 msgstr "挑战方法"
 
 
@@ -236,10 +233,6 @@ msgstr "清空"
 msgid "Comments"
 msgid "Comments"
 msgstr "注释"
 msgstr "注释"
 
 
-#: src/views/certificate/Certificate.vue:41
-msgid "Config Name"
-msgstr "配置文件名称"
-
 #: src/views/domain/ngx_conf/config_template/ConfigTemplate.vue:82
 #: src/views/domain/ngx_conf/config_template/ConfigTemplate.vue:82
 msgid "Config Templates"
 msgid "Config Templates"
 msgstr "配置"
 msgstr "配置"
@@ -294,7 +287,7 @@ msgstr "创建时间"
 msgid "Creating client facilitates communication with the CA server"
 msgid "Creating client facilitates communication with the CA server"
 msgstr "正在创建客户端用于与 CA 服务器通信"
 msgstr "正在创建客户端用于与 CA 服务器通信"
 
 
-#: src/views/domain/cert/components/DNSChallenge.vue:89
+#: src/views/domain/cert/components/DNSChallenge.vue:105
 msgid "Credential"
 msgid "Credential"
 msgstr "DNS 凭证"
 msgstr "DNS 凭证"
 
 
@@ -375,11 +368,10 @@ msgstr "目录"
 msgid "Disable"
 msgid "Disable"
 msgstr "禁用"
 msgstr "禁用"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:128
+#: src/views/domain/cert/components/ObtainCert.vue:78
 msgid "Disable auto-renewal failed for %{name}"
 msgid "Disable auto-renewal failed for %{name}"
 msgstr "关闭 %{name} 自动续签失败"
 msgstr "关闭 %{name} 自动续签失败"
 
 
-#: src/views/certificate/Certificate.vue:57
 #: src/views/domain/cert/ChangeCert.vue:48 src/views/domain/DomainEdit.vue:190
 #: src/views/domain/cert/ChangeCert.vue:48 src/views/domain/DomainEdit.vue:190
 #: src/views/domain/DomainList.vue:123
 #: src/views/domain/DomainList.vue:123
 msgid "Disabled"
 msgid "Disabled"
@@ -394,16 +386,16 @@ msgstr "禁用成功"
 msgid "Disk IO"
 msgid "Disk IO"
 msgstr "磁盘 IO"
 msgstr "磁盘 IO"
 
 
-#: src/routes/index.ts:113 src/views/certificate/DNSCredential.vue:39
+#: src/routes/index.ts:130 src/views/certificate/DNSCredential.vue:39
 msgid "DNS Credentials"
 msgid "DNS Credentials"
 msgstr "DNS 凭证"
 msgstr "DNS 凭证"
 
 
 #: src/views/certificate/DNSChallenge.vue:74
 #: src/views/certificate/DNSChallenge.vue:74
-#: src/views/domain/cert/components/DNSChallenge.vue:79
+#: src/views/domain/cert/components/DNSChallenge.vue:95
 msgid "DNS Provider"
 msgid "DNS Provider"
 msgstr "DNS供应商"
 msgstr "DNS供应商"
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:69
+#: src/views/domain/cert/components/AutoCertStepOne.vue:71
 msgid "DNS01"
 msgid "DNS01"
 msgstr "DNS01"
 msgstr "DNS01"
 
 
@@ -412,7 +404,7 @@ msgid "Do you want to deploy this file to remote server?"
 msgid_plural "Do you want to deploy this file to remote servers?"
 msgid_plural "Do you want to deploy this file to remote servers?"
 msgstr[0] "你想把这个文件部署到远程服务器上吗?"
 msgstr[0] "你想把这个文件部署到远程服务器上吗?"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:207
+#: src/views/domain/cert/components/ObtainCert.vue:146
 msgid "Do you want to disable auto-cert renewal?"
 msgid "Do you want to disable auto-cert renewal?"
 msgstr "你想禁用自动更新证书吗?"
 msgstr "你想禁用自动更新证书吗?"
 
 
@@ -436,7 +428,7 @@ msgstr "你想删除这个服务器吗?"
 msgid "Domain Config Created Successfully"
 msgid "Domain Config Created Successfully"
 msgstr "域名配置文件创建成功"
 msgstr "域名配置文件创建成功"
 
 
-#: src/views/certificate/Certificate.vue:125
+#: src/views/certificate/CertificateEditor.vue:103
 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} 重新打开证书自动续期。"
 
 
@@ -501,7 +493,7 @@ msgstr "在%{node_name}中启用%{conf_name}失败"
 msgid "Enable %{conf_name} in %{node_name} successfully"
 msgid "Enable %{conf_name} in %{node_name} successfully"
 msgstr "成功启用%{node_name}中的%{conf_name}"
 msgstr "成功启用%{node_name}中的%{conf_name}"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:121
+#: src/views/domain/cert/components/ObtainCert.vue:71
 msgid "Enable auto-renewal failed for %{name}"
 msgid "Enable auto-renewal failed for %{name}"
 msgstr "启用 %{name} 自动续签失败"
 msgstr "启用 %{name} 自动续签失败"
 
 
@@ -517,7 +509,6 @@ msgstr "启用成功"
 msgid "Enable TLS"
 msgid "Enable TLS"
 msgstr "启用 TLS"
 msgstr "启用 TLS"
 
 
-#: src/views/certificate/Certificate.vue:53
 #: src/views/domain/cert/ChangeCert.vue:44
 #: src/views/domain/cert/ChangeCert.vue:44
 #: src/views/domain/components/Deploy.vue:89
 #: src/views/domain/components/Deploy.vue:89
 #: src/views/domain/components/RightSettings.vue:75
 #: src/views/domain/components/RightSettings.vue:75
@@ -535,7 +526,7 @@ msgstr "启用成功"
 msgid "Encrypt website with Let's Encrypt"
 msgid "Encrypt website with Let's Encrypt"
 msgstr "用 Let's Encrypt 对网站进行加密"
 msgstr "用 Let's Encrypt 对网站进行加密"
 
 
-#: src/routes/index.ts:151 src/views/environment/Environment.vue:113
+#: src/routes/index.ts:168 src/views/environment/Environment.vue:113
 msgid "Environment"
 msgid "Environment"
 msgstr "环境"
 msgstr "环境"
 
 
@@ -547,7 +538,7 @@ msgstr "环境"
 msgid "Error"
 msgid "Error"
 msgstr "错误"
 msgstr "错误"
 
 
-#: src/routes/index.ts:138 src/views/domain/ngx_conf/LogEntry.vue:86
+#: src/routes/index.ts:155 src/views/domain/ngx_conf/LogEntry.vue:86
 msgid "Error Logs"
 msgid "Error Logs"
 msgstr "错误日志"
 msgstr "错误日志"
 
 
@@ -555,6 +546,10 @@ msgstr "错误日志"
 msgid "Executable Path"
 msgid "Executable Path"
 msgstr "可执行文件路径"
 msgstr "可执行文件路径"
 
 
+#: src/views/certificate/Certificate.vue:84
+msgid "Expired"
+msgstr "已过期"
+
 #: src/views/domain/cert/CertInfo.vue:27
 #: src/views/domain/cert/CertInfo.vue:27
 msgid "Expired At: %{date}"
 msgid "Expired At: %{date}"
 msgstr "过期时间: %{date}"
 msgstr "过期时间: %{date}"
@@ -626,7 +621,7 @@ msgstr "正在生成私钥用于注册账户"
 msgid "Get release information error"
 msgid "Get release information error"
 msgstr "获取发布信息错误"
 msgstr "获取发布信息错误"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:64
+#: src/views/domain/cert/components/ObtainCertLive.vue:68
 msgid "Getting the certificate, please wait..."
 msgid "Getting the certificate, please wait..."
 msgstr "正在获取证书,请稍等..."
 msgstr "正在获取证书,请稍等..."
 
 
@@ -666,7 +661,7 @@ msgstr "HTTP 监听主机"
 msgid "HTTP Port"
 msgid "HTTP Port"
 msgstr "HTTP 监听端口"
 msgstr "HTTP 监听端口"
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:66
+#: src/views/domain/cert/components/AutoCertStepOne.vue:68
 msgid "HTTP01"
 msgid "HTTP01"
 msgstr "HTTP01"
 msgstr "HTTP01"
 
 
@@ -678,7 +673,7 @@ msgstr "初始化核心升级程序错误"
 msgid "Initialing core upgrader"
 msgid "Initialing core upgrader"
 msgstr "初始化核心升级器"
 msgstr "初始化核心升级器"
 
 
-#: src/routes/index.ts:194 src/views/other/Install.vue:139
+#: src/routes/index.ts:211 src/views/other/Install.vue:139
 msgid "Install"
 msgid "Install"
 msgstr "安装"
 msgstr "安装"
 
 
@@ -735,7 +730,11 @@ msgstr "Location"
 msgid "Locations"
 msgid "Locations"
 msgstr "Locations"
 msgstr "Locations"
 
 
-#: src/routes/index.ts:200 src/views/other/Login.vue:147
+#: src/views/certificate/CertificateEditor.vue:156
+msgid "Log"
+msgstr "日志"
+
+#: src/routes/index.ts:217 src/views/other/Login.vue:147
 msgid "Login"
 msgid "Login"
 msgstr "登录"
 msgstr "登录"
 
 
@@ -747,7 +746,7 @@ msgstr "登录成功"
 msgid "Logout successful"
 msgid "Logout successful"
 msgstr "登出成功"
 msgstr "登出成功"
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:51
+#: src/views/domain/cert/components/AutoCertStepOne.vue:54
 msgid ""
 msgid ""
 "Make sure you have configured a reverse proxy for .well-known directory to "
 "Make sure you have configured a reverse proxy for .well-known directory to "
 "HTTPChallengePort before obtaining the certificate."
 "HTTPChallengePort before obtaining the certificate."
@@ -763,7 +762,7 @@ msgstr "配置管理"
 msgid "Manage Sites"
 msgid "Manage Sites"
 msgstr "网站管理"
 msgstr "网站管理"
 
 
-#: src/routes/index.ts:159 src/views/user/User.vue:53
+#: src/routes/index.ts:176 src/views/user/User.vue:53
 msgid "Manage Users"
 msgid "Manage Users"
 msgstr "用户管理"
 msgstr "用户管理"
 
 
@@ -778,10 +777,13 @@ msgstr "内存与存储"
 #: src/components/ChatGPT/ChatGPT.vue:256
 #: src/components/ChatGPT/ChatGPT.vue:256
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:137
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:137
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:336
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:336
-#: src/views/certificate/Certificate.vue:156
 msgid "Modify"
 msgid "Modify"
 msgstr "修改"
 msgstr "修改"
 
 
+#: src/routes/index.ts:114 src/views/certificate/CertificateEditor.vue:76
+msgid "Modify Certificate"
+msgstr "修改证书"
+
 #: src/views/domain/DomainAdd.vue:153
 #: src/views/domain/DomainAdd.vue:153
 msgid "Modify Config"
 msgid "Modify Config"
 msgstr "修改配置文件"
 msgstr "修改配置文件"
@@ -790,7 +792,7 @@ msgstr "修改配置文件"
 msgid "Multi-line Directive"
 msgid "Multi-line Directive"
 msgstr "多行指令"
 msgstr "多行指令"
 
 
-#: src/views/certificate/Certificate.vue:24
+#: src/views/certificate/Certificate.vue:22
 #: src/views/certificate/DNSCredential.vue:13 src/views/config/config.ts:9
 #: src/views/certificate/DNSCredential.vue:13 src/views/config/config.ts:9
 #: src/views/domain/cert/ChangeCert.vue:21
 #: src/views/domain/cert/ChangeCert.vue:21
 #: src/views/domain/components/RightSettings.vue:81
 #: src/views/domain/components/RightSettings.vue:81
@@ -819,7 +821,7 @@ msgstr "上传流量"
 msgid "New version released"
 msgid "New version released"
 msgstr "新版本发布"
 msgstr "新版本发布"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:281
+#: src/views/domain/cert/components/ObtainCert.vue:216
 #: src/views/domain/DomainAdd.vue:140
 #: src/views/domain/DomainAdd.vue:140
 msgid "Next"
 msgid "Next"
 msgstr "下一步"
 msgstr "下一步"
@@ -844,7 +846,7 @@ msgstr "控制 Nginx"
 msgid "Nginx Error Log Path"
 msgid "Nginx Error Log Path"
 msgstr "Nginx 错误日志路径"
 msgstr "Nginx 错误日志路径"
 
 
-#: src/routes/index.ts:128 src/views/nginx_log/NginxLog.vue:145
+#: src/routes/index.ts:145 src/views/nginx_log/NginxLog.vue:145
 msgid "Nginx Log"
 msgid "Nginx Log"
 msgstr "Nginx 日志"
 msgstr "Nginx 日志"
 
 
@@ -868,7 +870,11 @@ msgstr "取消"
 msgid "Node Secret"
 msgid "Node Secret"
 msgstr "节点密钥"
 msgstr "节点密钥"
 
 
-#: src/routes/index.ts:206 src/routes/index.ts:208
+#: src/views/certificate/Certificate.vue:90
+msgid "Not After"
+msgstr "有效期"
+
+#: src/routes/index.ts:223 src/routes/index.ts:225
 msgid "Not Found"
 msgid "Not Found"
 msgstr "找不到页面"
 msgstr "找不到页面"
 
 
@@ -877,11 +883,11 @@ msgid "Not Valid Before: %{date}"
 msgstr "此前无效: %{date}"
 msgstr "此前无效: %{date}"
 
 
 #: src/views/certificate/DNSCredential.vue:48
 #: src/views/certificate/DNSCredential.vue:48
-#: src/views/domain/cert/components/AutoCertStepOne.vue:38
+#: src/views/domain/cert/components/AutoCertStepOne.vue:40
 msgid "Note"
 msgid "Note"
 msgstr "注意"
 msgstr "注意"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:252
+#: src/views/domain/cert/components/ObtainCert.vue:191
 msgid "Obtain certificate"
 msgid "Obtain certificate"
 msgstr "获取证书"
 msgstr "获取证书"
 
 
@@ -900,7 +906,7 @@ msgstr "离线"
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:140
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:140
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:346
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:346
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:104
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:104
-#: src/views/domain/cert/components/ObtainCert.vue:210
+#: src/views/domain/cert/components/ObtainCert.vue:149
 #: src/views/domain/components/Deploy.vue:23
 #: src/views/domain/components/Deploy.vue:23
 #: src/views/domain/components/RightSettings.vue:51
 #: src/views/domain/components/RightSettings.vue:51
 #: src/views/domain/DomainList.vue:144
 #: src/views/domain/DomainList.vue:144
@@ -972,7 +978,7 @@ msgid ""
 "provider."
 "provider."
 msgstr "请填写 DNS 提供商提供的 API 验证凭据。"
 msgstr "请填写 DNS 提供商提供的 API 验证凭据。"
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:55
+#: src/views/domain/cert/components/AutoCertStepOne.vue:58
 msgid ""
 msgid ""
 "Please first add credentials in Certification > DNS Credentials, and then "
 "Please first add credentials in Certification > DNS Credentials, and then "
 "select one of the credentialsbelow to request the API of the DNS provider."
 "select one of the credentialsbelow to request the API of the DNS provider."
@@ -1011,7 +1017,7 @@ msgstr "请至少选择一个节点!"
 msgid "Pre-release"
 msgid "Pre-release"
 msgstr "预发布"
 msgstr "预发布"
 
 
-#: src/routes/index.ts:167 src/views/preference/Preference.vue:85
+#: src/routes/index.ts:184 src/views/preference/Preference.vue:85
 msgid "Preference"
 msgid "Preference"
 msgstr "偏好设置"
 msgstr "偏好设置"
 
 
@@ -1074,6 +1080,15 @@ msgstr "重载中"
 msgid "Reloading nginx"
 msgid "Reloading nginx"
 msgstr "正在重载 Nginx"
 msgstr "正在重载 Nginx"
 
 
+#: src/views/certificate/RenewCert.vue:43
+#: src/views/certificate/RenewCert.vue:47
+msgid "Renew Certificate"
+msgstr "更新证书"
+
+#: src/views/certificate/RenewCert.vue:25
+msgid "Renew successfully"
+msgstr "更新成功"
+
 #: src/language/constants.ts:35
 #: src/language/constants.ts:35
 msgid "Requested with wrong parameters"
 msgid "Requested with wrong parameters"
 msgstr "请求参数错误"
 msgstr "请求参数错误"
@@ -1098,8 +1113,9 @@ msgstr "运行模式"
 msgid "Running"
 msgid "Running"
 msgstr "运行中"
 msgstr "运行中"
 
 
-#: src/components/ChatGPT/ChatGPT.vue:259 src/views/config/ConfigEdit.vue:98
-#: src/views/domain/DomainEdit.vue:268
+#: src/components/ChatGPT/ChatGPT.vue:259
+#: src/views/certificate/CertificateEditor.vue:175
+#: src/views/config/ConfigEdit.vue:98 src/views/domain/DomainEdit.vue:268
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:111
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:111
 #: src/views/preference/Preference.vue:113
 #: src/views/preference/Preference.vue:113
 msgid "Save"
 msgid "Save"
@@ -1115,6 +1131,7 @@ msgid "Save error %{msg}"
 msgstr "保存错误 %{msg}"
 msgstr "保存错误 %{msg}"
 
 
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:42
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:42
+#: src/views/certificate/CertificateEditor.vue:46
 #: src/views/preference/Preference.vue:58
 #: src/views/preference/Preference.vue:58
 msgid "Save successfully"
 msgid "Save successfully"
 msgstr "保存成功"
 msgstr "保存成功"
@@ -1154,24 +1171,32 @@ msgstr "服务器错误"
 msgid "Server Info"
 msgid "Server Info"
 msgstr "服务器信息"
 msgstr "服务器信息"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:165
+#: src/views/domain/cert/components/ObtainCert.vue:115
 msgid "server_name not found in directives"
 msgid "server_name not found in directives"
 msgstr "未在指令集合中找到 server_name"
 msgstr "未在指令集合中找到 server_name"
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:27
+#: src/views/domain/cert/components/AutoCertStepOne.vue:29
 #: src/views/domain/DomainAdd.vue:119
 #: src/views/domain/DomainAdd.vue:119
 msgid "server_name parameter is required"
 msgid "server_name parameter is required"
 msgstr "必须为 server_name 指令指明参数"
 msgstr "必须为 server_name 指令指明参数"
 
 
+#: src/language/constants.ts:15
+msgid "Setting DNS01 challenge provider"
+msgstr "使用 DNS01 Challenge 提供商"
+
 #: src/language/constants.ts:16
 #: src/language/constants.ts:16
 msgid "Setting environment variables"
 msgid "Setting environment variables"
 msgstr "正在设置环境变量"
 msgstr "正在设置环境变量"
 
 
+#: src/language/constants.ts:14
+msgid "Setting HTTP01 challenge provider"
+msgstr "使用 HTTP01 challenge provider"
+
 #: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:54
 #: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:54
 msgid "Single Directive"
 msgid "Single Directive"
 msgstr "单行指令"
 msgstr "单行指令"
 
 
-#: src/routes/index.ts:142
+#: src/routes/index.ts:159
 msgid "Site Logs"
 msgid "Site Logs"
 msgstr "站点列表"
 msgstr "站点列表"
 
 
@@ -1179,19 +1204,19 @@ msgstr "站点列表"
 msgid "Sites List"
 msgid "Sites List"
 msgstr "站点列表"
 msgstr "站点列表"
 
 
-#: src/views/certificate/Certificate.vue:164
+#: src/views/certificate/CertificateEditor.vue:135
 msgid "SSL Certificate Content"
 msgid "SSL Certificate Content"
 msgstr "SSL 证书内容"
 msgstr "SSL 证书内容"
 
 
-#: src/views/certificate/Certificate.vue:171
+#: src/views/certificate/CertificateEditor.vue:142
 msgid "SSL Certificate Key Content"
 msgid "SSL Certificate Key Content"
 msgstr "SSL 证书密钥内容"
 msgstr "SSL 证书密钥内容"
 
 
-#: src/views/certificate/Certificate.vue:73
+#: src/views/certificate/Certificate.vue:63
 msgid "SSL Certificate Key Path"
 msgid "SSL Certificate Key Path"
 msgstr "SSL证书密钥路径"
 msgstr "SSL证书密钥路径"
 
 
-#: src/views/certificate/Certificate.vue:65
+#: src/views/certificate/Certificate.vue:55
 msgid "SSL Certificate Path"
 msgid "SSL Certificate Path"
 msgstr "SSL证书路径"
 msgstr "SSL证书路径"
 
 
@@ -1203,7 +1228,8 @@ msgstr "SSO 登录"
 msgid "Stable"
 msgid "Stable"
 msgstr "稳定"
 msgstr "稳定"
 
 
-#: src/views/domain/DomainList.vue:25 src/views/environment/Environment.vue:78
+#: src/views/certificate/Certificate.vue:71 src/views/domain/DomainList.vue:25
+#: src/views/environment/Environment.vue:78
 msgid "Status"
 msgid "Status"
 msgstr "状态"
 msgstr "状态"
 
 
@@ -1231,7 +1257,7 @@ msgstr "切换到深色主题"
 msgid "Switch to light theme"
 msgid "Switch to light theme"
 msgstr "切换到浅色"
 msgstr "切换到浅色"
 
 
-#: src/routes/index.ts:175
+#: src/routes/index.ts:192
 msgid "System"
 msgid "System"
 msgstr "系统"
 msgstr "系统"
 
 
@@ -1243,7 +1269,7 @@ msgstr "列表"
 msgid "Target"
 msgid "Target"
 msgstr "目标"
 msgstr "目标"
 
 
-#: src/routes/index.ts:120 src/views/pty/Terminal.vue:95
+#: src/routes/index.ts:137 src/views/pty/Terminal.vue:95
 msgid "Terminal"
 msgid "Terminal"
 msgstr "终端"
 msgstr "终端"
 
 
@@ -1251,7 +1277,7 @@ msgstr "终端"
 msgid "Terminal Start Command"
 msgid "Terminal Start Command"
 msgstr "终端启动命令"
 msgstr "终端启动命令"
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:47
+#: src/views/domain/cert/components/AutoCertStepOne.vue:50
 msgid ""
 msgid ""
 "The certificate for the domain will be checked 5 minutes, and will be "
 "The certificate for the domain will be checked 5 minutes, and will be "
 "renewed if it has been more than 1 week since it was last issued."
 "renewed if it has been more than 1 week since it was last issued."
@@ -1263,7 +1289,7 @@ msgstr ""
 msgid "The filename cannot contain the following characters: %{c}"
 msgid "The filename cannot contain the following characters: %{c}"
 msgstr "文件名不能包含以下字符: %{c}"
 msgstr "文件名不能包含以下字符: %{c}"
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:42
+#: src/views/domain/cert/components/AutoCertStepOne.vue:45
 msgid ""
 msgid ""
 "The server_name in the current configuration must be the domain name you "
 "The server_name in the current configuration must be the domain name you "
 "need to get the certificate, supportmultiple domains."
 "need to get the certificate, supportmultiple domains."
@@ -1273,10 +1299,14 @@ msgstr "当前配置中的 server_name 必须是获取证书所需的域名,
 msgid "The username or password is incorrect"
 msgid "The username or password is incorrect"
 msgstr "用户名或密码错误"
 msgstr "用户名或密码错误"
 
 
-#: src/views/certificate/Certificate.vue:115
+#: src/views/certificate/CertificateEditor.vue:93
 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:83
+msgid "This certificate is managed by Nginx UI"
+msgstr "该证书由 Nginx UI 托管"
+
 #: src/components/StdDesign/StdDataEntry/StdFormItem.vue:31
 #: src/components/StdDesign/StdDataEntry/StdFormItem.vue:31
 msgid "This field should not be empty"
 msgid "This field should not be empty"
 msgstr "该字段不能为空"
 msgstr "该字段不能为空"
@@ -1291,11 +1321,10 @@ msgstr ""
 "为了确保认证自动更新能够正常工作,我们需要添加一个能够代理从权威机构到后端的"
 "为了确保认证自动更新能够正常工作,我们需要添加一个能够代理从权威机构到后端的"
 "请求的 Location,并且我们需要保存这个文件并重新加载Nginx。你确定要继续吗?"
 "请求的 Location,并且我们需要保存这个文件并重新加载Nginx。你确定要继续吗?"
 
 
-#: src/views/config/config.ts:14
+#: src/views/certificate/Certificate.vue:39 src/views/config/config.ts:14
 msgid "Type"
 msgid "Type"
 msgstr "类型"
 msgstr "类型"
 
 
-#: src/views/certificate/Certificate.vue:81
 #: src/views/certificate/DNSCredential.vue:26 src/views/config/config.ts:29
 #: src/views/certificate/DNSCredential.vue:26 src/views/config/config.ts:29
 #: src/views/config/ConfigEdit.vue:123
 #: src/views/config/ConfigEdit.vue:123
 #: src/views/domain/components/RightSettings.vue:84
 #: src/views/domain/components/RightSettings.vue:84
@@ -1308,7 +1337,7 @@ msgstr "修改时间"
 msgid "Updated successfully"
 msgid "Updated successfully"
 msgstr "更新成功"
 msgstr "更新成功"
 
 
-#: src/routes/index.ts:186 src/views/system/Upgrade.vue:143
+#: src/routes/index.ts:203 src/views/system/Upgrade.vue:143
 #: src/views/system/Upgrade.vue:235
 #: src/views/system/Upgrade.vue:235
 msgid "Upgrade"
 msgid "Upgrade"
 msgstr "升级"
 msgstr "升级"
@@ -1341,20 +1370,16 @@ msgstr "用户名"
 msgid "Username (*)"
 msgid "Username (*)"
 msgstr "用户名 (*)"
 msgstr "用户名 (*)"
 
 
-#: src/language/constants.ts:15
-msgid "Using DNS01 challenge provider"
-msgstr "使用 DNS01 Challenge 提供商"
-
-#: src/language/constants.ts:14
-msgid "Using HTTP01 challenge provider"
-msgstr "使用 HTTP01 challenge provider"
+#: src/views/certificate/Certificate.vue:80
+msgid "Valid"
+msgstr "有效的"
 
 
 #: src/views/domain/ngx_conf/config_template/ConfigTemplate.vue:101
 #: src/views/domain/ngx_conf/config_template/ConfigTemplate.vue:101
 msgid "View"
 msgid "View"
 msgstr "查看"
 msgstr "查看"
 
 
 #: src/views/config/InspectConfig.vue:36
 #: src/views/config/InspectConfig.vue:36
-#: src/views/domain/cert/components/AutoCertStepOne.vue:21
+#: src/views/domain/cert/components/AutoCertStepOne.vue:23
 #: src/views/domain/DomainAdd.vue:114
 #: src/views/domain/DomainAdd.vue:114
 msgid "Warning"
 msgid "Warning"
 msgstr "警告"
 msgstr "警告"
@@ -1365,7 +1390,7 @@ msgid ""
 "ownership verification."
 "ownership verification."
 msgstr "我们将在您域名的 DNS 记录中添加一个或多个 TXT 记录,以核实域名所有权。"
 msgstr "我们将在您域名的 DNS 记录中添加一个或多个 TXT 记录,以核实域名所有权。"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:208
+#: src/views/domain/cert/components/ObtainCert.vue:147
 msgid ""
 msgid ""
 "We will remove the HTTPChallenge configuration from this file and reload the "
 "We will remove the HTTPChallenge configuration from this file and reload the "
 "Nginx. Are you sure you want to continue?"
 "Nginx. Are you sure you want to continue?"
@@ -1398,6 +1423,18 @@ msgstr "您使用的是最新版本"
 msgid "You can check Nginx UI upgrade at this page."
 msgid "You can check Nginx UI upgrade at this page."
 msgstr "你可以在这个页面检查Nginx UI的升级。"
 msgstr "你可以在这个页面检查Nginx UI的升级。"
 
 
+#~ msgid "Renew certificate"
+#~ msgstr "更新证书"
+
+#~ msgid "Auto Cert is enabled"
+#~ msgstr "自动更新已启用"
+
+#~ msgid "Auto Cert Log"
+#~ msgstr "证书自动续期日志"
+
+#~ msgid "Config Name"
+#~ msgstr "配置文件名称"
+
 #~ msgid "Auto cert is enabled, please do not modify this certification."
 #~ msgid "Auto cert is enabled, please do not modify this certification."
 #~ msgstr "自动更新已启用,请勿修改此证书配置。"
 #~ msgstr "自动更新已启用,请勿修改此证书配置。"
 
 

+ 126 - 81
app/src/language/zh_TW/app.po

@@ -14,15 +14,15 @@ msgstr ""
 "Generated-By: easygettext\n"
 "Generated-By: easygettext\n"
 "X-Generator: Poedit 3.4.1\n"
 "X-Generator: Poedit 3.4.1\n"
 
 
-#: src/routes/index.ts:182
+#: src/routes/index.ts:199
 msgid "About"
 msgid "About"
 msgstr "關於"
 msgstr "關於"
 
 
-#: src/routes/index.ts:134 src/views/domain/ngx_conf/LogEntry.vue:78
+#: src/routes/index.ts:151 src/views/domain/ngx_conf/LogEntry.vue:78
 msgid "Access Logs"
 msgid "Access Logs"
 msgstr "存取日誌"
 msgstr "存取日誌"
 
 
-#: src/views/certificate/Certificate.vue:87
+#: src/views/certificate/Certificate.vue:96
 #: src/views/certificate/DNSCredential.vue:32 src/views/config/config.ts:36
 #: src/views/certificate/DNSCredential.vue:32 src/views/config/config.ts:36
 #: src/views/domain/DomainList.vue:50 src/views/environment/Environment.vue:105
 #: src/views/domain/DomainList.vue:50 src/views/environment/Environment.vue:105
 #: src/views/user/User.vue:46
 #: src/views/user/User.vue:46
@@ -36,6 +36,12 @@ msgstr "操作"
 msgid "Add"
 msgid "Add"
 msgstr "新增"
 msgstr "新增"
 
 
+#: src/routes/index.ts:122 src/views/certificate/Certificate.vue:115
+#: src/views/certificate/CertificateEditor.vue:76
+#, fuzzy
+msgid "Add Certificate"
+msgstr "憑證狀態"
+
 #: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:98
 #: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:98
 msgid "Add Directive Below"
 msgid "Add Directive Below"
 msgstr "在下方新增指令"
 msgstr "在下方新增指令"
@@ -103,33 +109,23 @@ msgstr "助理"
 msgid "Author"
 msgid "Author"
 msgstr "作者"
 msgstr "作者"
 
 
-#: src/views/certificate/Certificate.vue:46
 #: src/views/domain/cert/ChangeCert.vue:37
 #: src/views/domain/cert/ChangeCert.vue:37
 msgid "Auto Cert"
 msgid "Auto Cert"
 msgstr "自動憑證"
 msgstr "自動憑證"
 
 
-#: src/views/certificate/Certificate.vue:105
-#, fuzzy
-msgid "Auto Cert is enabled"
-msgstr "自動憑證"
-
-#: src/views/certificate/Certificate.vue:135
-#, fuzzy
-msgid "Auto Cert Log"
-msgstr "自動憑證日誌"
-
 #: src/views/nginx_log/NginxLog.vue:149
 #: src/views/nginx_log/NginxLog.vue:149
 msgid "Auto Refresh"
 msgid "Auto Refresh"
 msgstr "自動重新整理"
 msgstr "自動重新整理"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:126
+#: src/views/domain/cert/components/ObtainCert.vue:76
 msgid "Auto-renewal disabled for %{name}"
 msgid "Auto-renewal disabled for %{name}"
 msgstr "已關閉 %{name} 的自動續簽"
 msgstr "已關閉 %{name} 的自動續簽"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:119
+#: src/views/domain/cert/components/ObtainCert.vue:69
 msgid "Auto-renewal enabled for %{name}"
 msgid "Auto-renewal enabled for %{name}"
 msgstr "已啟用 %{name} 的自動續簽"
 msgstr "已啟用 %{name} 的自動續簽"
 
 
+#: src/views/certificate/CertificateEditor.vue:168
 #: src/views/config/Config.vue:75 src/views/config/ConfigEdit.vue:89
 #: src/views/config/Config.vue:75 src/views/config/ConfigEdit.vue:89
 #: src/views/domain/DomainEdit.vue:261 src/views/nginx_log/NginxLog.vue:170
 #: src/views/domain/DomainEdit.vue:261 src/views/nginx_log/NginxLog.vue:170
 msgid "Back"
 msgid "Back"
@@ -170,7 +166,7 @@ msgstr "CADir"
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:58
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:58
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:139
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:139
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:103
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:103
-#: src/views/domain/cert/components/ObtainCert.vue:211
+#: src/views/domain/cert/components/ObtainCert.vue:150
 #: src/views/domain/components/Deploy.vue:24
 #: src/views/domain/components/Deploy.vue:24
 #: src/views/domain/components/RightSettings.vue:52
 #: src/views/domain/components/RightSettings.vue:52
 #: src/views/domain/ngx_conf/NgxConfigEditor.vue:216
 #: src/views/domain/ngx_conf/NgxConfigEditor.vue:216
@@ -186,22 +182,22 @@ msgstr "此憑證已過期"
 msgid "Certificate is valid"
 msgid "Certificate is valid"
 msgstr "此憑證有效"
 msgstr "此憑證有效"
 
 
-#: src/views/certificate/Certificate.vue:145 src/views/domain/cert/Cert.vue:35
+#: src/views/certificate/CertificateEditor.vue:119
+#: src/views/domain/cert/Cert.vue:35
 msgid "Certificate Status"
 msgid "Certificate Status"
 msgstr "憑證狀態"
 msgstr "憑證狀態"
 
 
-#: src/routes/index.ts:100 src/views/certificate/Certificate.vue:96
+#: src/routes/index.ts:100 src/views/certificate/Certificate.vue:109
 #, fuzzy
 #, fuzzy
 msgid "Certificates"
 msgid "Certificates"
 msgstr "憑證狀態"
 msgstr "憑證狀態"
 
 
-#: src/routes/index.ts:108
+#: src/routes/index.ts:109
 #, fuzzy
 #, fuzzy
 msgid "Certificates List"
 msgid "Certificates List"
 msgstr "憑證清單"
 msgstr "憑證清單"
 
 
-#: src/views/certificate/Certificate.vue:150
-#: src/views/domain/cert/components/AutoCertStepOne.vue:63
+#: src/views/domain/cert/components/AutoCertStepOne.vue:65
 msgid "Challenge Method"
 msgid "Challenge Method"
 msgstr "驗證方式"
 msgstr "驗證方式"
 
 
@@ -241,10 +237,6 @@ msgstr "清除"
 msgid "Comments"
 msgid "Comments"
 msgstr "備註"
 msgstr "備註"
 
 
-#: src/views/certificate/Certificate.vue:41
-msgid "Config Name"
-msgstr "設定名稱"
-
 #: src/views/domain/ngx_conf/config_template/ConfigTemplate.vue:82
 #: src/views/domain/ngx_conf/config_template/ConfigTemplate.vue:82
 msgid "Config Templates"
 msgid "Config Templates"
 msgstr "設定模板"
 msgstr "設定模板"
@@ -299,7 +291,7 @@ msgstr "建立時間"
 msgid "Creating client facilitates communication with the CA server"
 msgid "Creating client facilitates communication with the CA server"
 msgstr "建立客戶端方便與CA伺服器通訊"
 msgstr "建立客戶端方便與CA伺服器通訊"
 
 
-#: src/views/domain/cert/components/DNSChallenge.vue:89
+#: src/views/domain/cert/components/DNSChallenge.vue:105
 msgid "Credential"
 msgid "Credential"
 msgstr "認證"
 msgstr "認證"
 
 
@@ -382,11 +374,10 @@ msgstr "指令"
 msgid "Disable"
 msgid "Disable"
 msgstr "停用"
 msgstr "停用"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:128
+#: src/views/domain/cert/components/ObtainCert.vue:78
 msgid "Disable auto-renewal failed for %{name}"
 msgid "Disable auto-renewal failed for %{name}"
 msgstr "關閉 %{name} 自動續簽失敗"
 msgstr "關閉 %{name} 自動續簽失敗"
 
 
-#: src/views/certificate/Certificate.vue:57
 #: src/views/domain/cert/ChangeCert.vue:48 src/views/domain/DomainEdit.vue:190
 #: src/views/domain/cert/ChangeCert.vue:48 src/views/domain/DomainEdit.vue:190
 #: src/views/domain/DomainList.vue:123
 #: src/views/domain/DomainList.vue:123
 msgid "Disabled"
 msgid "Disabled"
@@ -401,16 +392,16 @@ msgstr "成功停用"
 msgid "Disk IO"
 msgid "Disk IO"
 msgstr "磁碟 IO"
 msgstr "磁碟 IO"
 
 
-#: src/routes/index.ts:113 src/views/certificate/DNSCredential.vue:39
+#: src/routes/index.ts:130 src/views/certificate/DNSCredential.vue:39
 msgid "DNS Credentials"
 msgid "DNS Credentials"
 msgstr "DNS 認證"
 msgstr "DNS 認證"
 
 
 #: src/views/certificate/DNSChallenge.vue:74
 #: src/views/certificate/DNSChallenge.vue:74
-#: src/views/domain/cert/components/DNSChallenge.vue:79
+#: src/views/domain/cert/components/DNSChallenge.vue:95
 msgid "DNS Provider"
 msgid "DNS Provider"
 msgstr "DNS 供應商"
 msgstr "DNS 供應商"
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:69
+#: src/views/domain/cert/components/AutoCertStepOne.vue:71
 msgid "DNS01"
 msgid "DNS01"
 msgstr "DNS01"
 msgstr "DNS01"
 
 
@@ -419,7 +410,7 @@ msgid "Do you want to deploy this file to remote server?"
 msgid_plural "Do you want to deploy this file to remote servers?"
 msgid_plural "Do you want to deploy this file to remote servers?"
 msgstr[0] "您要將此檔案部署至遠端伺服器嗎?"
 msgstr[0] "您要將此檔案部署至遠端伺服器嗎?"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:207
+#: src/views/domain/cert/components/ObtainCert.vue:146
 msgid "Do you want to disable auto-cert renewal?"
 msgid "Do you want to disable auto-cert renewal?"
 msgstr "您要停用自動憑證續訂嗎?"
 msgstr "您要停用自動憑證續訂嗎?"
 
 
@@ -443,7 +434,7 @@ msgstr "您要移除此伺服器嗎?"
 msgid "Domain Config Created Successfully"
 msgid "Domain Config Created Successfully"
 msgstr "網域設定檔成功建立"
 msgstr "網域設定檔成功建立"
 
 
-#: src/views/certificate/Certificate.vue:125
+#: src/views/certificate/CertificateEditor.vue:103
 #, fuzzy
 #, fuzzy
 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} 的自動憑證"
@@ -509,7 +500,7 @@ msgstr "在 %{node_name} 啟用 %{conf_name} 失敗"
 msgid "Enable %{conf_name} in %{node_name} successfully"
 msgid "Enable %{conf_name} in %{node_name} successfully"
 msgstr "成功在 %{node_name} 啟用 %{conf_name}"
 msgstr "成功在 %{node_name} 啟用 %{conf_name}"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:121
+#: src/views/domain/cert/components/ObtainCert.vue:71
 msgid "Enable auto-renewal failed for %{name}"
 msgid "Enable auto-renewal failed for %{name}"
 msgstr "啟用 %{name} 自動續簽失敗"
 msgstr "啟用 %{name} 自動續簽失敗"
 
 
@@ -525,7 +516,6 @@ msgstr "啟用成功"
 msgid "Enable TLS"
 msgid "Enable TLS"
 msgstr "啟用 TLS"
 msgstr "啟用 TLS"
 
 
-#: src/views/certificate/Certificate.vue:53
 #: src/views/domain/cert/ChangeCert.vue:44
 #: src/views/domain/cert/ChangeCert.vue:44
 #: src/views/domain/components/Deploy.vue:89
 #: src/views/domain/components/Deploy.vue:89
 #: src/views/domain/components/RightSettings.vue:75
 #: src/views/domain/components/RightSettings.vue:75
@@ -543,7 +533,7 @@ msgstr "成功啟用"
 msgid "Encrypt website with Let's Encrypt"
 msgid "Encrypt website with Let's Encrypt"
 msgstr "用 Let's Encrypt 對網站進行加密"
 msgstr "用 Let's Encrypt 對網站進行加密"
 
 
-#: src/routes/index.ts:151 src/views/environment/Environment.vue:113
+#: src/routes/index.ts:168 src/views/environment/Environment.vue:113
 msgid "Environment"
 msgid "Environment"
 msgstr "環境"
 msgstr "環境"
 
 
@@ -555,7 +545,7 @@ msgstr "環境"
 msgid "Error"
 msgid "Error"
 msgstr "錯誤"
 msgstr "錯誤"
 
 
-#: src/routes/index.ts:138 src/views/domain/ngx_conf/LogEntry.vue:86
+#: src/routes/index.ts:155 src/views/domain/ngx_conf/LogEntry.vue:86
 msgid "Error Logs"
 msgid "Error Logs"
 msgstr "錯誤日誌"
 msgstr "錯誤日誌"
 
 
@@ -563,6 +553,10 @@ msgstr "錯誤日誌"
 msgid "Executable Path"
 msgid "Executable Path"
 msgstr "可執行檔路徑"
 msgstr "可執行檔路徑"
 
 
+#: src/views/certificate/Certificate.vue:84
+msgid "Expired"
+msgstr ""
+
 #: src/views/domain/cert/CertInfo.vue:27
 #: src/views/domain/cert/CertInfo.vue:27
 #, fuzzy
 #, fuzzy
 msgid "Expired At: %{date}"
 msgid "Expired At: %{date}"
@@ -635,7 +629,7 @@ msgstr "產生註冊帳號的私鑰"
 msgid "Get release information error"
 msgid "Get release information error"
 msgstr "取得發布資訊錯誤"
 msgstr "取得發布資訊錯誤"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:64
+#: src/views/domain/cert/components/ObtainCertLive.vue:68
 msgid "Getting the certificate, please wait..."
 msgid "Getting the certificate, please wait..."
 msgstr "正在取得憑證,請稍候..."
 msgstr "正在取得憑證,請稍候..."
 
 
@@ -675,7 +669,7 @@ msgstr "HTTP 監聽主機"
 msgid "HTTP Port"
 msgid "HTTP Port"
 msgstr "HTTP 監聽埠"
 msgstr "HTTP 監聽埠"
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:66
+#: src/views/domain/cert/components/AutoCertStepOne.vue:68
 msgid "HTTP01"
 msgid "HTTP01"
 msgstr "HTTP01"
 msgstr "HTTP01"
 
 
@@ -687,7 +681,7 @@ msgstr "初始化核心升級程式錯誤"
 msgid "Initialing core upgrader"
 msgid "Initialing core upgrader"
 msgstr "正在初始化核心升級程式"
 msgstr "正在初始化核心升級程式"
 
 
-#: src/routes/index.ts:194 src/views/other/Install.vue:139
+#: src/routes/index.ts:211 src/views/other/Install.vue:139
 msgid "Install"
 msgid "Install"
 msgstr "安裝"
 msgstr "安裝"
 
 
@@ -746,7 +740,12 @@ msgstr "Location"
 msgid "Locations"
 msgid "Locations"
 msgstr "Locations"
 msgstr "Locations"
 
 
-#: src/routes/index.ts:200 src/views/other/Login.vue:147
+#: src/views/certificate/CertificateEditor.vue:156
+#, fuzzy
+msgid "Log"
+msgstr "登入"
+
+#: src/routes/index.ts:217 src/views/other/Login.vue:147
 msgid "Login"
 msgid "Login"
 msgstr "登入"
 msgstr "登入"
 
 
@@ -758,7 +757,7 @@ msgstr "登入成功"
 msgid "Logout successful"
 msgid "Logout successful"
 msgstr "登出成功"
 msgstr "登出成功"
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:51
+#: src/views/domain/cert/components/AutoCertStepOne.vue:54
 msgid ""
 msgid ""
 "Make sure you have configured a reverse proxy for .well-known directory to "
 "Make sure you have configured a reverse proxy for .well-known directory to "
 "HTTPChallengePort before obtaining the certificate."
 "HTTPChallengePort before obtaining the certificate."
@@ -773,7 +772,7 @@ msgstr "管理設定"
 msgid "Manage Sites"
 msgid "Manage Sites"
 msgstr "管理網站"
 msgstr "管理網站"
 
 
-#: src/routes/index.ts:159 src/views/user/User.vue:53
+#: src/routes/index.ts:176 src/views/user/User.vue:53
 msgid "Manage Users"
 msgid "Manage Users"
 msgstr "管理使用者"
 msgstr "管理使用者"
 
 
@@ -788,10 +787,14 @@ msgstr "記憶體與儲存"
 #: src/components/ChatGPT/ChatGPT.vue:256
 #: src/components/ChatGPT/ChatGPT.vue:256
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:137
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:137
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:336
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:336
-#: src/views/certificate/Certificate.vue:156
 msgid "Modify"
 msgid "Modify"
 msgstr "修改"
 msgstr "修改"
 
 
+#: src/routes/index.ts:114 src/views/certificate/CertificateEditor.vue:76
+#, fuzzy
+msgid "Modify Certificate"
+msgstr "憑證狀態"
+
 #: src/views/domain/DomainAdd.vue:153
 #: src/views/domain/DomainAdd.vue:153
 msgid "Modify Config"
 msgid "Modify Config"
 msgstr "修改設定"
 msgstr "修改設定"
@@ -800,7 +803,7 @@ msgstr "修改設定"
 msgid "Multi-line Directive"
 msgid "Multi-line Directive"
 msgstr "多行指令"
 msgstr "多行指令"
 
 
-#: src/views/certificate/Certificate.vue:24
+#: src/views/certificate/Certificate.vue:22
 #: src/views/certificate/DNSCredential.vue:13 src/views/config/config.ts:9
 #: src/views/certificate/DNSCredential.vue:13 src/views/config/config.ts:9
 #: src/views/domain/cert/ChangeCert.vue:21
 #: src/views/domain/cert/ChangeCert.vue:21
 #: src/views/domain/components/RightSettings.vue:81
 #: src/views/domain/components/RightSettings.vue:81
@@ -829,7 +832,7 @@ msgstr "上傳流量"
 msgid "New version released"
 msgid "New version released"
 msgstr "新版本發布"
 msgstr "新版本發布"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:281
+#: src/views/domain/cert/components/ObtainCert.vue:216
 #: src/views/domain/DomainAdd.vue:140
 #: src/views/domain/DomainAdd.vue:140
 msgid "Next"
 msgid "Next"
 msgstr "下一步"
 msgstr "下一步"
@@ -854,7 +857,7 @@ msgstr "Nginx 控制元件"
 msgid "Nginx Error Log Path"
 msgid "Nginx Error Log Path"
 msgstr "Nginx 錯誤日誌路徑"
 msgstr "Nginx 錯誤日誌路徑"
 
 
-#: src/routes/index.ts:128 src/views/nginx_log/NginxLog.vue:145
+#: src/routes/index.ts:145 src/views/nginx_log/NginxLog.vue:145
 msgid "Nginx Log"
 msgid "Nginx Log"
 msgstr "Nginx 日誌"
 msgstr "Nginx 日誌"
 
 
@@ -878,7 +881,11 @@ msgstr "取消"
 msgid "Node Secret"
 msgid "Node Secret"
 msgstr "Node Secret"
 msgstr "Node Secret"
 
 
-#: src/routes/index.ts:206 src/routes/index.ts:208
+#: src/views/certificate/Certificate.vue:90
+msgid "Not After"
+msgstr ""
+
+#: src/routes/index.ts:223 src/routes/index.ts:225
 msgid "Not Found"
 msgid "Not Found"
 msgstr "找不到頁面"
 msgstr "找不到頁面"
 
 
@@ -887,11 +894,11 @@ msgid "Not Valid Before: %{date}"
 msgstr "此前無效: %{date}"
 msgstr "此前無效: %{date}"
 
 
 #: src/views/certificate/DNSCredential.vue:48
 #: src/views/certificate/DNSCredential.vue:48
-#: src/views/domain/cert/components/AutoCertStepOne.vue:38
+#: src/views/domain/cert/components/AutoCertStepOne.vue:40
 msgid "Note"
 msgid "Note"
 msgstr "備註"
 msgstr "備註"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:252
+#: src/views/domain/cert/components/ObtainCert.vue:191
 msgid "Obtain certificate"
 msgid "Obtain certificate"
 msgstr "取得憑證"
 msgstr "取得憑證"
 
 
@@ -910,7 +917,7 @@ msgstr "離線"
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:140
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:140
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:346
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:346
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:104
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:104
-#: src/views/domain/cert/components/ObtainCert.vue:210
+#: src/views/domain/cert/components/ObtainCert.vue:149
 #: src/views/domain/components/Deploy.vue:23
 #: src/views/domain/components/Deploy.vue:23
 #: src/views/domain/components/RightSettings.vue:51
 #: src/views/domain/components/RightSettings.vue:51
 #: src/views/domain/DomainList.vue:144
 #: src/views/domain/DomainList.vue:144
@@ -982,7 +989,7 @@ msgid ""
 "provider."
 "provider."
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:55
+#: src/views/domain/cert/components/AutoCertStepOne.vue:58
 #, fuzzy
 #, fuzzy
 msgid ""
 msgid ""
 "Please first add credentials in Certification > DNS Credentials, and then "
 "Please first add credentials in Certification > DNS Credentials, and then "
@@ -1022,7 +1029,7 @@ msgstr "請至少選擇一個節點!"
 msgid "Pre-release"
 msgid "Pre-release"
 msgstr "預先發布"
 msgstr "預先發布"
 
 
-#: src/routes/index.ts:167 src/views/preference/Preference.vue:85
+#: src/routes/index.ts:184 src/views/preference/Preference.vue:85
 msgid "Preference"
 msgid "Preference"
 msgstr "偏好設定"
 msgstr "偏好設定"
 
 
@@ -1085,6 +1092,17 @@ msgstr "重新載入中"
 msgid "Reloading nginx"
 msgid "Reloading nginx"
 msgstr "正在重新載入 Nginx"
 msgstr "正在重新載入 Nginx"
 
 
+#: src/views/certificate/RenewCert.vue:43
+#: src/views/certificate/RenewCert.vue:47
+#, fuzzy
+msgid "Renew Certificate"
+msgstr "更換憑證"
+
+#: src/views/certificate/RenewCert.vue:25
+#, fuzzy
+msgid "Renew successfully"
+msgstr "啟用成功"
+
 #: src/language/constants.ts:35
 #: src/language/constants.ts:35
 msgid "Requested with wrong parameters"
 msgid "Requested with wrong parameters"
 msgstr "請求參數錯誤"
 msgstr "請求參數錯誤"
@@ -1109,8 +1127,9 @@ msgstr "執行模式"
 msgid "Running"
 msgid "Running"
 msgstr "執行中"
 msgstr "執行中"
 
 
-#: src/components/ChatGPT/ChatGPT.vue:259 src/views/config/ConfigEdit.vue:98
-#: src/views/domain/DomainEdit.vue:268
+#: src/components/ChatGPT/ChatGPT.vue:259
+#: src/views/certificate/CertificateEditor.vue:175
+#: src/views/config/ConfigEdit.vue:98 src/views/domain/DomainEdit.vue:268
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:111
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:111
 #: src/views/preference/Preference.vue:113
 #: src/views/preference/Preference.vue:113
 msgid "Save"
 msgid "Save"
@@ -1126,6 +1145,7 @@ msgid "Save error %{msg}"
 msgstr "儲存錯誤 %{msg}"
 msgstr "儲存錯誤 %{msg}"
 
 
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:42
 #: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:42
+#: src/views/certificate/CertificateEditor.vue:46
 #: src/views/preference/Preference.vue:58
 #: src/views/preference/Preference.vue:58
 msgid "Save successfully"
 msgid "Save successfully"
 msgstr "儲存成功"
 msgstr "儲存成功"
@@ -1165,24 +1185,34 @@ msgstr "伺服器錯誤"
 msgid "Server Info"
 msgid "Server Info"
 msgstr "伺服器資訊"
 msgstr "伺服器資訊"
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:165
+#: src/views/domain/cert/components/ObtainCert.vue:115
 msgid "server_name not found in directives"
 msgid "server_name not found in directives"
 msgstr "在指令中未找到 server_name"
 msgstr "在指令中未找到 server_name"
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:27
+#: src/views/domain/cert/components/AutoCertStepOne.vue:29
 #: src/views/domain/DomainAdd.vue:119
 #: src/views/domain/DomainAdd.vue:119
 msgid "server_name parameter is required"
 msgid "server_name parameter is required"
 msgstr "必須提供 server_name 參數"
 msgstr "必須提供 server_name 參數"
 
 
+#: src/language/constants.ts:15
+#, fuzzy
+msgid "Setting DNS01 challenge provider"
+msgstr "使用 DNS01 挑戰提供者"
+
 #: src/language/constants.ts:16
 #: src/language/constants.ts:16
 msgid "Setting environment variables"
 msgid "Setting environment variables"
 msgstr "設定環境變數中"
 msgstr "設定環境變數中"
 
 
+#: src/language/constants.ts:14
+#, fuzzy
+msgid "Setting HTTP01 challenge provider"
+msgstr "使用 HTTP01 挑戰提供者"
+
 #: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:54
 #: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:54
 msgid "Single Directive"
 msgid "Single Directive"
 msgstr "單一指令"
 msgstr "單一指令"
 
 
-#: src/routes/index.ts:142
+#: src/routes/index.ts:159
 msgid "Site Logs"
 msgid "Site Logs"
 msgstr "網站日誌"
 msgstr "網站日誌"
 
 
@@ -1190,21 +1220,21 @@ msgstr "網站日誌"
 msgid "Sites List"
 msgid "Sites List"
 msgstr "網站列表"
 msgstr "網站列表"
 
 
-#: src/views/certificate/Certificate.vue:164
+#: src/views/certificate/CertificateEditor.vue:135
 #, fuzzy
 #, fuzzy
 msgid "SSL Certificate Content"
 msgid "SSL Certificate Content"
 msgstr "SSL 認證內容"
 msgstr "SSL 認證內容"
 
 
-#: src/views/certificate/Certificate.vue:171
+#: src/views/certificate/CertificateEditor.vue:142
 #, fuzzy
 #, fuzzy
 msgid "SSL Certificate Key Content"
 msgid "SSL Certificate Key Content"
 msgstr "SSL 憑證金鑰內容"
 msgstr "SSL 憑證金鑰內容"
 
 
-#: src/views/certificate/Certificate.vue:73
+#: src/views/certificate/Certificate.vue:63
 msgid "SSL Certificate Key Path"
 msgid "SSL Certificate Key Path"
 msgstr "SSL 憑證金鑰路徑"
 msgstr "SSL 憑證金鑰路徑"
 
 
-#: src/views/certificate/Certificate.vue:65
+#: src/views/certificate/Certificate.vue:55
 msgid "SSL Certificate Path"
 msgid "SSL Certificate Path"
 msgstr "SSL 憑證路徑"
 msgstr "SSL 憑證路徑"
 
 
@@ -1217,7 +1247,8 @@ msgstr "登入"
 msgid "Stable"
 msgid "Stable"
 msgstr "穩定"
 msgstr "穩定"
 
 
-#: src/views/domain/DomainList.vue:25 src/views/environment/Environment.vue:78
+#: src/views/certificate/Certificate.vue:71 src/views/domain/DomainList.vue:25
+#: src/views/environment/Environment.vue:78
 msgid "Status"
 msgid "Status"
 msgstr "狀態"
 msgstr "狀態"
 
 
@@ -1246,7 +1277,7 @@ msgstr ""
 msgid "Switch to light theme"
 msgid "Switch to light theme"
 msgstr ""
 msgstr ""
 
 
-#: src/routes/index.ts:175
+#: src/routes/index.ts:192
 msgid "System"
 msgid "System"
 msgstr "系統"
 msgstr "系統"
 
 
@@ -1258,7 +1289,7 @@ msgstr "表格"
 msgid "Target"
 msgid "Target"
 msgstr "目標"
 msgstr "目標"
 
 
-#: src/routes/index.ts:120 src/views/pty/Terminal.vue:95
+#: src/routes/index.ts:137 src/views/pty/Terminal.vue:95
 msgid "Terminal"
 msgid "Terminal"
 msgstr "終端機"
 msgstr "終端機"
 
 
@@ -1266,7 +1297,7 @@ msgstr "終端機"
 msgid "Terminal Start Command"
 msgid "Terminal Start Command"
 msgstr "終端機啟動指令"
 msgstr "終端機啟動指令"
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:47
+#: src/views/domain/cert/components/AutoCertStepOne.vue:50
 #, fuzzy
 #, fuzzy
 msgid ""
 msgid ""
 "The certificate for the domain will be checked 5 minutes, and will be "
 "The certificate for the domain will be checked 5 minutes, and will be "
@@ -1279,7 +1310,7 @@ msgstr ""
 msgid "The filename cannot contain the following characters: %{c}"
 msgid "The filename cannot contain the following characters: %{c}"
 msgstr "檔名不能包含以下字元: %{c}"
 msgstr "檔名不能包含以下字元: %{c}"
 
 
-#: src/views/domain/cert/components/AutoCertStepOne.vue:42
+#: src/views/domain/cert/components/AutoCertStepOne.vue:45
 #, fuzzy
 #, fuzzy
 msgid ""
 msgid ""
 "The server_name in the current configuration must be the domain name you "
 "The server_name in the current configuration must be the domain name you "
@@ -1290,11 +1321,15 @@ msgstr "注意:目前設定中的 server_name 必須為需要申請憑證的
 msgid "The username or password is incorrect"
 msgid "The username or password is incorrect"
 msgstr "使用者名稱或密碼不正確"
 msgstr "使用者名稱或密碼不正確"
 
 
-#: src/views/certificate/Certificate.vue:115
+#: src/views/certificate/CertificateEditor.vue:93
 #, fuzzy
 #, fuzzy
 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:83
+msgid "This certificate is managed by Nginx UI"
+msgstr ""
+
 #: src/components/StdDesign/StdDataEntry/StdFormItem.vue:31
 #: src/components/StdDesign/StdDataEntry/StdFormItem.vue:31
 msgid "This field should not be empty"
 msgid "This field should not be empty"
 msgstr "此欄位不應為空"
 msgstr "此欄位不應為空"
@@ -1309,11 +1344,10 @@ msgstr ""
 "為了確保憑證自動續期能夠正常運作,我們需要新增一個 Location 來代理從授權後端"
 "為了確保憑證自動續期能夠正常運作,我們需要新增一個 Location 來代理從授權後端"
 "的請求,我們需要儲存這個檔案並重新載入 Nginx。你確定你要繼續嗎?"
 "的請求,我們需要儲存這個檔案並重新載入 Nginx。你確定你要繼續嗎?"
 
 
-#: src/views/config/config.ts:14
+#: src/views/certificate/Certificate.vue:39 src/views/config/config.ts:14
 msgid "Type"
 msgid "Type"
 msgstr "類型"
 msgstr "類型"
 
 
-#: src/views/certificate/Certificate.vue:81
 #: src/views/certificate/DNSCredential.vue:26 src/views/config/config.ts:29
 #: src/views/certificate/DNSCredential.vue:26 src/views/config/config.ts:29
 #: src/views/config/ConfigEdit.vue:123
 #: src/views/config/ConfigEdit.vue:123
 #: src/views/domain/components/RightSettings.vue:84
 #: src/views/domain/components/RightSettings.vue:84
@@ -1326,7 +1360,7 @@ msgstr "更新時間"
 msgid "Updated successfully"
 msgid "Updated successfully"
 msgstr "更新成功"
 msgstr "更新成功"
 
 
-#: src/routes/index.ts:186 src/views/system/Upgrade.vue:143
+#: src/routes/index.ts:203 src/views/system/Upgrade.vue:143
 #: src/views/system/Upgrade.vue:235
 #: src/views/system/Upgrade.vue:235
 msgid "Upgrade"
 msgid "Upgrade"
 msgstr "升級"
 msgstr "升級"
@@ -1359,20 +1393,16 @@ msgstr "使用者名稱"
 msgid "Username (*)"
 msgid "Username (*)"
 msgstr "使用者名稱 (*)"
 msgstr "使用者名稱 (*)"
 
 
-#: src/language/constants.ts:15
-msgid "Using DNS01 challenge provider"
-msgstr "使用 DNS01 挑戰提供者"
-
-#: src/language/constants.ts:14
-msgid "Using HTTP01 challenge provider"
-msgstr "使用 HTTP01 挑戰提供者"
+#: src/views/certificate/Certificate.vue:80
+msgid "Valid"
+msgstr ""
 
 
 #: src/views/domain/ngx_conf/config_template/ConfigTemplate.vue:101
 #: src/views/domain/ngx_conf/config_template/ConfigTemplate.vue:101
 msgid "View"
 msgid "View"
 msgstr "檢視"
 msgstr "檢視"
 
 
 #: src/views/config/InspectConfig.vue:36
 #: src/views/config/InspectConfig.vue:36
-#: src/views/domain/cert/components/AutoCertStepOne.vue:21
+#: src/views/domain/cert/components/AutoCertStepOne.vue:23
 #: src/views/domain/DomainAdd.vue:114
 #: src/views/domain/DomainAdd.vue:114
 msgid "Warning"
 msgid "Warning"
 msgstr "警告"
 msgstr "警告"
@@ -1383,7 +1413,7 @@ msgid ""
 "ownership verification."
 "ownership verification."
 msgstr ""
 msgstr ""
 
 
-#: src/views/domain/cert/components/ObtainCert.vue:208
+#: src/views/domain/cert/components/ObtainCert.vue:147
 msgid ""
 msgid ""
 "We will remove the HTTPChallenge configuration from this file and reload the "
 "We will remove the HTTPChallenge configuration from this file and reload the "
 "Nginx. Are you sure you want to continue?"
 "Nginx. Are you sure you want to continue?"
@@ -1417,6 +1447,21 @@ msgstr "您正在使用最新版本"
 msgid "You can check Nginx UI upgrade at this page."
 msgid "You can check Nginx UI upgrade at this page."
 msgstr "您可以在此頁面檢查 Nginx UI 的升級。"
 msgstr "您可以在此頁面檢查 Nginx UI 的升級。"
 
 
+#, fuzzy
+#~ msgid "Renew certificate"
+#~ msgstr "取得憑證"
+
+#, fuzzy
+#~ msgid "Auto Cert is enabled"
+#~ msgstr "自動憑證"
+
+#, fuzzy
+#~ msgid "Auto Cert Log"
+#~ msgstr "自動憑證日誌"
+
+#~ msgid "Config Name"
+#~ msgstr "設定名稱"
+
 #~ msgid "Auto cert is enabled, please do not modify this certification."
 #~ msgid "Auto cert is enabled, please do not modify this certification."
 #~ msgstr "自動憑證已啟用,請勿修改此憑證。"
 #~ msgstr "自動憑證已啟用,請勿修改此憑證。"
 
 

+ 17 - 0
app/src/routes/index.ts

@@ -99,6 +99,7 @@ export const routes: Route[] = [
         path: 'certificates',
         path: 'certificates',
         name: () => $gettext('Certificates'),
         name: () => $gettext('Certificates'),
         component: () => import('@/layouts/BaseRouterView.vue'),
         component: () => import('@/layouts/BaseRouterView.vue'),
+        redirect: '/certificates/list',
         meta: {
         meta: {
           icon: SafetyCertificateOutlined,
           icon: SafetyCertificateOutlined,
         },
         },
@@ -108,6 +109,22 @@ export const routes: Route[] = [
             name: () => $gettext('Certificates List'),
             name: () => $gettext('Certificates List'),
             component: () => import('@/views/certificate/Certificate.vue'),
             component: () => import('@/views/certificate/Certificate.vue'),
           },
           },
+          {
+            path: ':id',
+            name: () => $gettext('Modify Certificate'),
+            component: () => import('@/views/certificate/CertificateEditor.vue'),
+            meta: {
+              hiddenInSidebar: true,
+            },
+          },
+          {
+            path: 'add',
+            name: () => $gettext('Add Certificate'),
+            component: () => import('@/views/certificate/CertificateEditor.vue'),
+            meta: {
+              hiddenInSidebar: true,
+            },
+          },
           {
           {
             path: 'dns_credential',
             path: 'dns_credential',
             name: () => $gettext('DNS Credentials'),
             name: () => $gettext('DNS Credentials'),

+ 1 - 1
app/src/version.json

@@ -1 +1 @@
-{"version":"2.0.0-beta.4","build_id":72,"total_build":276}
+{"version":"2.0.0-beta.4","build_id":73,"total_build":277}

+ 44 - 95
app/src/views/certificate/Certificate.vue

@@ -1,18 +1,16 @@
 <script setup lang="tsx">
 <script setup lang="tsx">
 import { useGettext } from 'vue3-gettext'
 import { useGettext } from 'vue3-gettext'
-import { Badge } from 'ant-design-vue'
+import { Badge, Tag } from 'ant-design-vue'
 import { h, provide } from 'vue'
 import { h, provide } from 'vue'
+import dayjs from 'dayjs'
 import { input } from '@/components/StdDesign/StdDataEntry'
 import { input } from '@/components/StdDesign/StdDataEntry'
 import type { customRender } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
 import type { customRender } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
 import { datetime } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
 import { datetime } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
 import cert from '@/api/cert'
 import cert from '@/api/cert'
-import StdCurd from '@/components/StdDesign/StdDataDisplay/StdCurd.vue'
-import CodeEditor from '@/components/CodeEditor/CodeEditor.vue'
-import CertInfo from '@/views/domain/cert/CertInfo.vue'
 import type { Column } from '@/components/StdDesign/types'
 import type { Column } from '@/components/StdDesign/types'
 import type { Cert } from '@/api/cert'
 import type { Cert } from '@/api/cert'
 import { AutoCertState } from '@/constants'
 import { AutoCertState } from '@/constants'
-import AutoCertStepOne from '@/views/domain/cert/components/AutoCertStepOne.vue'
+import StdTable from '@/components/StdDesign/StdDataDisplay/StdTable.vue'
 
 
 const { $gettext } = useGettext()
 const { $gettext } = useGettext()
 
 
@@ -38,24 +36,16 @@ const columns: Column[] = [{
   },
   },
   search: true,
   search: true,
 }, {
 }, {
-  title: () => $gettext('Config Name'),
-  dataIndex: 'filename',
-  sortable: true,
-  pithy: true,
-}, {
-  title: () => $gettext('Auto Cert'),
+  title: () => $gettext('Type'),
   dataIndex: 'auto_cert',
   dataIndex: 'auto_cert',
   customRender: (args: customRender) => {
   customRender: (args: customRender) => {
     const template = []
     const template = []
     const { text } = args
     const { text } = args
-    if (text === true || text > 0) {
-      template.push(<Badge status="success"/>)
-      template.push($gettext('Enabled'))
-    }
-    else {
-      template.push(<Badge status="warning"/>)
-      template.push($gettext('Disabled'))
-    }
+    if (text === true || text > 0)
+      template.push(<Tag bordered={false} color="processing">{$gettext('Managed Certificate')}</Tag>)
+
+    else
+      template.push(<Tag bordered={false} color="purple">{$gettext('General Certificate')}</Tag>)
 
 
     return h('div', template)
     return h('div', template)
   },
   },
@@ -78,8 +68,27 @@ const columns: Column[] = [{
   },
   },
   hidden: true,
   hidden: true,
 }, {
 }, {
-  title: () => $gettext('Updated at'),
-  dataIndex: 'updated_at',
+  title: () => $gettext('Status'),
+  dataIndex: 'certificate_info',
+  customRender: (args: customRender) => {
+    const template = []
+
+    const text = args.text?.not_before && args.text?.not_after && !dayjs().isBefore(args.text?.not_before) && !dayjs().isAfter(args.text?.not_after)
+
+    if (text) {
+      template.push(<Badge status="success"/>)
+      template.push($gettext('Valid'))
+    }
+    else {
+      template.push(<Badge status="error"/>)
+      template.push($gettext('Expired'))
+    }
+
+    return h('div', template)
+  },
+}, {
+  title: () => $gettext('Not After'),
+  dataIndex: ['certificate_info', 'not_after'],
   customRender: datetime,
   customRender: datetime,
   sortable: true,
   sortable: true,
   pithy: true,
   pithy: true,
@@ -88,6 +97,7 @@ const columns: Column[] = [{
   dataIndex: 'action',
   dataIndex: 'action',
 }]
 }]
 
 
+// DO NOT REMOVE THESE LINES
 const no_server_name = computed(() => {
 const no_server_name = computed(() => {
   return false
   return false
 })
 })
@@ -96,82 +106,21 @@ provide('no_server_name', no_server_name)
 </script>
 </script>
 
 
 <template>
 <template>
-  <StdCurd
-    :title="$gettext('Certificates')"
-    :api="cert"
-    :columns="columns"
-    :modal-max-width="600"
-  >
-    <template #beforeEdit="{ data }: {data: Cert}">
-      <template v-if="data.auto_cert === AutoCertState.Enable">
-        <div class="mt-4 mb-4">
-          <AAlert
-            :message="$gettext('Auto Cert is enabled')"
-            type="success"
-            show-icon
-          />
-        </div>
-        <div
-          v-if="!data.filename"
-          class="mt-4 mb-4"
-        >
-          <AAlert
-            :message="$gettext('This Auto Cert item is invalid, please remove it.')"
-            type="error"
-            show-icon
-          />
-        </div>
-        <div
-          v-else-if="!data.domains"
-          class="mt-4 mb-4"
-        >
-          <AAlert
-            :message="$gettext('Domains list is empty, try to reopen Auto Cert for %{config}', { config: data.filename })"
-            type="error"
-            show-icon
-          />
-        </div>
-        <div
-          v-if="data.log"
-          class="mt-4 mb-4"
-        >
-          <AForm layout="vertical">
-            <AFormItem :label="$gettext('Auto Cert Log')">
-              <p>{{ data.log }}</p>
-            </AFormItem>
-          </AForm>
-        </div>
-      </template>
-      <AForm
-        v-if="data.certificate_info"
-        layout="vertical"
+  <ACard :title="$gettext('Certificates')">
+    <template #extra>
+      <AButton
+        type="link"
+        @click="$router.push('/certificates/add')"
       >
       >
-        <AFormItem :label="$gettext('Certificate Status')">
-          <CertInfo :cert="data.certificate_info" />
-        </AFormItem>
-      </AForm>
-
-      <AutoCertStepOne hide-note />
-    </template>
-    <template #edit="{ data }: {data: Cert}">
-      <AForm layout="vertical">
-        <AFormItem :label="$gettext('SSL Certificate Content')">
-          <CodeEditor
-            v-model:content="data.ssl_certificate"
-            default-height="200px"
-            :readonly="!notShowInAutoCert(data)"
-          />
-        </AFormItem>
-        <AFormItem :label="$gettext('SSL Certificate Key Content')">
-          <CodeEditor
-            v-model:content="data.ssl_certificate_key"
-            default-height="200px"
-            :readonly="!notShowInAutoCert(data)"
-          />
-        </AFormItem>
-      </AForm>
+        {{ $gettext('Add Certificate') }}
+      </AButton>
     </template>
     </template>
-  </StdCurd>
+    <StdTable
+      :api="cert"
+      :columns="columns"
+      @click-edit="id => $router.push(`/certificates/${id}`)"
+    />
+  </ACard>
 </template>
 </template>
 
 
 <style lang="less" scoped>
 <style lang="less" scoped>

+ 200 - 0
app/src/views/certificate/CertificateEditor.vue

@@ -0,0 +1,200 @@
+<script setup lang="ts">
+import { useGettext } from 'vue3-gettext'
+import type { Ref } from 'vue'
+import { message } from 'ant-design-vue'
+import { AutoCertState } from '@/constants'
+import CertInfo from '@/views/domain/cert/CertInfo.vue'
+import AutoCertStepOne from '@/views/domain/cert/components/AutoCertStepOne.vue'
+import CodeEditor from '@/components/CodeEditor/CodeEditor.vue'
+import type { Cert } from '@/api/cert'
+import cert from '@/api/cert'
+import FooterToolBar from '@/components/FooterToolbar/FooterToolBar.vue'
+import RenewCert from '@/views/certificate/RenewCert.vue'
+
+const { $gettext } = useGettext()
+
+const route = useRoute()
+
+const id = computed(() => {
+  return Number.parseInt(route.params.id as string)
+})
+
+const data = ref({}) as Ref<Cert>
+
+const notShowInAutoCert = computed(() => {
+  return data.value.auto_cert !== AutoCertState.Enable
+})
+
+function init() {
+  if (id.value > 0) {
+    cert.get(id.value).then(r => {
+      data.value = r
+    })
+  }
+  else {
+    data.value = {} as Cert
+  }
+}
+
+onMounted(() => {
+  init()
+})
+
+function save() {
+  cert.save(data.value.id, data.value).then(r => {
+    data.value = r
+    message.success($gettext('Save successfully'))
+  })
+}
+
+provide('data', data)
+
+provide('no_server_name', computed(() => {
+  return false
+}))
+
+const log = computed(() => {
+  const logs = data.value.log?.split('\n')
+
+  logs.forEach((line, idx, lines) => {
+    const regex = /\[Nginx UI\] (.*)/
+
+    const matches = line.match(regex)
+
+    if (matches && matches.length > 1) {
+      const extractedText = matches[1]
+
+      lines[idx] = line.replaceAll(extractedText, $gettext(extractedText))
+    }
+  })
+
+  return logs.join('\n')
+})
+</script>
+
+<template>
+  <ACard :title="id > 0 ? $gettext('Modify Certificate') : $gettext('Add Certificate')">
+    <div
+      v-if="data.auto_cert === AutoCertState.Enable"
+      class="mb-4"
+    >
+      <div class="mb-2">
+        <AAlert
+          :message="$gettext('This certificate is managed by Nginx UI')"
+          type="success"
+          show-icon
+        />
+      </div>
+      <div
+        v-if="!data.filename"
+        class="mt-4 mb-4"
+      >
+        <AAlert
+          :message="$gettext('This Auto Cert item is invalid, please remove it.')"
+          type="error"
+          show-icon
+        />
+      </div>
+      <div
+        v-else-if="!data.domains"
+        class="mt-4 mb-4"
+      >
+        <AAlert
+          :message="$gettext('Domains list is empty, try to reopen Auto Cert for %{config}', { config: data.filename })"
+          type="error"
+          show-icon
+        />
+      </div>
+    </div>
+
+    <ARow>
+      <ACol
+        :sm="24"
+        :md="12"
+      >
+        <AForm
+          v-if="data.certificate_info"
+          layout="vertical"
+        >
+          <AFormItem :label="$gettext('Certificate Status')">
+            <CertInfo :cert="data.certificate_info" />
+          </AFormItem>
+        </AForm>
+
+        <RenewCert
+          v-if="data.auto_cert === AutoCertState.Enable"
+          @renewed="init"
+        />
+
+        <AutoCertStepOne
+          v-if="data.auto_cert === AutoCertState.Enable"
+          style="max-width: 600px"
+          hide-note
+        />
+        <AForm
+          layout="vertical"
+          style="max-width: 600px"
+        >
+          <AFormItem :label="$gettext('SSL Certificate Path')">
+            <AInput v-model:value="data.ssl_certificate_path" />
+          </AFormItem>
+          <AFormItem :label="$gettext('SSL Certificate Key Path')">
+            <AInput v-model:value="data.ssl_certificate_key_path" />
+          </AFormItem>
+          <AFormItem :label="$gettext('SSL Certificate Content')">
+            <CodeEditor
+              v-model:content="data.ssl_certificate"
+              default-height="300px"
+              :readonly="!notShowInAutoCert"
+            />
+          </AFormItem>
+          <AFormItem :label="$gettext('SSL Certificate Key Content')">
+            <CodeEditor
+              v-model:content="data.ssl_certificate_key"
+              default-height="300px"
+              :readonly="!notShowInAutoCert"
+            />
+          </AFormItem>
+        </AForm>
+      </ACol>
+      <ACol
+        v-if="data.auto_cert === AutoCertState.Enable"
+        :sm="24"
+        :md="12"
+      >
+        <ACard :title="$gettext('Log')">
+          <pre
+            class="log-container"
+            v-html="log"
+          />
+        </ACard>
+      </ACol>
+    </ARow>
+
+    <FooterToolBar>
+      <ASpace>
+        <AButton @click="$router.push('/certificates/list')">
+          {{ $gettext('Back') }}
+        </AButton>
+
+        <AButton
+          type="primary"
+          @click="save"
+        >
+          {{ $gettext('Save') }}
+        </AButton>
+      </ASpace>
+    </FooterToolBar>
+  </ACard>
+</template>
+
+<style scoped lang="less">
+.log-container {
+  overflow: scroll;
+  padding: 5px;
+  margin-bottom: 0;
+
+  font-size: 12px;
+  line-height: 2;
+}
+</style>

+ 68 - 0
app/src/views/certificate/RenewCert.vue

@@ -0,0 +1,68 @@
+<script setup lang="ts">
+import { useGettext } from 'vue3-gettext'
+import type { Ref } from 'vue'
+import { message } from 'ant-design-vue'
+import ObtainCertLive from '@/views/domain/cert/components/ObtainCertLive.vue'
+import type { Cert } from '@/api/cert'
+
+const emit = defineEmits<{
+  renewed: [void]
+}>()
+
+const { $gettext } = useGettext()
+
+const modalVisible = ref(false)
+const modalClosable = ref(true)
+
+const refObtainCertLive = ref()
+
+const data = inject('data') as Ref<Cert>
+
+const issue_cert = () => {
+  modalVisible.value = true
+
+  refObtainCertLive.value.issue_cert(data.value.name, data.value.domains, () => {
+    message.success($gettext('Renew successfully'))
+    emit('renewed')
+  })
+}
+
+const issuing_cert = ref(false)
+
+provide('issuing_cert', issuing_cert)
+</script>
+
+<template>
+  <div>
+    <AButton
+      type="primary"
+      ghost
+      class="mb-6"
+      @click="issue_cert"
+    >
+      {{ $gettext('Renew Certificate') }}
+    </AButton>
+    <AModal
+      v-model:open="modalVisible"
+      :title="$gettext('Renew Certificate')"
+      :mask-closable="modalClosable"
+      :footer="null"
+      :closable="modalClosable"
+      :width="600"
+      force-render
+    >
+      <ObtainCertLive
+        ref="refObtainCertLive"
+        v-model:modal-closable="modalClosable"
+        v-model:modal-visible="modalVisible"
+      />
+    </AModal>
+  </div>
+</template>
+
+<style lang="less" scoped>
+.control-btn {
+  display: flex;
+  justify-content: flex-end;
+}
+</style>

+ 4 - 1
app/src/views/domain/cert/Cert.vue

@@ -34,7 +34,10 @@ const enabled = computed({
     <h2>
     <h2>
       {{ $gettext('Certificate Status') }}
       {{ $gettext('Certificate Status') }}
     </h2>
     </h2>
-    <CertInfo :cert="certInfo" />
+    <CertInfo
+      :cert="certInfo"
+      class="mb-4"
+    />
 
 
     <ChangeCert />
     <ChangeCert />
 
 

+ 1 - 1
app/src/views/domain/cert/CertInfo.vue

@@ -15,7 +15,7 @@ const { $gettext } = useGettext()
 <template>
 <template>
   <div
   <div
     v-if="cert"
     v-if="cert"
-    class="cert-info pb-4"
+    class="cert-info"
   >
   >
     <p>
     <p>
       {{ $gettext('Intermediate Certification Authorities: %{issuer}', { issuer: cert.issuer_name }) }}
       {{ $gettext('Intermediate Certification Authorities: %{issuer}', { issuer: cert.issuer_name }) }}

+ 0 - 21
app/src/views/domain/cert/IssueCert.vue

@@ -67,27 +67,6 @@ async function onchange() {
   </div>
   </div>
 </template>
 </template>
 
 
-<style lang="less">
-.dark {
-  .issue-cert-log-container {
-    background-color: rgba(0, 0, 0, 0.84);
-  }
-}
-.issue-cert-log-container {
-  height: 320px;
-  overflow: scroll;
-  background-color: #f3f3f3;
-  border-radius: 4px;
-  margin-top: 15px;
-  padding: 10px;
-
-  p {
-    font-size: 12px;
-    line-height: 1.3;
-  }
-}
-</style>
-
 <style lang="less" scoped>
 <style lang="less" scoped>
 .ant-tag {
 .ant-tag {
   margin: 0;
   margin: 0;

+ 54 - 51
app/src/views/domain/cert/components/AutoCertStepOne.vue

@@ -1,5 +1,6 @@
 <script setup lang="ts">
 <script setup lang="ts">
 import { useGettext } from 'vue3-gettext'
 import { useGettext } from 'vue3-gettext'
+import type { Ref } from 'vue'
 import type { DnsChallenge } from '@/api/auto_cert'
 import type { DnsChallenge } from '@/api/auto_cert'
 import DNSChallenge from '@/views/domain/cert/components/DNSChallenge.vue'
 import DNSChallenge from '@/views/domain/cert/components/DNSChallenge.vue'
 
 
@@ -12,66 +13,68 @@ const { $gettext } = useGettext()
 const no_server_name = inject('no_server_name')
 const no_server_name = inject('no_server_name')
 
 
 // Provide by ObtainCert.vue
 // Provide by ObtainCert.vue
-const data = inject('data') as DnsChallenge
+const data = inject('data') as Ref<DnsChallenge>
 </script>
 </script>
 
 
 <template>
 <template>
-  <template v-if="no_server_name">
+  <div>
+    <template v-if="no_server_name">
+      <AAlert
+        :message="$gettext('Warning')"
+        type="warning"
+        show-icon
+      >
+        <template #description>
+          <span v-if="no_server_name">
+            {{ $gettext('server_name parameter is required') }}
+          </span>
+        </template>
+      </AAlert>
+      <br>
+    </template>
+
     <AAlert
     <AAlert
-      :message="$gettext('Warning')"
-      type="warning"
+      v-if="!hideNote"
+      type="info"
       show-icon
       show-icon
+      :message="$gettext('Note')"
+      class="mb-4"
     >
     >
       <template #description>
       <template #description>
-        <span v-if="no_server_name">
-          {{ $gettext('server_name parameter is required') }}
-        </span>
+        <p>
+          {{ $gettext('The server_name'
+            + ' in the current configuration must be the domain name you need to get the certificate, support'
+            + 'multiple domains.') }}
+        </p>
+        <p>
+          {{ $gettext('The certificate for the domain will be checked 5 minutes, '
+            + 'and will be renewed if it has been more than 1 week since it was last issued.') }}
+        </p>
+        <p v-if="data.challenge_method === 'http01'">
+          {{ $gettext('Make sure you have configured a reverse proxy for .well-known '
+            + 'directory to HTTPChallengePort before obtaining the certificate.') }}
+        </p>
+        <p v-else-if="data.challenge_method === 'dns01'">
+          {{ $gettext('Please first add credentials in Certification > DNS Credentials, '
+            + 'and then select one of the credentials'
+            + 'below to request the API of the DNS provider.') }}
+        </p>
       </template>
       </template>
     </AAlert>
     </AAlert>
-    <br>
-  </template>
-
-  <AAlert
-    v-if="!hideNote"
-    type="info"
-    show-icon
-    :message="$gettext('Note')"
-    class="mb-4"
-  >
-    <template #description>
-      <p>
-        {{ $gettext('The server_name'
-          + ' in the current configuration must be the domain name you need to get the certificate, support'
-          + 'multiple domains.') }}
-      </p>
-      <p>
-        {{ $gettext('The certificate for the domain will be checked 5 minutes, '
-          + 'and will be renewed if it has been more than 1 week since it was last issued.') }}
-      </p>
-      <p v-if="data.challenge_method === 'http01'">
-        {{ $gettext('Make sure you have configured a reverse proxy for .well-known '
-          + 'directory to HTTPChallengePort before obtaining the certificate.') }}
-      </p>
-      <p v-else-if="data.challenge_method === 'dns01'">
-        {{ $gettext('Please first add credentials in Certification > DNS Credentials, '
-          + 'and then select one of the credentials'
-          + 'below to request the API of the DNS provider.') }}
-      </p>
-    </template>
-  </AAlert>
-  <AForm layout="vertical">
-    <AFormItem :label="$gettext('Challenge Method')">
-      <ASelect v-model:value="data.challenge_method">
-        <ASelectOption value="http01">
-          {{ $gettext('HTTP01') }}
-        </ASelectOption>
-        <ASelectOption value="dns01">
-          {{ $gettext('DNS01') }}
-        </ASelectOption>
-      </ASelect>
-    </AFormItem>
-  </AForm>
-  <DNSChallenge v-if="data.challenge_method === 'dns01'" />
+    <AForm layout="vertical">
+      <AFormItem :label="$gettext('Challenge Method')">
+        <ASelect v-model:value="data.challenge_method">
+          <ASelectOption value="http01">
+            {{ $gettext('HTTP01') }}
+          </ASelectOption>
+          <ASelectOption value="dns01">
+            {{ $gettext('DNS01') }}
+          </ASelectOption>
+        </ASelect>
+      </AFormItem>
+    </AForm>
+    <DNSChallenge v-if="data.challenge_method === 'dns01'" />
+  </div>
 </template>
 </template>
 
 
 <style lang="less" scoped>
 <style lang="less" scoped>

+ 10 - 10
app/src/views/domain/cert/components/DNSChallenge.vue

@@ -14,10 +14,10 @@ const credentials = ref<SelectProps['options']>([])
 // is the object that you are trying to modify it
 // is the object that you are trying to modify it
 // we externalize the dns_credential_id to the parent component,
 // we externalize the dns_credential_id to the parent component,
 // this is used to tell the backend which dns_credential to use
 // this is used to tell the backend which dns_credential to use
-const data = inject('data') as DNSProvider & { dns_credential_id: number | null }
+const data = inject('data') as Ref<DNSProvider & { dns_credential_id: number | null }>
 
 
 const code = computed(() => {
 const code = computed(() => {
-  return data.code
+  return data.value.code
 })
 })
 
 
 const provider_idx = ref()
 const provider_idx = ref()
@@ -38,12 +38,12 @@ watch(code, init)
 
 
 watch(current, () => {
 watch(current, () => {
   credentials.value = []
   credentials.value = []
-  data.code = current.value.code
-  data.provider = current.value.name
+  data.value.code = current.value.code
+  data.value.provider = current.value.name
   if (mounted.value)
   if (mounted.value)
-    data.dns_credential_id = null
+    data.value.dns_credential_id = null
 
 
-  dns_credential.get_list({ provider: data.provider }).then(r => {
+  dns_credential.get_list({ provider: data.value.provider }).then(r => {
     r.data.forEach(v => {
     r.data.forEach(v => {
       credentials.value?.push({
       credentials.value?.push({
         value: v.id,
         value: v.id,
@@ -60,10 +60,10 @@ onMounted(async () => {
     init()
     init()
   })
   })
 
 
-  if (data.dns_credential_id) {
-    await dns_credential.get(data.dns_credential_id).then(r => {
-      data.code = r.code
-      data.provider = r.provider
+  if (data.value.dns_credential_id) {
+    await dns_credential.get(data.value.dns_credential_id).then(r => {
+      data.value.code = r.code
+      data.value.provider = r.provider
       provider_idx.value = providers.value.findIndex(v => v.code === r.code)
       provider_idx.value = providers.value.findIndex(v => v.code === r.code)
     })
     })
   }
   }

+ 19 - 84
app/src/views/domain/cert/components/ObtainCert.vue

@@ -2,13 +2,13 @@
 import { useGettext } from 'vue3-gettext'
 import { useGettext } from 'vue3-gettext'
 import { Modal, message } from 'ant-design-vue'
 import { Modal, message } from 'ant-design-vue'
 import type { Ref } from 'vue'
 import type { Ref } from 'vue'
-import websocket from '@/lib/websocket'
 import template from '@/api/template'
 import template from '@/api/template'
 import domain from '@/api/domain'
 import domain from '@/api/domain'
 import AutoCertStepOne from '@/views/domain/cert/components/AutoCertStepOne.vue'
 import AutoCertStepOne from '@/views/domain/cert/components/AutoCertStepOne.vue'
 import type { NgxConfig, NgxDirective } from '@/api/ngx'
 import type { NgxConfig, NgxDirective } from '@/api/ngx'
 import type { Props } from '@/views/domain/cert/IssueCert.vue'
 import type { Props } from '@/views/domain/cert/IssueCert.vue'
 import type { DnsChallenge } from '@/api/auto_cert'
 import type { DnsChallenge } from '@/api/auto_cert'
+import ObtainCertLive from '@/views/domain/cert/components/ObtainCertLive.vue'
 
 
 const emit = defineEmits(['update:auto_cert'])
 const emit = defineEmits(['update:auto_cert'])
 
 
@@ -20,29 +20,20 @@ const directivesMap = inject('directivesMap') as Ref<Record<string, NgxDirective
 
 
 const [modal, ContextHolder] = Modal.useModal()
 const [modal, ContextHolder] = Modal.useModal()
 
 
-const progressStrokeColor = {
-  from: '#108ee9',
-  to: '#87d068',
-}
-
-const data: DnsChallenge = reactive({
-  dns_credential_id: 0,
+const data = ref({
+  dns_credential_id: null,
   challenge_method: 'http01',
   challenge_method: 'http01',
   code: '',
   code: '',
   configuration: {
   configuration: {
     credentials: {},
     credentials: {},
     additional: {},
     additional: {},
   },
   },
-})
+}) as Ref<DnsChallenge>
 
 
-const progressPercent = ref(0)
-const progressStatus = ref('active')
 const modalClosable = ref(true)
 const modalClosable = ref(true)
 
 
 provide('data', data)
 provide('data', data)
 
 
-const logContainer = ref()
-
 const save_site_config = inject('save_site_config') as () => Promise<void>
 const save_site_config = inject('save_site_config') as () => Promise<void>
 const no_server_name = inject('no_server_name') as Ref<boolean>
 const no_server_name = inject('no_server_name') as Ref<boolean>
 const props = inject('props') as Props
 const props = inject('props') as Props
@@ -54,67 +45,26 @@ const name = computed(() => {
   return directivesMap.value.server_name[0].params.trim()
   return directivesMap.value.server_name[0].params.trim()
 })
 })
 
 
-const issue_cert = async (config_name: string, server_name: string) => {
-  progressStatus.value = 'active'
-  modalClosable.value = false
-  modalVisible.value = true
-  progressPercent.value = 0
-  logContainer.value.innerHTML = ''
-
-  log($gettext('Getting the certificate, please wait...'))
-
-  const ws = websocket(`/api/domain/${config_name}/cert`, false)
-
-  ws.onopen = () => {
-    ws.send(JSON.stringify({
-      server_name: server_name.trim().split(' '),
-      ...data,
-    }))
-  }
-
-  ws.onmessage = m => {
-    const r = JSON.parse(m.data)
-
-    log(r.message)
-
-    // eslint-disable-next-line sonarjs/no-small-switch
-    switch (r.status) {
-      case 'info':
-        // If it's a lego log, do not increase the percent.
-        if (!r.message.includes('[INFO]'))
-          progressPercent.value += 5
+const refObtainCertLive = ref()
 
 
-        break
-      default:
-        modalClosable.value = true
-        issuing_cert.value = false
-
-        if (r.status === 'success' && r.ssl_certificate !== undefined && r.ssl_certificate_key !== undefined) {
-          progressStatus.value = 'success'
-          progressPercent.value = 100
-          callback(r.ssl_certificate, r.ssl_certificate_key)
-          change_auto_cert(true)
-        }
-        else {
-          progressStatus.value = 'exception'
-        }
-        break
-    }
-  }
+const issue_cert = (config_name: string, server_name: string) => {
+  refObtainCertLive.value.issue_cert(config_name, server_name.trim().split(' '), callback)
 }
 }
 
 
 async function callback(ssl_certificate: string, ssl_certificate_key: string) {
 async function callback(ssl_certificate: string, ssl_certificate_key: string) {
   directivesMap.value.ssl_certificate[0].params = ssl_certificate
   directivesMap.value.ssl_certificate[0].params = ssl_certificate
   directivesMap.value.ssl_certificate_key[0].params = ssl_certificate_key
   directivesMap.value.ssl_certificate_key[0].params = ssl_certificate_key
   await save_site_config()
   await save_site_config()
+  change_auto_cert(true)
+  emit('update:auto_cert', true)
 }
 }
 
 
 function change_auto_cert(status: boolean) {
 function change_auto_cert(status: boolean) {
   if (status) {
   if (status) {
     domain.add_auto_cert(props.configName, {
     domain.add_auto_cert(props.configName, {
       domains: name.value.trim().split(' '),
       domains: name.value.trim().split(' '),
-      challenge_method: data.challenge_method,
-      dns_credential_id: data.dns_credential_id,
+      challenge_method: data.value.challenge_method,
+      dns_credential_id: data.value.dns_credential_id,
     }).then(() => {
     }).then(() => {
       message.success(interpolate($gettext('Auto-renewal enabled for %{name}'), { name: name.value }))
       message.success(interpolate($gettext('Auto-renewal enabled for %{name}'), { name: name.value }))
     }).catch(e => {
     }).catch(e => {
@@ -190,17 +140,6 @@ function job() {
     issue_cert(props.configName, name.value)
     issue_cert(props.configName, name.value)
   })
   })
 }
 }
-
-function log(msg: string) {
-  const para = document.createElement('p')
-
-  para.appendChild(document.createTextNode($gettext(msg)))
-
-  logContainer.value.appendChild(para)
-
-  logContainer.value?.scroll({ top: 100000, left: 0, behavior: 'smooth' })
-}
-
 function toggle(status: boolean) {
 function toggle(status: boolean) {
   if (status) {
   if (status) {
     modal.confirm({
     modal.confirm({
@@ -231,10 +170,10 @@ const can_next = computed(() => {
     return false
     return false
   }
   }
   else {
   else {
-    if (data.challenge_method === 'http01')
+    if (data.value.challenge_method === 'http01')
       return true
       return true
-    else if (data.challenge_method === 'dns01')
-      return data?.code ?? false
+    else if (data.value.challenge_method === 'dns01')
+      return data.value?.code ?? false
   }
   }
 })
 })
 
 
@@ -253,21 +192,17 @@ function next() {
       :mask-closable="modalClosable"
       :mask-closable="modalClosable"
       :footer="null"
       :footer="null"
       :closable="modalClosable"
       :closable="modalClosable"
+      :width="600"
       force-render
       force-render
     >
     >
       <template v-if="step === 1">
       <template v-if="step === 1">
         <AutoCertStepOne />
         <AutoCertStepOne />
       </template>
       </template>
       <template v-else-if="step === 2">
       <template v-else-if="step === 2">
-        <AProgress
-          :stroke-color="progressStrokeColor"
-          :percent="progressPercent"
-          :status="progressStatus"
-        />
-
-        <div
-          ref="logContainer"
-          class="issue-cert-log-container"
+        <ObtainCertLive
+          ref="refObtainCertLive"
+          v-model:modal-closable="modalClosable"
+          v-model:modal-visible="modalVisible"
         />
         />
       </template>
       </template>
       <div
       <div

+ 163 - 0
app/src/views/domain/cert/components/ObtainCertLive.vue

@@ -0,0 +1,163 @@
+<script setup lang="ts">
+import type { Ref } from 'vue'
+import { useGettext } from 'vue3-gettext'
+import websocket from '@/lib/websocket'
+import type { DnsChallenge } from '@/api/auto_cert'
+
+const props = defineProps<{
+  modalClosable: boolean
+  modalVisible: boolean
+}>()
+
+const emit = defineEmits<{
+  'update:modalClosable': [value: boolean]
+  'update:modalVisible': [value: boolean]
+}>()
+
+const modalClosable = computed({
+  get() {
+    return props.modalClosable
+  },
+  set(value) {
+    emit('update:modalClosable', value)
+  },
+})
+
+const modalVisible = computed({
+  get() {
+    return props.modalVisible
+  },
+  set(value) {
+    emit('update:modalVisible', value)
+  },
+})
+
+const { $gettext } = useGettext()
+
+const issuing_cert = inject('issuing_cert') as Ref<boolean>
+const data = inject('data') as Ref<DnsChallenge>
+
+const progressStrokeColor = {
+  from: '#108ee9',
+  to: '#87d068',
+}
+
+const progressPercent = ref(0)
+const progressStatus = ref('active')
+
+const logContainer = ref()
+
+function log(msg: string) {
+  const para = document.createElement('p')
+
+  para.appendChild(document.createTextNode($gettext(msg)))
+
+  logContainer.value.appendChild(para)
+
+  logContainer.value?.scroll({ top: 100000, left: 0, behavior: 'smooth' })
+}
+
+const issue_cert = async (config_name: string, server_name: string[],
+  callback?: (ssl_certificate: string, ssl_certificate_key: string) => void) => {
+  progressStatus.value = 'active'
+  modalClosable.value = false
+  modalVisible.value = true
+  progressPercent.value = 0
+  logContainer.value.innerHTML = ''
+
+  log($gettext('Getting the certificate, please wait...'))
+
+  const ws = websocket(`/api/domain/${config_name}/cert`, false)
+
+  ws.onopen = () => {
+    ws.send(JSON.stringify({
+      server_name,
+      ...data.value,
+    }))
+  }
+
+  ws.onmessage = async m => {
+    const r = JSON.parse(m.data)
+
+    const regex = /\[Nginx UI\] (.*)/
+
+    const matches = r.message.match(regex)
+
+    if (matches && matches.length > 1) {
+      const extractedText = matches[1]
+
+      r.message = r.message.replaceAll(extractedText, $gettext(extractedText))
+    }
+
+    log(r.message)
+
+    // eslint-disable-next-line sonarjs/no-small-switch
+    switch (r.status) {
+      case 'info':
+        // If it is a nginx ui log, increase the percent.
+        if (r.message.includes('[Nginx UI]'))
+          progressPercent.value += 5
+
+        break
+      default:
+        modalClosable.value = true
+        issuing_cert.value = false
+
+        if (r.status === 'success' && r.ssl_certificate !== undefined && r.ssl_certificate_key !== undefined) {
+          progressStatus.value = 'success'
+          progressPercent.value = 100
+          if (callback)
+            callback(r.ssl_certificate, r.ssl_certificate_key)
+        }
+        else {
+          progressStatus.value = 'exception'
+        }
+        break
+    }
+  }
+}
+
+defineExpose({
+  issue_cert,
+})
+</script>
+
+<template>
+  <div>
+    <AProgress
+      :stroke-color="progressStrokeColor"
+      :percent="progressPercent"
+      :status="progressStatus"
+    />
+
+    <div
+      ref="logContainer"
+      class="issue-cert-log-container"
+    />
+  </div>
+</template>
+
+<style lang="less">
+.dark {
+  .issue-cert-log-container {
+    background-color: rgba(0, 0, 0, 0.84);
+  }
+}
+.issue-cert-log-container {
+  height: 320px;
+  overflow: scroll;
+  background-color: #f3f3f3;
+  border-radius: 4px;
+  margin-top: 15px;
+  padding: 10px;
+
+  p {
+    font-size: 12px;
+    line-height: 1.3;
+  }
+}
+</style>
+
+<style scoped lang="less">
+
+</style>

+ 1 - 1
app/version.json

@@ -1 +1 @@
-{"version":"2.0.0-beta.4","build_id":72,"total_build":276}
+{"version":"2.0.0-beta.4","build_id":73,"total_build":277}

+ 49 - 97
internal/cert/auto_cert.go

@@ -1,128 +1,80 @@
 package cert
 package cert
 
 
 import (
 import (
-	"fmt"
 	"github.com/0xJacky/Nginx-UI/internal/logger"
 	"github.com/0xJacky/Nginx-UI/internal/logger"
 	"github.com/0xJacky/Nginx-UI/model"
 	"github.com/0xJacky/Nginx-UI/model"
 	"github.com/pkg/errors"
 	"github.com/pkg/errors"
+	"strings"
 	"time"
 	"time"
 )
 )
 
 
-func handleIssueCertLogChan(logChan chan string) {
+func AutoObtain() {
 	defer func() {
 	defer func() {
 		if err := recover(); err != nil {
 		if err := recover(); err != nil {
-			logger.Error(err)
+			logger.Error("AutoCert Recover", err)
 		}
 		}
 	}()
 	}()
-
-	for logString := range logChan {
-		logger.Info("Auto Cert", logString)
+	logger.Info("AutoCert Worker Started")
+	autoCertList := model.GetAutoCertList()
+	for _, certModel := range autoCertList {
+		certModel := certModel
+		renew(certModel)
 	}
 	}
+	logger.Info("AutoCert Worker End")
 }
 }
 
 
-type AutoCertErrorLog struct {
-	buffer []string
-	cert   *model.Cert
-}
-
-func (t *AutoCertErrorLog) SetCertModel(cert *model.Cert) {
-	t.cert = cert
-}
-
-func (t *AutoCertErrorLog) Push(text string, err error) {
-	t.buffer = append(t.buffer, text+" "+err.Error())
-	logger.Error("AutoCert", text, err)
-}
+func renew(certModel *model.Cert) {
+	confName := certModel.Filename
 
 
-func (t *AutoCertErrorLog) Exit(text string, err error) {
-	t.buffer = append(t.buffer, text+" "+err.Error())
-	logger.Error("AutoCert", text, err)
+	log := &Logger{}
+	log.SetCertModel(certModel)
+	defer log.Exit()
 
 
-	if t.cert == nil {
+	if len(certModel.Filename) == 0 {
+		log.Error(errors.New("filename is empty"))
 		return
 		return
 	}
 	}
 
 
-	_ = t.cert.Updates(&model.Cert{
-		Log: t.ToString(),
-	})
-}
-
-func (t *AutoCertErrorLog) ToString() (content string) {
-
-	for _, v := range t.buffer {
-		content += fmt.Sprintf("[Error] %s\n", v)
+	if len(certModel.Domains) == 0 {
+		log.Error(errors.New("domains list is empty, " +
+			"try to reopen auto-cert for this config:" + confName))
+		return
 	}
 	}
 
 
-	return
-}
-
-func AutoObtain() {
-	defer func() {
-		if err := recover(); err != nil {
-			logger.Error("AutoCert Recover", err)
-		}
-	}()
-	logger.Info("AutoCert Worker Started")
-	autoCertList := model.GetAutoCertList()
-	for _, certModel := range autoCertList {
-		confName := certModel.Filename
-
-		errLog := &AutoCertErrorLog{}
-		errLog.SetCertModel(certModel)
-
-		if len(certModel.Filename) == 0 {
-			errLog.Exit("", errors.New("filename is empty"))
-			continue
-		}
-
-		if len(certModel.Domains) == 0 {
-			errLog.Exit(confName, errors.New("domains list is empty, "+
-				"try to reopen auto-cert for this config:"+confName))
-			continue
+	if certModel.SSLCertificatePath != "" {
+		cert, err := GetCertInfo(certModel.SSLCertificatePath)
+		if err != nil {
+			// Get certificate info error, ignore this certificate
+			log.Error(errors.Wrap(err, "get certificate info error"))
+			return
 		}
 		}
-
-		if certModel.SSLCertificatePath != "" {
-			cert, err := GetCertInfo(certModel.SSLCertificatePath)
-			if err != nil {
-				errLog.Push("get cert info", err)
-				// Get certificate info error, ignore this domain
-				continue
-			}
-			// every week
-			if time.Now().Sub(cert.NotBefore).Hours()/24 < 7 {
-				continue
-			}
+		if time.Now().Sub(cert.NotBefore).Hours()/24 < 7 {
+			// not between 1 week, ignore this certificate
+			return
 		}
 		}
-		// after 1 mo, reissue certificate
-		logChan := make(chan string, 1)
-		errChan := make(chan error, 1)
-
-		// support SAN certification
-		payload := &ConfigPayload{
-			ServerName:      certModel.Domains,
-			ChallengeMethod: certModel.ChallengeMethod,
-			DNSCredentialID: certModel.DnsCredentialID,
-		}
-
-		// logChan and errChan should be closed inside IssueCert
-		go IssueCert(payload, logChan, errChan)
+	}
+	// after 1 mo, reissue certificate
+	logChan := make(chan string, 1)
+	errChan := make(chan error, 1)
+
+	// support SAN certification
+	payload := &ConfigPayload{
+		ServerName:      certModel.Domains,
+		ChallengeMethod: certModel.ChallengeMethod,
+		DNSCredentialID: certModel.DnsCredentialID,
+	}
 
 
-		go handleIssueCertLogChan(logChan)
+	// errChan will be closed inside IssueCert
+	go IssueCert(payload, logChan, errChan)
 
 
-		// block, unless errChan closed
-		for err := range errChan {
-			errLog.Push("issue cert", err)
+	go func() {
+		for logString := range logChan {
+			log.Info(strings.TrimSpace(logString))
 		}
 		}
+	}()
 
 
-		logStr := errLog.ToString()
-		if logStr != "" {
-			// store error log to db
-			_ = certModel.Updates(&model.Cert{
-				Log: errLog.ToString(),
-			})
-		} else {
-			certModel.ClearLog()
-		}
+	// block, unless errChan closed
+	for err := range errChan {
+		log.Error(err)
 	}
 	}
-	logger.Info("AutoCert Worker End")
 }
 }

+ 203 - 235
internal/cert/cert.go

@@ -1,248 +1,216 @@
 package cert
 package cert
 
 
 import (
 import (
-	"crypto"
-	"crypto/ecdsa"
-	"crypto/elliptic"
-	"crypto/rand"
-	"crypto/tls"
-	"github.com/0xJacky/Nginx-UI/internal/cert/dns"
-	"github.com/0xJacky/Nginx-UI/internal/logger"
-	"github.com/0xJacky/Nginx-UI/internal/nginx"
-	"github.com/0xJacky/Nginx-UI/query"
-	"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/challenge/http01"
-	"github.com/go-acme/lego/v4/lego"
-	lego_log "github.com/go-acme/lego/v4/log"
-	dns_providers "github.com/go-acme/lego/v4/providers/dns"
-	"github.com/go-acme/lego/v4/registration"
-	"github.com/pkg/errors"
-	"io"
-	"log"
-	"net/http"
-	"os"
-	"path/filepath"
-	"strings"
+    "crypto/ecdsa"
+    "crypto/elliptic"
+    "crypto/rand"
+    "crypto/tls"
+    "github.com/0xJacky/Nginx-UI/internal/cert/dns"
+    "github.com/0xJacky/Nginx-UI/internal/logger"
+    "github.com/0xJacky/Nginx-UI/internal/nginx"
+    "github.com/0xJacky/Nginx-UI/query"
+    "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/challenge/http01"
+    "github.com/go-acme/lego/v4/lego"
+    legolog "github.com/go-acme/lego/v4/log"
+    dnsproviders "github.com/go-acme/lego/v4/providers/dns"
+    "github.com/go-acme/lego/v4/registration"
+    "github.com/pkg/errors"
+    "log"
+    "net/http"
+    "os"
+    "path/filepath"
+    "strings"
+    "time"
 )
 )
 
 
 const (
 const (
-	HTTP01 = "http01"
-	DNS01  = "dns01"
+    HTTP01 = "http01"
+    DNS01  = "dns01"
 )
 )
 
 
-// MyUser You'll need a user or account type that implements acme.User
-type MyUser struct {
-	Email        string
-	Registration *registration.Resource
-	Key          crypto.PrivateKey
-}
-
-func (u *MyUser) GetEmail() string {
-	return u.Email
-}
-
-func (u *MyUser) GetRegistration() *registration.Resource {
-	return u.Registration
-}
-
-func (u *MyUser) GetPrivateKey() crypto.PrivateKey {
-	return u.Key
-}
-
 type ConfigPayload struct {
 type ConfigPayload struct {
-	ServerName      []string `json:"server_name"`
-	ChallengeMethod string   `json:"challenge_method"`
-	DNSCredentialID int      `json:"dns_credential_id"`
-}
-
-type channelWriter struct {
-	ch chan []byte
-}
-
-func (cw *channelWriter) Write(p []byte) (n int, err error) {
-	n = len(p)
-	temp := make([]byte, n)
-	copy(temp, p)
-	cw.ch <- temp
-	return n, nil
+    ServerName      []string `json:"server_name"`
+    ChallengeMethod string   `json:"challenge_method"`
+    DNSCredentialID int      `json:"dns_credential_id"`
 }
 }
 
 
 func IssueCert(payload *ConfigPayload, logChan chan string, errChan chan error) {
 func IssueCert(payload *ConfigPayload, logChan chan string, errChan chan error) {
-	defer func() {
-		if err := recover(); err != nil {
-			logger.Error(err)
-		}
-	}()
-
-	defer close(logChan)
-	defer close(errChan)
-
-	// Use a channel to receive lego log
-	logChannel := make(chan []byte, 1024)
-	defer close(logChannel)
-
-	domain := payload.ServerName
-
-	// Create a user. New accounts need an email and private key to start.
-	logChan <- "Generating private key for registering account"
-	privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
-	if err != nil {
-		errChan <- errors.Wrap(err, "issue cert generate key error")
-		return
-	}
-
-	logChan <- "Preparing lego configurations"
-	myUser := MyUser{
-		Email: settings.ServerSettings.Email,
-		Key:   privateKey,
-	}
-
-	// Hijack the (logger) of lego
-	cw := &channelWriter{ch: logChannel}
-	multiWriter := io.MultiWriter(os.Stderr, cw)
-	l := log.New(os.Stderr, "", log.LstdFlags)
-	l.SetOutput(multiWriter)
-	lego_log.Logger = l
-
-	// Start a goroutine to fetch and process logs from channel
-	go func() {
-		for msg := range logChannel {
-			logChan <- string(msg)
-		}
-	}()
-
-	config := lego.NewConfig(&myUser)
-
-	if settings.ServerSettings.Demo {
-		config.CADirURL = "https://acme-staging-v02.api.letsencrypt.org/directory"
-	}
-
-	if settings.ServerSettings.CADir != "" {
-		config.CADirURL = settings.ServerSettings.CADir
-		if config.HTTPClient != nil {
-			config.HTTPClient.Transport = &http.Transport{
-				TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
-			}
-		}
-	}
-
-	config.Certificate.KeyType = certcrypto.RSA2048
-
-	logChan <- "Creating client facilitates communication with the CA server"
-	// A client facilitates communication with the CA server.
-	client, err := lego.NewClient(config)
-	if err != nil {
-		errChan <- errors.Wrap(err, "issue cert new client error")
-		return
-	}
-
-	switch payload.ChallengeMethod {
-	default:
-		fallthrough
-	case HTTP01:
-		logChan <- "Using HTTP01 challenge provider"
-		err = client.Challenge.SetHTTP01Provider(
-			http01.NewProviderServer("",
-				settings.ServerSettings.HTTPChallengePort,
-			),
-		)
-	case DNS01:
-		d := query.DnsCredential
-		dnsCredential, err := d.FirstByID(payload.DNSCredentialID)
-		if err != nil {
-			errChan <- errors.Wrap(err, "get dns credential error")
-			return
-		}
-
-		logChan <- "Using DNS01 challenge provider"
-		code := dnsCredential.Config.Code
-		pConfig, ok := dns.GetProvider(code)
-
-		if !ok {
-			errChan <- errors.Wrap(err, "provider not found")
-		}
-		logChan <- "Setting environment variables"
-		if dnsCredential.Config.Configuration != nil {
-			err = pConfig.SetEnv(*dnsCredential.Config.Configuration)
-			if err != nil {
-				break
-			}
-			defer func() {
-				logChan <- "Cleaning environment variables"
-				pConfig.CleanEnv()
-			}()
-			provider, err := dns_providers.NewDNSChallengeProviderByName(code)
-			if err != nil {
-				break
-			}
-			err = client.Challenge.SetDNS01Provider(provider)
-		} else {
-			errChan <- errors.Wrap(err, "environment configuration is empty")
-			return
-		}
-
-	}
-
-	if err != nil {
-		errChan <- errors.Wrap(err, "fail to challenge")
-		return
-	}
-
-	// New users will need to register
-	logChan <- "Registering user"
-	reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
-	if err != nil {
-		errChan <- errors.Wrap(err, "fail to register")
-		return
-	}
-	myUser.Registration = reg
-
-	request := certificate.ObtainRequest{
-		Domains: domain,
-		Bundle:  true,
-	}
-
-	logChan <- "Obtaining certificate"
-	certificates, err := client.Certificate.Obtain(request)
-	if err != nil {
-		errChan <- errors.Wrap(err, "fail to obtain")
-		return
-	}
-	name := strings.Join(domain, "_")
-	saveDir := nginx.GetConfPath("ssl/" + name)
-	if _, err = os.Stat(saveDir); os.IsNotExist(err) {
-		err = os.MkdirAll(saveDir, 0755)
-		if err != nil {
-			errChan <- errors.Wrap(err, "fail to mkdir")
-			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.
-	logChan <- "Writing certificate to disk"
-	err = os.WriteFile(filepath.Join(saveDir, "fullchain.cer"),
-		certificates.Certificate, 0644)
-
-	if err != nil {
-		errChan <- errors.Wrap(err, "error issue cert write fullchain.cer")
-		return
-	}
-
-	logChan <- "Writing certificate private key to disk"
-	err = os.WriteFile(filepath.Join(saveDir, "private.key"),
-		certificates.PrivateKey, 0644)
-
-	if err != nil {
-		errChan <- errors.Wrap(err, "fail to write key")
-		return
-	}
-
-	logChan <- "Reloading nginx"
-
-	nginx.Reload()
-
-	logChan <- "Finished"
+    defer func() {
+        if err := recover(); err != nil {
+            logger.Error(err)
+        }
+    }()
+
+    // initial a channelWriter to receive logs
+    cw := NewChannelWriter()
+    defer close(errChan)
+
+    // initial a logger
+    l := log.New(os.Stderr, "", log.LstdFlags)
+    l.SetOutput(cw)
+
+    // Hijack the (logger) of lego
+    legolog.Logger = l
+
+    domain := payload.ServerName
+
+    // Create a user. New accounts need an email and private key to start.
+    l.Println("[INFO] [Nginx UI] Generating private key for registering account")
+    privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+    if err != nil {
+        errChan <- errors.Wrap(err, "issue cert generate key error")
+        return
+    }
+
+    l.Println("[INFO] [Nginx UI] Preparing lego configurations")
+    user := User{
+        Email: settings.ServerSettings.Email,
+        Key:   privateKey,
+    }
+
+    // Start a goroutine to fetch and process logs from channel
+    go func() {
+        for msg := range cw.Ch {
+            logChan <- string(msg)
+        }
+    }()
+
+    config := lego.NewConfig(&user)
+
+    if settings.ServerSettings.Demo {
+        config.CADirURL = "https://acme-staging-v02.api.letsencrypt.org/directory"
+    }
+
+    if settings.ServerSettings.CADir != "" {
+        config.CADirURL = settings.ServerSettings.CADir
+        if config.HTTPClient != nil {
+            config.HTTPClient.Transport = &http.Transport{
+                TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
+            }
+        }
+    }
+
+    config.Certificate.KeyType = certcrypto.RSA2048
+
+    l.Println("[INFO] [Nginx UI] Creating client facilitates communication with the CA server")
+    // A client facilitates communication with the CA server.
+    client, err := lego.NewClient(config)
+    if err != nil {
+        errChan <- errors.Wrap(err, "issue cert new client error")
+        return
+    }
+
+    switch payload.ChallengeMethod {
+    default:
+        fallthrough
+    case HTTP01:
+        l.Println("[INFO] [Nginx UI] Setting HTTP01 challenge provider")
+        err = client.Challenge.SetHTTP01Provider(
+            http01.NewProviderServer("",
+                settings.ServerSettings.HTTPChallengePort,
+            ),
+        )
+    case DNS01:
+        d := query.DnsCredential
+        dnsCredential, err := d.FirstByID(payload.DNSCredentialID)
+        if err != nil {
+            errChan <- errors.Wrap(err, "get dns credential error")
+            return
+        }
+
+        l.Println("[INFO] [Nginx UI] Setting DNS01 challenge provider")
+        code := dnsCredential.Config.Code
+        pConfig, ok := dns.GetProvider(code)
+
+        if !ok {
+            errChan <- errors.Wrap(err, "provider not found")
+        }
+        l.Println("[INFO] [Nginx UI] Setting environment variables")
+        if dnsCredential.Config.Configuration != nil {
+            err = pConfig.SetEnv(*dnsCredential.Config.Configuration)
+            if err != nil {
+                break
+            }
+            defer func() {
+                pConfig.CleanEnv()
+                l.Println("[INFO] [Nginx UI] Cleaned environment variables")
+            }()
+            provider, err := dnsproviders.NewDNSChallengeProviderByName(code)
+            if err != nil {
+                break
+            }
+            err = client.Challenge.SetDNS01Provider(provider)
+        } else {
+            errChan <- errors.Wrap(err, "environment configuration is empty")
+            return
+        }
+
+    }
+
+    if err != nil {
+        errChan <- errors.Wrap(err, "challenge error")
+        return
+    }
+
+    // New users will need to register
+    l.Println("[INFO] [Nginx UI] Registering user")
+    reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
+    if err != nil {
+        errChan <- errors.Wrap(err, "register error")
+        return
+    }
+    user.Registration = reg
+
+    request := certificate.ObtainRequest{
+        Domains: domain,
+        Bundle:  true,
+    }
+
+    l.Println("[INFO] [Nginx UI] Obtaining certificate")
+    certificates, err := client.Certificate.Obtain(request)
+    if err != nil {
+        errChan <- errors.Wrap(err, "obtain certificate error")
+        return
+    }
+    name := strings.Join(domain, "_")
+    saveDir := nginx.GetConfPath("ssl/" + name)
+    if _, err = os.Stat(saveDir); os.IsNotExist(err) {
+        err = os.MkdirAll(saveDir, 0755)
+        if err != nil {
+            errChan <- errors.Wrap(err, "mkdir error")
+            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.
+    l.Println("[INFO] [Nginx UI] Writing certificate to disk")
+    err = os.WriteFile(filepath.Join(saveDir, "fullchain.cer"),
+        certificates.Certificate, 0644)
+
+    if err != nil {
+        errChan <- errors.Wrap(err, "write fullchain.cer error")
+        return
+    }
+
+    l.Println("[INFO] [Nginx UI] Writing certificate private key to disk")
+    err = os.WriteFile(filepath.Join(saveDir, "private.key"),
+        certificates.PrivateKey, 0644)
+
+    if err != nil {
+        errChan <- errors.Wrap(err, "write private.key error")
+        return
+    }
+
+    l.Println("[INFO] [Nginx UI] Reloading nginx")
+
+    nginx.Reload()
+
+    l.Println("[INFO] [Nginx UI] Finished")
+
+    // Wait log to be written
+    time.Sleep(5 * time.Second)
 }
 }

+ 17 - 2
internal/cert/cert_info.go

@@ -5,9 +5,17 @@ import (
 	"encoding/pem"
 	"encoding/pem"
 	"github.com/pkg/errors"
 	"github.com/pkg/errors"
 	"os"
 	"os"
+	"time"
 )
 )
 
 
-func GetCertInfo(sslCertificatePath string) (cert *x509.Certificate, err error) {
+type Info struct {
+	SubjectName string    `json:"subject_name"`
+	IssuerName  string    `json:"issuer_name"`
+	NotAfter    time.Time `json:"not_after"`
+	NotBefore   time.Time `json:"not_before"`
+}
+
+func GetCertInfo(sslCertificatePath string) (info *Info, err error) {
 	certData, err := os.ReadFile(sslCertificatePath)
 	certData, err := os.ReadFile(sslCertificatePath)
 
 
 	if err != nil {
 	if err != nil {
@@ -22,12 +30,19 @@ func GetCertInfo(sslCertificatePath string) (cert *x509.Certificate, err error)
 		return
 		return
 	}
 	}
 
 
-	cert, err = x509.ParseCertificate(block.Bytes)
+	cert, err := x509.ParseCertificate(block.Bytes)
 
 
 	if err != nil {
 	if err != nil {
 		err = errors.Wrap(err, "certificate parsing error")
 		err = errors.Wrap(err, "certificate parsing error")
 		return
 		return
 	}
 	}
 
 
+	info = &Info{
+		SubjectName: cert.Subject.CommonName,
+		IssuerName:  cert.Issuer.CommonName,
+		NotAfter:    cert.NotAfter,
+		NotBefore:   cert.NotBefore,
+	}
+
 	return
 	return
 }
 }

+ 43 - 0
internal/cert/issue.go

@@ -0,0 +1,43 @@
+package cert
+
+import (
+    "crypto"
+    "github.com/go-acme/lego/v4/registration"
+)
+
+type ChannelWriter struct {
+    Ch chan []byte
+}
+
+func NewChannelWriter() *ChannelWriter {
+    return &ChannelWriter{
+        Ch: make(chan []byte, 1024),
+    }
+}
+
+func (cw *ChannelWriter) Write(p []byte) (n int, err error) {
+    n = len(p)
+    temp := make([]byte, n)
+    copy(temp, p)
+    cw.Ch <- temp
+    return n, nil
+}
+
+// User You'll need a user or account type that implements acme.User
+type User struct {
+    Email        string
+    Registration *registration.Resource
+    Key          crypto.PrivateKey
+}
+
+func (u *User) GetEmail() string {
+    return u.Email
+}
+
+func (u *User) GetRegistration() *registration.Resource {
+    return u.Registration
+}
+
+func (u *User) GetPrivateKey() crypto.PrivateKey {
+    return u.Key
+}

+ 46 - 0
internal/cert/logger.go

@@ -0,0 +1,46 @@
+package cert
+
+import (
+	"fmt"
+	"github.com/0xJacky/Nginx-UI/internal/logger"
+	"github.com/0xJacky/Nginx-UI/model"
+	"strings"
+	"time"
+)
+
+type Logger struct {
+	buffer []string
+	cert   *model.Cert
+}
+
+func (t *Logger) SetCertModel(cert *model.Cert) {
+	t.cert = cert
+}
+
+func (t *Logger) Info(text string) {
+	t.buffer = append(t.buffer, strings.TrimSpace(text))
+	logger.Info("AutoCert", strings.TrimSpace(text))
+}
+
+func (t *Logger) Error(err error) {
+	t.buffer = append(t.buffer, fmt.Sprintf("%s [Error] %s",
+		time.Now().Format("2006/01/02 15:04:05"),
+		strings.TrimSpace(err.Error()),
+	))
+	logger.Error("AutoCert", err)
+}
+
+func (t *Logger) Exit() {
+	if t.cert == nil {
+		return
+	}
+
+	_ = t.cert.Updates(&model.Cert{
+		Log: t.ToString(),
+	})
+}
+
+func (t *Logger) ToString() (content string) {
+	content = strings.Join(t.buffer, "\n")
+	return
+}

+ 46 - 0
internal/cert/write_file.go

@@ -0,0 +1,46 @@
+package cert
+
+import (
+	"os"
+	"path/filepath"
+)
+
+type Content struct {
+	SSLCertificatePath    string `json:"ssl_certificate_path" binding:"required"`
+	SSLCertificateKeyPath string `json:"ssl_certificate_key_path" binding:"required"`
+	SSLCertificate        string `json:"ssl_certificate"`
+	SSLCertificateKey     string `json:"ssl_certificate_key"`
+}
+
+func (c *Content) WriteFile() (err error) {
+	// MkdirAll creates a directory named path, along with any necessary parents,
+	// and returns nil, or else returns an error.
+	// The permission bits perm (before umask) are used for all directories that MkdirAll creates.
+	// If path is already a directory, MkdirAll does nothing and returns nil.
+
+	err = os.MkdirAll(filepath.Dir(c.SSLCertificatePath), 0644)
+	if err != nil {
+		return
+	}
+
+	err = os.MkdirAll(filepath.Dir(c.SSLCertificateKeyPath), 0644)
+	if err != nil {
+		return
+	}
+
+	if c.SSLCertificate != "" {
+		err = os.WriteFile(c.SSLCertificatePath, []byte(c.SSLCertificate), 0644)
+		if err != nil {
+			return
+		}
+	}
+
+	if c.SSLCertificateKey != "" {
+		err = os.WriteFile(c.SSLCertificateKeyPath, []byte(c.SSLCertificateKey), 0644)
+		if err != nil {
+			return
+		}
+	}
+
+	return
+}

+ 0 - 18
model/cert.go

@@ -72,24 +72,6 @@ func GetAutoCertList() (c []*Cert) {
 	return
 	return
 }
 }
 
 
-func GetCertList(name, domain string) (c []Cert) {
-	tx := db
-	if name != "" {
-		tx = tx.Where("name LIKE ? or domain LIKE ?", "%"+name+"%", "%"+name+"%")
-	}
-	if domain != "" {
-		tx = tx.Where("domain LIKE ?", "%"+domain+"%")
-	}
-	tx.Find(&c)
-	return
-}
-
-func FirstCertByID(id int) (c Cert, err error) {
-	err = db.First(&c, id).Error
-
-	return
-}
-
 func (c *Cert) Updates(n *Cert) error {
 func (c *Cert) Updates(n *Cert) error {
 	return db.Model(&Cert{}).Where("id", c.ID).Updates(n).Error
 	return db.Model(&Cert{}).Where("id", c.ID).Updates(n).Error
 }
 }

+ 0 - 1
settings/settings.go

@@ -63,7 +63,6 @@ func mapTo(section string, v interface{}) {
 }
 }
 
 
 func reflectFrom(section string, v interface{}) {
 func reflectFrom(section string, v interface{}) {
-	log.Print(section, v)
 	err := Conf.Section(section).ReflectFrom(v)
 	err := Conf.Section(section).ReflectFrom(v)
 	if err != nil {
 	if err != nil {
 		log.Fatalf("Cfg.ReflectFrom %s err: %v", section, err)
 		log.Fatalf("Cfg.ReflectFrom %s err: %v", section, err)