Compare commits

...
Author SHA1 Message Date
ssongliu 582cf1f533 feat: update vm and file resources (#13210) 2026-07-07 14:33:34 +08:00
ssongliu b8a4e8e9e0 chore: update xpack menu migration (#13207) 2026-07-06 11:14:29 +08:00
ssongliu 4a462aecc7 fix: reset firewall import dialogs on open (#13198) 2026-07-03 16:51:08 +08:00
ssongliu 74f221b895 fix: use svg renderer for container monitor charts (#13197) 2026-07-03 16:50:47 +08:00
ssongliu cbcb628bff fix: normalize firewall import addresses (#13196) 2026-07-03 16:37:03 +08:00
蘭 f602645e31 feat: Implement code editor layout with splitter for improved UI (#13195) 2026-07-03 16:01:44 +08:00
CityFun ec9e609f10 feat: add some translate (#13194) 2026-07-03 15:59:35 +08:00
ssongliu 1c1f3c7761 feat: support importing all firewall rules (#13192)
* feat: support importing all firewall rules

* fix: preserve selected firewall import action
2026-07-03 15:59:22 +08:00
ssongliu fae49284b7 fix: support mariadb manual backup args (#13193) 2026-07-03 15:58:15 +08:00
蘭 072a608a63 feat: File editor supports right-click operation (#13191) 2026-07-03 15:04:04 +08:00
蘭 1e6fd9c3a0 ref: Optimize menu settings (#13190) 2026-07-03 12:10:47 +08:00
ssongliu 23200cbe85 fix: support mariadb cronjob backup args (#13188) 2026-07-03 11:41:52 +08:00
ssongliu 08604e8c02 fix: fix dashboard running time calculation (#13187) 2026-07-03 11:41:37 +08:00
蘭 62a472d2d1 ref: refactor code editor theme management (#13186) 2026-07-03 11:41:22 +08:00
ssongliu 2c84665e8b chore: organize i18n language files (#13183) 2026-07-02 21:13:22 +08:00
蘭 616bd6830c feat: add menu accordion setting and update related components (#13182) 2026-07-02 21:13:07 +08:00
ssongliu e55ea96f00 feat: support virtual machine (#13171)
* feat: support virtual machine

* feat: add vm operation logs
2026-07-02 15:07:48 +08:00
蘭 aa676e139c feat: implement code editor theme management and synchronization (#13169) 2026-07-02 14:49:52 +08:00
ssongliu 7708fea58d feat: update operation log content (#13166) 2026-07-01 18:14:33 +08:00
ssongliu 34bdff01ad fix: allow ssl push on selected node (#13165) 2026-07-01 17:04:00 +08:00
CityFun 5a49579ddf feat: Optimize error messages for HTTP certificate requests (#13164) 2026-07-01 16:19:57 +08:00
CityFun b98a2b06c9 feat: Add multiple dimensions to website search (#13163) 2026-07-01 16:19:43 +08:00
ssongliu 9073b16baa feat: support compose rebuild operation (#13162) 2026-07-01 16:19:25 +08:00
ssongliu 2ec4db8d7e feat: adjust batch application installation API (#13161) 2026-07-01 16:19:12 +08:00
CityFun fe9628f91c feat: Add TaskLog for MCP Servers (#13160) 2026-07-01 16:18:59 +08:00
蘭 18a469e4be fix: Enhance Python language support in Monaco editor (#13158) 2026-07-01 16:18:42 +08:00
蘭 8c691cc074 fix: Resolve the issue of inability to access mobile web login (#13157) 2026-07-01 16:18:26 +08:00
ssongliu 2cd31a47f8 fix: complete operation logs (#13155) 2026-06-30 22:22:20 +08:00
CityFun d97aa9c2a0 feat: Optimize SSH session performance on Ubuntu 25. (#13152)
* feat: Optimize SSH session performance on Ubuntu 25.

* feat: Optimize SSH session performance on Ubuntu 25.

* feat: Optimize SSH session performance on Ubuntu 25.

* feat: Optimize SSH session performance on Ubuntu 25.
2026-06-30 18:36:28 +08:00
ssongliu f31f0a89ff feat: support certificate synchronization (#13153) 2026-06-30 18:31:45 +08:00
CityFun 0a1621166e feat: Unify the default website and default site under the same button. (#13149) 2026-06-30 15:56:25 +08:00
蘭 8623aa5318 feat: Enhance API authentication with HMAC-SHA256 support and user role management (#13148) 2026-06-30 14:16:36 +08:00
CityFun ec50599526 feat: Node runtime environment supports configuring whether to install node_modules. (#13147) 2026-06-30 14:16:22 +08:00
CityFun 458a30c520 feat: Add a description for syncing WAF IP groups. (#13143) 2026-06-29 18:42:02 +08:00
Andrea Leone 9a660db4c3 feat: add Ionos DNS Provider (#13024)
* feat: add Ionos DNS Provider

* Fix typo string formatting for APIKey in Ionos config
2026-06-29 16:11:33 +08:00
Reza Alipour Kondori f4fc71d32b add some translate and update Persian (#13132)
* Add Persian (fa) translations

* Update index.ts

Add fa to LOCALE_LOADERS

* Update fu.ts

Add fa item

* Update index.vue

enable Persian (fa) in language selector

* Update login-form.vue

enable Persian (fa) in language selector

* Create fa.yaml

add fa backend translations

* Update i18n.go

Add fa to langFiles variable

* Add Persian (fa) Translation to agent

* Add Persian README file

Add Persian (fa) README.fa.md to project

* fix(i18n): add Persian (fa) to backend validation and login dropdown

* Update README.fa.md

* Upade link in readme
2026-06-29 15:25:56 +08:00
王贺 e45a8185e3 fix container upgrade network IP handling (#13126) 2026-06-26 18:38:11 +08:00
CityFun 7be9189b3c fix: Fixed issue with reload ssl failed (#13129) 2026-06-26 18:08:38 +08:00
蘭 bdf13c01f6 ref: Improve support for Persian (fa) language (#13128) 2026-06-26 18:08:22 +08:00
王贺 902bc90aef fix: Fix updating the application host binding IP (#13127) 2026-06-26 18:08:08 +08:00
Octopusandocto-patch 27ba50d8be feat: add MiniMax M3 model to provider catalog (#13119)
Add the latest MiniMax-M3 flagship model to the MiniMax provider model
list and set it as the default. M3 offers a 1M context window, 128K max
output, reasoning, and image input. Drop the older M2.5 entries while
keeping M2.7 as an alternative, and update the account verification probe
to use M3.

Co-authored-by: octo-patch <266937838+octo-patch@users.noreply.github.com>
2026-06-26 17:55:04 +08:00
Reza Alipour Kondori fb483ecb90 Add Persian (fa) translations (#13100)
* Add Persian (fa) translations

* Update index.ts

Add fa to LOCALE_LOADERS

* Update fu.ts

Add fa item

* Update index.vue

enable Persian (fa) in language selector

* Update login-form.vue

enable Persian (fa) in language selector

* Create fa.yaml

add fa backend translations

* Update i18n.go

Add fa to langFiles variable

* Add Persian (fa) Translation to agent
2026-06-26 17:17:32 +08:00
蘭 2de7079dd2 feat: add new localization strings for skill management features (#13124) 2026-06-26 16:17:57 +08:00
CityFun 2e4ac604a8 fix: Fix incomplete log download issue (#13123) 2026-06-26 16:17:40 +08:00
CityFun 46af80142e feat: add username/password support for hermes-agent (#13121)
* feat: add username/password support for hermes-agent

* feat: add username/password support for hermes-agent

* feat: add username/password support for hermes-agent
2026-06-26 16:17:23 +08:00
CityFun 677b47dcdb fix: Fixed issue with openclaw config telegram failed (#13114) 2026-06-25 18:40:34 +08:00
王贺 56cccdf7c0 refactor: remove skills hub server leftovers (#13115) 2026-06-25 15:09:21 +08:00
蘭 3e0d0bb809 feat: add quick toggle comment functionality in the editor (#13107) 2026-06-24 18:23:51 +08:00
ssongliu 86aa6c09c6 fix: resolve snapshot extraction directory missing issue (#13104) 2026-06-24 18:23:37 +08:00
蘭 f67e1d897c ref: add some translate (#13102) 2026-06-24 18:23:23 +08:00
蘭 9e518daa62 ref: add some translate (#13093) 2026-06-23 14:05:48 +08:00
CityFun 2e5455e655 feat: Add “Remove old images during app upgrade” configuration to the App Store. (#13092) 2026-06-23 14:05:33 +08:00
CityFun 868f1db4c5 feat: Create and delete runtime environments, and add task logs. (#13081) 2026-06-18 18:46:32 +08:00
王贺 efd84b1e1b feat: support skills hub server frontend (#13074) 2026-06-18 16:57:53 +08:00
CityFun 5591fe50f0 chore: optimize runtime environment container configuration (#13071)
* chore: optimize runtime environment container configuration

* chore: optimize runtime environment container configuration
2026-06-17 19:09:31 +08:00
王贺 5e0a598799 feat: update waf prompt translations (#13070) 2026-06-17 17:00:28 +08:00
CityFun 45d7b30abc feat: Add support for syncing self-signed certificates and manually u… (#13068)
* feat: Add support for syncing self-signed certificates and manually uploaded certificates to other nodes.

* feat: Add support for syncing self-signed certificates and manually
2026-06-17 17:00:15 +08:00
ssongliu 46af88e1d0 feat: support app and image synchronization (#13067) 2026-06-17 15:41:09 +08:00
CityFun 7f331f5503 fix: 解决证书推送到其他节点报错的问题 (#13065) 2026-06-17 15:31:51 +08:00
igophper 7b74e09d30 fix: manage expanded node states in the tree view component (#13064) 2026-06-17 12:36:23 +08:00
蘭 01e4455110 refactor: Remove error logging for missing alert config in alert handling (#13060) 2026-06-17 11:08:45 +08:00
CityFun 922a2d21c8 feat: add protocolVersion param for MCP Server (#13057)
* feat: add protocolVersion param for MCP Server

* feat: add protocolVersion param for MCP Server
2026-06-16 16:47:27 +08:00
CityFun 439c4794b7 feat: Optimize the vLLM display (#13056) 2026-06-15 16:42:00 +08:00
ssongliu 5ac7f16b67 feat: optimize image deletion logs (#13053) 2026-06-15 15:41:46 +08:00
蘭 bfb79066b4 fix: Adjust the default values of alert attributes (#13052) 2026-06-15 15:41:33 +08:00
蘭 19602b42fb feat: add QR code verification endpoint to password expiration checks (#13049) 2026-06-15 15:15:09 +08:00
ssongliu f987af264f feat: disable script library auto-sync on startup (#13047) 2026-06-15 13:46:24 +08:00
ssongliu a6c76dffc3 feat: add snapshot rollback prompt (#13045) 2026-06-15 13:46:13 +08:00
CityFun a2eed66bc4 fix: fixed issue with refresh agent page failed (#13035) 2026-06-12 18:14:35 +08:00
CityFun a49b9b132d feat: update app upgrade logic (#13032) 2026-06-12 17:44:34 +08:00
ssongliu e8505a249a fix: resolve password expiration issue in multi-user mode (#13030) 2026-06-12 14:16:16 +08:00
245 changed files with 18866 additions and 61946 deletions
+2 -1
View File
@@ -25,7 +25,7 @@
<a href="/docs/README.pt-br.md"><img alt="Português (Brasil)" src="https://img.shields.io/badge/Português (Brasil)-d9d9d9"></a> <a href="/docs/README.pt-br.md"><img alt="Português (Brasil)" src="https://img.shields.io/badge/Português (Brasil)-d9d9d9"></a>
<a href="/docs/README.ar.md"><img alt="العربية" src="https://img.shields.io/badge/العربية-d9d9d9"></a> <a href="/docs/README.ar.md"><img alt="العربية" src="https://img.shields.io/badge/العربية-d9d9d9"></a>
<a href="/docs/README.de.md"><img alt="Deutsch" src="https://img.shields.io/badge/Deutsch-d9d9d9"></a> <a href="/docs/README.de.md"><img alt="Deutsch" src="https://img.shields.io/badge/Deutsch-d9d9d9"></a>
<a href="/docs/README.es.md"><img alt="Español" src="https://img.shields.io/badge/Español-d9d9d9"></a> <a href="/docs/README.es-es.md"><img alt="Español" src="https://img.shields.io/badge/Español-d9d9d9"></a>
<a href="/docs/README.fr.md"><img alt="français" src="https://img.shields.io/badge/français-d9d9d9"></a> <a href="/docs/README.fr.md"><img alt="français" src="https://img.shields.io/badge/français-d9d9d9"></a>
<a href="/docs/README.ko.md"><img alt="한국어" src="https://img.shields.io/badge/한국어-d9d9d9"></a> <a href="/docs/README.ko.md"><img alt="한국어" src="https://img.shields.io/badge/한국어-d9d9d9"></a>
<a href="/docs/README.id.md"><img alt="Bahasa Indonesia" src="https://img.shields.io/badge/Bahasa Indonesia-d9d9d9"></a> <a href="/docs/README.id.md"><img alt="Bahasa Indonesia" src="https://img.shields.io/badge/Bahasa Indonesia-d9d9d9"></a>
@@ -33,6 +33,7 @@
<a href="/docs/README.tr.md"><img alt="Türkçe" src="https://img.shields.io/badge/Türkçe-d9d9d9"></a> <a href="/docs/README.tr.md"><img alt="Türkçe" src="https://img.shields.io/badge/Türkçe-d9d9d9"></a>
<a href="/docs/README.ru.md"><img alt="Русский" src="https://img.shields.io/badge/Русский-d9d9d9"></a> <a href="/docs/README.ru.md"><img alt="Русский" src="https://img.shields.io/badge/Русский-d9d9d9"></a>
<a href="/docs/README.ms.md"><img alt="Bahasa Melayu" src="https://img.shields.io/badge/Bahasa Melayu-d9d9d9"></a> <a href="/docs/README.ms.md"><img alt="Bahasa Melayu" src="https://img.shields.io/badge/Bahasa Melayu-d9d9d9"></a>
<a href="/docs/README.fa.md"><img alt="Persian" src="https://img.shields.io/badge/%D9%81%D8%A7%D8%B1%D8%B3%DB%8C-d9d9d9"></a>
</p> </p>
--- ---
+6 -1
View File
@@ -413,10 +413,15 @@ func (b *BaseApi) Backup(c *gin.Context) {
switch req.Type { switch req.Type {
case "app": case "app":
if _, err := backupService.AppBackup(req); err != nil { record, err := backupService.AppBackup(req)
if err != nil {
helper.InternalServer(c, err) helper.InternalServer(c, err)
return return
} }
if req.IsImmediate {
helper.SuccessWithData(c, record)
return
}
case "mysql", "mariadb", constant.AppMysqlCluster: case "mysql", "mariadb", constant.AppMysqlCluster:
if err := backupService.MysqlBackup(req); err != nil { if err := backupService.MysqlBackup(req); err != nil {
helper.InternalServer(c, err) helper.InternalServer(c, err)
+63
View File
@@ -23,6 +23,27 @@ func (b *BaseApi) PageMcpServers(c *gin.Context) {
helper.SuccessWithData(c, list) helper.SuccessWithData(c, list)
} }
// @Tags McpServer
// @Summary Load mcp server detail
// @Accept json
// @Param request body request.McpServerDetail true "request"
// @Success 200 {object} response.McpServerDTO
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/mcp/server/detail [post]
func (b *BaseApi) LoadMcpServerDetail(c *gin.Context) {
var req request.McpServerDetail
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
res, err := mcpServerService.Detail(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, res)
}
// @Tags McpServer // @Tags McpServer
// @Summary Create mcp server // @Summary Create mcp server
// @Accept json // @Accept json
@@ -107,6 +128,48 @@ func (b *BaseApi) OperateMcpServer(c *gin.Context) {
helper.Success(c) helper.Success(c)
} }
// @Tags McpServer
// @Summary Sync mcp server status
// @Accept json
// @Param request body request.McpServerStatusSync true "request"
// @Success 200 {array} response.McpServerStatusDTO
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/mcp/server/status/sync [post]
func (b *BaseApi) SyncMcpServerStatus(c *gin.Context) {
var req request.McpServerStatusSync
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
res, err := mcpServerService.SyncStatus(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, res)
}
// @Tags McpServer
// @Summary Test mcp server connection
// @Accept json
// @Param request body request.McpServerConnectionTest true "request"
// @Success 200 {object} response.McpServerConnectionTestRes
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/mcp/server/connection/test [post]
func (b *BaseApi) TestMcpServerConnection(c *gin.Context) {
var req request.McpServerConnectionTest
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
res, err := mcpServerService.TestConnection(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, res)
}
// @Tags McpServer // @Tags McpServer
// @Summary Bind Domain for mcp server // @Summary Bind Domain for mcp server
// @Accept json // @Accept json
+25
View File
@@ -210,6 +210,27 @@ func (b *BaseApi) UpdateWebsiteSSL(c *gin.Context) {
helper.Success(c) helper.Success(c)
} }
// @Tags Website SSL
// @Summary Push ssl to nodes
// @Accept json
// @Param request body request.WebsiteSSLPush true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /websites/ssl/push [post]
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"website_ssls","output_column":"primary_domain","output_value":"domain"}],"formatZH":"推送证书到节点 [domain]","formatEN":"Push ssl to nodes [domain]"}
func (b *BaseApi) PushWebsiteSSLToNode(c *gin.Context) {
var req request.WebsiteSSLPush
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := websiteSSLService.PushToNode(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags Website SSL // @Tags Website SSL
// @Summary Upload ssl // @Summary Upload ssl
// @Accept json // @Accept json
@@ -248,6 +269,8 @@ func (b *BaseApi) UploadSSLFile(c *gin.Context) {
var req request.WebsiteSSLFileUpload var req request.WebsiteSSLFileUpload
req.Description = c.PostForm("description") req.Description = c.PostForm("description")
req.Nodes = c.PostForm("nodes")
req.PushNode, _ = strconv.ParseBool(c.PostForm("pushNode"))
sslID := c.PostForm("sslID") sslID := c.PostForm("sslID")
if sslID != "" { if sslID != "" {
req.SSLID, _ = strconv.ParseUint(sslID, 10, 64) req.SSLID, _ = strconv.ParseUint(sslID, 10, 64)
@@ -283,6 +306,8 @@ func (b *BaseApi) UploadSSLFile(c *gin.Context) {
Certificate: string(certificateContent), Certificate: string(certificateContent),
Description: req.Description, Description: req.Description,
SSLID: uint(req.SSLID), SSLID: uint(req.SSLID),
PushNode: req.PushNode,
Nodes: req.Nodes,
} }
if err := websiteSSLService.Upload(uploadReq); err != nil { if err := websiteSSLService.Upload(uploadReq); err != nil {
+39 -34
View File
@@ -3,28 +3,30 @@ package dto
import "time" import "time"
type AgentCreateReq struct { type AgentCreateReq struct {
Name string `json:"name" validate:"required"` Name string `json:"name" validate:"required"`
Remark string `json:"remark"` Remark string `json:"remark"`
AppVersion string `json:"appVersion" validate:"required"` AppVersion string `json:"appVersion" validate:"required"`
WebUIPort int `json:"webUIPort" validate:"required,min=1,max=65535"` WebUIPort int `json:"webUIPort" validate:"required,min=1,max=65535"`
BridgePort int `json:"bridgePort"` BridgePort int `json:"bridgePort"`
AllowedOrigins []string `json:"allowedOrigins"` AllowedOrigins []string `json:"allowedOrigins"`
AgentType string `json:"agentType" validate:"required,oneof=openclaw copaw hermes-agent"` AgentType string `json:"agentType" validate:"required,oneof=openclaw copaw hermes-agent"`
Model string `json:"model"` Model string `json:"model"`
AccountID uint `json:"accountId"` AccountID uint `json:"accountId"`
Token string `json:"token"` Token string `json:"token"`
TaskID string `json:"taskID"` DashboardUsername string `json:"dashboardUsername"`
Advanced bool `json:"advanced"` DashboardPassword string `json:"dashboardPassword"`
ContainerName string `json:"containerName"` TaskID string `json:"taskID"`
AllowPort bool `json:"allowPort"` Advanced bool `json:"advanced"`
SpecifyIP string `json:"specifyIP"` ContainerName string `json:"containerName"`
RestartPolicy string `json:"restartPolicy"` AllowPort bool `json:"allowPort"`
CpuQuota float64 `json:"cpuQuota"` SpecifyIP string `json:"specifyIP"`
MemoryLimit float64 `json:"memoryLimit"` RestartPolicy string `json:"restartPolicy"`
MemoryUnit string `json:"memoryUnit"` CpuQuota float64 `json:"cpuQuota"`
PullImage bool `json:"pullImage"` MemoryLimit float64 `json:"memoryLimit"`
EditCompose bool `json:"editCompose"` MemoryUnit string `json:"memoryUnit"`
DockerCompose string `json:"dockerCompose"` PullImage bool `json:"pullImage"`
EditCompose bool `json:"editCompose"`
DockerCompose string `json:"dockerCompose"`
} }
type AgentBatchInstallReq struct { type AgentBatchInstallReq struct {
@@ -38,6 +40,8 @@ type AgentBatchInstallReq struct {
Model string `json:"model"` Model string `json:"model"`
AccountID uint `json:"accountId"` AccountID uint `json:"accountId"`
Token string `json:"token"` Token string `json:"token"`
DashboardUsername string `json:"dashboardUsername"`
DashboardPassword string `json:"dashboardPassword"`
TaskID string `json:"taskID"` TaskID string `json:"taskID"`
Advanced bool `json:"advanced"` Advanced bool `json:"advanced"`
ContainerName string `json:"containerName"` ContainerName string `json:"containerName"`
@@ -119,6 +123,8 @@ type AgentItem struct {
BaseURL string `json:"baseUrl"` BaseURL string `json:"baseUrl"`
APIKey string `json:"apiKey"` APIKey string `json:"apiKey"`
Token string `json:"token"` Token string `json:"token"`
DashboardUsername string `json:"dashboardUsername"`
DashboardPassword string `json:"dashboardPassword"`
Status string `json:"status"` Status string `json:"status"`
Message string `json:"message"` Message string `json:"message"`
AppInstallID uint `json:"appInstallId"` AppInstallID uint `json:"appInstallId"`
@@ -407,11 +413,6 @@ type AgentFeishuConfigUpdateReq struct {
Bots []AgentFeishuBot `json:"bots" validate:"required,min=1"` Bots []AgentFeishuBot `json:"bots" validate:"required,min=1"`
} }
type AgentFeishuPairingApproveReq struct {
AgentID uint `json:"agentId" validate:"required"`
PairingCode string `json:"pairingCode" validate:"required"`
}
type AgentFeishuConfig struct { type AgentFeishuConfig struct {
Enabled bool `json:"enabled"` Enabled bool `json:"enabled"`
ThreadSession bool `json:"threadSession"` ThreadSession bool `json:"threadSession"`
@@ -660,16 +661,20 @@ type AgentSecurityConfig struct {
} }
type AgentOtherConfigUpdateReq struct { type AgentOtherConfigUpdateReq struct {
AgentID uint `json:"agentId" validate:"required"` AgentID uint `json:"agentId" validate:"required"`
UserTimezone string `json:"userTimezone" validate:"required"` UserTimezone string `json:"userTimezone" validate:"required"`
BrowserEnabled bool `json:"browserEnabled"` BrowserEnabled bool `json:"browserEnabled"`
NPMRegistry string `json:"npmRegistry" validate:"required"` NPMRegistry string `json:"npmRegistry" validate:"required"`
DashboardUsername string `json:"dashboardUsername"`
DashboardPassword string `json:"dashboardPassword"`
} }
type AgentOtherConfig struct { type AgentOtherConfig struct {
UserTimezone string `json:"userTimezone"` UserTimezone string `json:"userTimezone"`
BrowserEnabled bool `json:"browserEnabled"` BrowserEnabled bool `json:"browserEnabled"`
NPMRegistry string `json:"npmRegistry"` NPMRegistry string `json:"npmRegistry"`
DashboardUsername string `json:"dashboardUsername"`
DashboardPassword string `json:"dashboardPassword"`
} }
type AgentConfigFileReq struct { type AgentConfigFileReq struct {
+1
View File
@@ -132,6 +132,7 @@ type Locale struct {
Ko string `json:"ko"` Ko string `json:"ko"`
Tr string `json:"tr"` Tr string `json:"tr"`
Es string `json:"es-es" yaml:"es-es"` Es string `json:"es-es" yaml:"es-es"`
Fa string `json:"fa"`
} }
type AppForm struct { type AppForm struct {
+9 -8
View File
@@ -65,14 +65,15 @@ type UploadForRecover struct {
} }
type CommonBackup struct { type CommonBackup struct {
Type string `json:"type" validate:"required,oneof=app mysql mariadb redis website postgresql mongodb mysql-cluster postgresql-cluster redis-cluster container compose"` Type string `json:"type" validate:"required,oneof=app mysql mariadb redis website postgresql mongodb mysql-cluster postgresql-cluster redis-cluster container compose"`
Name string `json:"name"` Name string `json:"name"`
DetailName string `json:"detailName"` DetailName string `json:"detailName"`
Secret string `json:"secret"` Secret string `json:"secret"`
StopBefore bool `json:"stopBefore"` IsImmediate bool `json:"isImmediate"`
TaskID string `json:"taskID"` StopBefore bool `json:"stopBefore"`
FileName string `json:"fileName"` TaskID string `json:"taskID"`
Args []string `json:"args"` FileName string `json:"fileName"`
Args []string `json:"args"`
Description string `json:"description"` Description string `json:"description"`
} }
+1 -1
View File
@@ -319,7 +319,7 @@ type ComposeCreate struct {
type ComposeOperation struct { type ComposeOperation struct {
Name string `json:"name" validate:"required"` Name string `json:"name" validate:"required"`
Path string `json:"path"` Path string `json:"path"`
Operation string `json:"operation" validate:"required,oneof=up start restart stop down delete"` Operation string `json:"operation" validate:"required,oneof=up start restart stop down delete rebuild"`
WithFile bool `json:"withFile"` WithFile bool `json:"withFile"`
Force bool `json:"force"` Force bool `json:"force"`
} }
+10 -2
View File
@@ -79,8 +79,9 @@ type NodeCurrent struct {
} }
type DashboardCurrent struct { type DashboardCurrent struct {
Uptime uint64 `json:"uptime"` Uptime uint64 `json:"uptime"`
TimeSinceUptime string `json:"timeSinceUptime"` TimeSinceUptime string `json:"timeSinceUptime"`
RunningTime RunningTime `json:"runningTime"`
Procs uint64 `json:"procs"` Procs uint64 `json:"procs"`
@@ -128,6 +129,13 @@ type DashboardCurrent struct {
ShotTime time.Time `json:"shotTime"` ShotTime time.Time `json:"shotTime"`
} }
type RunningTime struct {
Days uint64 `json:"days"`
Hours uint64 `json:"hours"`
Minutes uint64 `json:"minutes"`
Seconds uint64 `json:"seconds"`
}
type AppLauncherSync struct { type AppLauncherSync struct {
Keys []string `json:"keys"` Keys []string `json:"keys"`
} }
+1
View File
@@ -99,6 +99,7 @@ type AppInstallUpgrade struct {
DetailID uint `json:"detailId"` DetailID uint `json:"detailId"`
Backup bool `json:"backup"` Backup bool `json:"backup"`
PullImage bool `json:"pullImage"` PullImage bool `json:"pullImage"`
DeleteImage bool `json:"deleteImage"`
DockerCompose string `json:"dockerCompose"` DockerCompose string `json:"dockerCompose"`
TaskID string `json:"taskID"` TaskID string `json:"taskID"`
} }
+15
View File
@@ -21,6 +21,9 @@ type McpServerCreate struct {
StreamableHttpPath string `json:"streamableHttpPath"` StreamableHttpPath string `json:"streamableHttpPath"`
OutputTransport string `json:"outputTransport" validate:"required"` OutputTransport string `json:"outputTransport" validate:"required"`
Type string `json:"type" validate:"required"` Type string `json:"type" validate:"required"`
GatewayImage string `json:"gatewayImage"`
ProtocolVersion string `json:"protocolVersion"`
TaskID string `json:"taskID"`
} }
type McpServerUpdate struct { type McpServerUpdate struct {
@@ -32,11 +35,23 @@ type McpServerDelete struct {
ID uint `json:"id" validate:"required"` ID uint `json:"id" validate:"required"`
} }
type McpServerDetail struct {
ID uint `json:"id" validate:"required"`
}
type McpServerStatusSync struct {
IDs []uint `json:"ids"`
}
type McpServerOperate struct { type McpServerOperate struct {
ID uint `json:"id" validate:"required"` ID uint `json:"id" validate:"required"`
Operate string `json:"operate" validate:"required"` Operate string `json:"operate" validate:"required"`
} }
type McpServerConnectionTest struct {
ID uint `json:"id" validate:"required"`
}
type McpBindDomain struct { type McpBindDomain struct {
Domain string `json:"domain" validate:"required"` Domain string `json:"domain" validate:"required"`
SSLID uint `json:"sslID"` SSLID uint `json:"sslID"`
+8 -3
View File
@@ -21,13 +21,14 @@ type RuntimeCreate struct {
Source string `json:"source"` Source string `json:"source"`
CodeDir string `json:"codeDir"` CodeDir string `json:"codeDir"`
Remark string `json:"remark"` Remark string `json:"remark"`
TaskID string `json:"taskID"`
Params map[string]interface{} `json:"params"` Params map[string]interface{} `json:"params"`
NodeConfig NodeConfig
} }
type NodeConfig struct { type NodeConfig struct {
Install bool `json:"install"` Install *bool `json:"install"`
Clean bool `json:"clean"` Clean bool `json:"clean"`
ExposedPorts []ExposedPort `json:"exposedPorts"` ExposedPorts []ExposedPort `json:"exposedPorts"`
Environments []Environment `json:"environments"` Environments []Environment `json:"environments"`
@@ -42,12 +43,14 @@ type Environment struct {
type Volume struct { type Volume struct {
Source string `json:"source"` Source string `json:"source"`
Target string `json:"target"` Target string `json:"target"`
Mode string `json:"mode"`
} }
type ExposedPort struct { type ExposedPort struct {
HostPort int `json:"hostPort"` HostPort int `json:"hostPort"`
ContainerPort int `json:"containerPort"` ContainerPort int `json:"containerPort"`
HostIP string `json:"hostIP"` HostIP string `json:"hostIP"`
Protocol string `json:"protocol"`
} }
type ExtraHost struct { type ExtraHost struct {
@@ -56,8 +59,10 @@ type ExtraHost struct {
} }
type RuntimeDelete struct { type RuntimeDelete struct {
ID uint `json:"id"` ID uint `json:"id"`
ForceDelete bool `json:"forceDelete"` ForceDelete bool `json:"forceDelete"`
DeleteImage bool `json:"deleteImage"`
TaskID string `json:"taskID"`
} }
type RuntimeUpdate struct { type RuntimeUpdate struct {
+14
View File
@@ -126,6 +126,16 @@ type WebsiteSSLUpload struct {
Type string `json:"type" validate:"required,oneof=paste local"` Type string `json:"type" validate:"required,oneof=paste local"`
SSLID uint `json:"sslID"` SSLID uint `json:"sslID"`
Description string `json:"description"` Description string `json:"description"`
PushNode bool `json:"pushNode"`
Nodes string `json:"nodes"`
}
type WebsiteSSLPush struct {
ID uint `json:"id" validate:"required"`
PushNode bool `json:"pushNode"`
Nodes string `json:"nodes"`
TaskID string `json:"taskID" validate:"required"`
Sync bool `json:"sync"`
} }
type WebsiteCASearch struct { type WebsiteCASearch struct {
@@ -157,6 +167,8 @@ type WebsiteCAObtain struct {
Description string `json:"description"` Description string `json:"description"`
ExecShell bool `json:"execShell"` ExecShell bool `json:"execShell"`
Shell string `json:"shell"` Shell string `json:"shell"`
PushNode bool `json:"pushNode"`
Nodes string `json:"nodes"`
} }
type WebsiteCARenew struct { type WebsiteCARenew struct {
@@ -167,4 +179,6 @@ type WebsiteSSLFileUpload struct {
Type string `json:"type"` Type string `json:"type"`
Description string `json:"description"` Description string `json:"description"`
SSLID uint64 `json:"sslID"` SSLID uint64 `json:"sslID"`
PushNode bool `json:"pushNode"`
Nodes string `json:"nodes"`
} }
+30 -28
View File
@@ -104,34 +104,36 @@ type AppDetail struct {
} }
type AppInstallDTO struct { type AppInstallDTO struct {
ID uint `json:"id"` ID uint `json:"id"`
Name string `json:"name"` Name string `json:"name"`
AppID uint `json:"appID"` AppID uint `json:"appID"`
AppDetailID uint `json:"appDetailID"` AppDetailID uint `json:"appDetailID"`
Version string `json:"version"` Version string `json:"version"`
Status string `json:"status"` Status string `json:"status"`
Message string `json:"message"` Message string `json:"message"`
HttpPort int `json:"httpPort"` HttpPort int `json:"httpPort"`
HttpsPort int `json:"httpsPort"` HttpsPort int `json:"httpsPort"`
Path string `json:"path"` Path string `json:"path"`
CanUpdate bool `json:"canUpdate"` CanUpdate bool `json:"canUpdate"`
Icon string `json:"icon"` Icon string `json:"icon"`
AppName string `json:"appName"` AppName string `json:"appName"`
Ready int `json:"ready"` Ready int `json:"ready"`
Total int `json:"total"` Total int `json:"total"`
AppKey string `json:"appKey"` AppKey string `json:"appKey"`
AppType string `json:"appType"` AppType string `json:"appType"`
AppStatus string `json:"appStatus"` AppStatus string `json:"appStatus"`
DockerCompose string `json:"dockerCompose"` DockerCompose string `json:"dockerCompose"`
WebUI string `json:"webUI"` WebUI string `json:"webUI"`
CreatedAt time.Time `json:"createdAt"` CreatedAt time.Time `json:"createdAt"`
Favorite bool `json:"favorite"` Favorite bool `json:"favorite"`
SortOrder int `json:"sortOrder"` SortOrder int `json:"sortOrder"`
App AppDetail `json:"app"` App AppDetail `json:"app"`
Container string `json:"container"` Container string `json:"container"`
IsEdit bool `json:"isEdit"` IsEdit bool `json:"isEdit"`
LinkDB bool `json:"linkDB"` LinkDB bool `json:"linkDB"`
ServiceName string `json:"serviceName"` ResourceKeys []string `json:"resourceKeys"`
ServiceName string `json:"serviceName"`
Env map[string]interface{} `json:"env"`
} }
type AppInstallInfo struct { type AppInstallInfo struct {
+14
View File
@@ -16,6 +16,12 @@ type McpServerDTO struct {
Volumes []request.Volume `json:"volumes"` Volumes []request.Volume `json:"volumes"`
} }
type McpServerStatusDTO struct {
ID uint `json:"id"`
Status string `json:"status"`
Message string `json:"message"`
}
type McpBindDomainRes struct { type McpBindDomainRes struct {
Domain string `json:"domain"` Domain string `json:"domain"`
SSLID uint `json:"sslID"` SSLID uint `json:"sslID"`
@@ -24,3 +30,11 @@ type McpBindDomainRes struct {
WebsiteID uint `json:"websiteID"` WebsiteID uint `json:"websiteID"`
ConnUrl string `json:"connUrl"` ConnUrl string `json:"connUrl"`
} }
type McpServerConnectionTestRes struct {
Success bool `json:"success"`
Endpoint string `json:"endpoint"`
OutputTransport string `json:"outputTransport"`
ProtocolVersion string `json:"protocolVersion,omitempty"`
Message string `json:"message"`
}
+2
View File
@@ -18,4 +18,6 @@ type McpServer struct {
StreamableHttpPath string `json:"streamableHttpPath"` StreamableHttpPath string `json:"streamableHttpPath"`
OutputTransport string `json:"outputTransport"` OutputTransport string `json:"outputTransport"`
Type string `json:"type"` Type string `json:"type"`
GatewayImage string `json:"gatewayImage"`
ProtocolVersion string `json:"protocolVersion"`
} }
+1 -2
View File
@@ -163,10 +163,9 @@ var catalog = map[string]Meta{
Input: []string{"text"}, Input: []string{"text"},
}, },
Models: []Model{ Models: []Model{
{ID: "minimax/MiniMax-M3", Name: "MiniMax M3", ContextWindow: 1000000, MaxTokens: 128000, Reasoning: true, Input: []string{"text", "image"}},
{ID: "minimax/MiniMax-M2.7", Name: "MiniMax M2.7"}, {ID: "minimax/MiniMax-M2.7", Name: "MiniMax M2.7"},
{ID: "minimax/MiniMax-M2.7-highspeed", Name: "MiniMax M2.7 highspeed"}, {ID: "minimax/MiniMax-M2.7-highspeed", Name: "MiniMax M2.7 highspeed"},
{ID: "minimax/MiniMax-M2.5", Name: "MiniMax M2.5", Reasoning: true},
{ID: "minimax/MiniMax-M2.5-highspeed", Name: "MiniMax M2.5 highspeed"},
}, },
}, },
"xiaomi": { "xiaomi": {
+1 -1
View File
@@ -131,7 +131,7 @@ func BuildVerifyRequest(provider, baseURL, apiKey string) VerifyRequest {
request.URL = base + "/v1/messages" request.URL = base + "/v1/messages"
} }
request.Body = mustJSON(map[string]interface{}{ request.Body = mustJSON(map[string]interface{}{
"model": "MiniMax-M2.5", "model": "MiniMax-M3",
"max_tokens": 1, "max_tokens": 1,
"messages": []map[string]interface{}{{ "messages": []map[string]interface{}{{
"role": "user", "role": "user",
+14
View File
@@ -17,6 +17,7 @@ type IWebsiteRepo interface {
WithGroupID(groupId uint) DBOption WithGroupID(groupId uint) DBOption
WithDefaultServer() DBOption WithDefaultServer() DBOption
WithDomainLike(domain string) DBOption WithDomainLike(domain string) DBOption
WithSearchKeyword(keyword string, ids []uint) DBOption
WithRuntimeID(runtimeID uint) DBOption WithRuntimeID(runtimeID uint) DBOption
WithParentID(websiteID uint) DBOption WithParentID(websiteID uint) DBOption
WithType(websiteType string) DBOption WithType(websiteType string) DBOption
@@ -76,6 +77,19 @@ func (w *WebsiteRepo) WithDomainLike(domain string) DBOption {
} }
} }
func (w *WebsiteRepo) WithSearchKeyword(keyword string, ids []uint) DBOption {
return func(db *gorm.DB) *gorm.DB {
if keyword == "" {
return db
}
keyword = "%" + keyword + "%"
if len(ids) == 0 {
return db.Where("(primary_domain like ? OR alias like ?)", keyword, keyword)
}
return db.Where("(primary_domain like ? OR alias like ? OR id in (?))", keyword, keyword, ids)
}
}
func (w *WebsiteRepo) WithAlias(alias string) DBOption { func (w *WebsiteRepo) WithAlias(alias string) DBOption {
return func(db *gorm.DB) *gorm.DB { return func(db *gorm.DB) *gorm.DB {
return db.Where("alias = ?", alias) return db.Where("alias = ?", alias)
+50 -27
View File
@@ -176,6 +176,7 @@ func (a AgentService) Create(req dto.AgentCreateReq) (*dto.AgentItem, error) {
var allowedOrigins []string var allowedOrigins []string
var account *model.AgentAccount var account *model.AgentAccount
var installHooks *appInstallHooks var installHooks *appInstallHooks
var hermesAuth hermesDashboardAuth
if agentType == constant.AppOpenclaw || agentType == constant.AppHermesAgent { if agentType == constant.AppOpenclaw || agentType == constant.AppHermesAgent {
if req.AccountID == 0 { if req.AccountID == 0 {
@@ -222,9 +223,13 @@ func (a AgentService) Create(req dto.AgentCreateReq) (*dto.AgentItem, error) {
}, },
} }
} else if agentType == constant.AppHermesAgent { } else if agentType == constant.AppHermesAgent {
hermesAuth = normalizeHermesDashboardAuth(req.DashboardUsername, req.DashboardPassword)
installHooks = &appInstallHooks{ installHooks = &appInstallHooks{
AfterCopyData: func(appInstall *model.AppInstall) error { AfterCopyData: func(appInstall *model.AppInstall) error {
return prepareHermesInstallFiles(appInstall, account, storedModel) if err := prepareHermesInstallFiles(appInstall, account, storedModel); err != nil {
return err
}
return writeHermesDashboardAuthEnv(path.Join(appInstall.GetPath(), ".env"), hermesAuth, false)
}, },
} }
} }
@@ -248,6 +253,10 @@ func (a AgentService) Create(req dto.AgentCreateReq) (*dto.AgentItem, error) {
params["API_KEY"] = apiKey params["API_KEY"] = apiKey
params["OPENCLAW_GATEWAY_TOKEN"] = token params["OPENCLAW_GATEWAY_TOKEN"] = token
} }
if agentType == constant.AppHermesAgent {
params[hermesDashboardUsernameEnvKey] = hermesAuth.Username
params[hermesDashboardPasswordEnvKey] = hermesAuth.Password
}
if req.EditCompose && strings.TrimSpace(req.DockerCompose) == "" { if req.EditCompose && strings.TrimSpace(req.DockerCompose) == "" {
return nil, buserr.New("ErrAgentComposeRequired") return nil, buserr.New("ErrAgentComposeRequired")
@@ -604,28 +613,30 @@ func batchOperateSkipMessage(operate constant.AppOperate, status string) string
func buildCreateReqFromBatchInstallReq(req dto.AgentBatchInstallReq) dto.AgentCreateReq { func buildCreateReqFromBatchInstallReq(req dto.AgentBatchInstallReq) dto.AgentCreateReq {
return dto.AgentCreateReq{ return dto.AgentCreateReq{
Name: req.Name, Name: req.Name,
Remark: req.Remark, Remark: req.Remark,
AppVersion: req.AppVersion, AppVersion: req.AppVersion,
WebUIPort: req.WebUIPort, WebUIPort: req.WebUIPort,
BridgePort: req.BridgePort, BridgePort: req.BridgePort,
AllowedOrigins: req.AllowedOrigins, AllowedOrigins: req.AllowedOrigins,
AgentType: req.AgentType, AgentType: req.AgentType,
Model: req.Model, Model: req.Model,
AccountID: req.AccountID, AccountID: req.AccountID,
Token: req.Token, Token: req.Token,
TaskID: req.TaskID, DashboardUsername: req.DashboardUsername,
Advanced: req.Advanced, DashboardPassword: req.DashboardPassword,
ContainerName: req.ContainerName, TaskID: req.TaskID,
AllowPort: req.AllowPort, Advanced: req.Advanced,
SpecifyIP: req.SpecifyIP, ContainerName: req.ContainerName,
RestartPolicy: req.RestartPolicy, AllowPort: req.AllowPort,
CpuQuota: req.CpuQuota, SpecifyIP: req.SpecifyIP,
MemoryLimit: req.MemoryLimit, RestartPolicy: req.RestartPolicy,
MemoryUnit: req.MemoryUnit, CpuQuota: req.CpuQuota,
PullImage: req.PullImage, MemoryLimit: req.MemoryLimit,
EditCompose: req.EditCompose, MemoryUnit: req.MemoryUnit,
DockerCompose: req.DockerCompose, PullImage: req.PullImage,
EditCompose: req.EditCompose,
DockerCompose: req.DockerCompose,
} }
} }
@@ -1327,10 +1338,13 @@ func (a AgentService) GetOtherConfig(req dto.AgentIDReq) (*dto.AgentOtherConfig,
if err != nil { if err != nil {
return nil, err return nil, err
} }
auth := readHermesDashboardAuthFromInstall(install)
return &dto.AgentOtherConfig{ return &dto.AgentOtherConfig{
UserTimezone: cfg.Timezone, UserTimezone: cfg.Timezone,
BrowserEnabled: true, BrowserEnabled: true,
NPMRegistry: "https://registry.npmjs.org/", NPMRegistry: "https://registry.npmjs.org/",
DashboardUsername: auth.Username,
DashboardPassword: auth.Password,
}, nil }, nil
} }
conf, err := readOpenclawConfig(agent.ConfigPath) conf, err := readOpenclawConfig(agent.ConfigPath)
@@ -1355,12 +1369,21 @@ func (a AgentService) UpdateOtherConfig(req dto.AgentOtherConfigUpdateReq) error
if err != nil { if err != nil {
return err return err
} }
previousAuth := readHermesDashboardAuthFromInstall(install)
nextAuth := normalizeHermesDashboardAuth(req.DashboardUsername, req.DashboardPassword)
if err := writeHermesConfig(path.Dir(agent.ConfigPath), account, agent.Model, strings.TrimSpace(req.UserTimezone)); err != nil { if err := writeHermesConfig(path.Dir(agent.ConfigPath), account, agent.Model, strings.TrimSpace(req.UserTimezone)); err != nil {
return err return err
} }
if err := writeHermesDashboardAuthEnv(path.Join(install.GetPath(), ".env"), nextAuth, true); err != nil {
return err
}
operate := constant.Restart
if previousAuth.Username != nextAuth.Username || previousAuth.Password != nextAuth.Password {
operate = constant.Rebuild
}
return NewIAppInstalledService().Operate(request.AppInstalledOperate{ return NewIAppInstalledService().Operate(request.AppInstalledOperate{
InstallId: install.ID, InstallId: install.ID,
Operate: constant.Restart, Operate: operate,
}) })
} }
if err := ensureContainerRunning(install.ContainerName); err != nil { if err := ensureContainerRunning(install.ContainerName); err != nil {
+27 -6
View File
@@ -811,9 +811,7 @@ func extractTelegramConfig(conf map[string]interface{}) dto.AgentTelegramConfig
result.RequireMention = result.GroupPolicy == "allowlist" result.RequireMention = result.GroupPolicy == "allowlist"
result.GroupAllowFrom = extractStringList(telegram["groupAllowFrom"]) result.GroupAllowFrom = extractStringList(telegram["groupAllowFrom"])
result.Proxy = extractStringValue(telegram["proxy"]) result.Proxy = extractStringValue(telegram["proxy"])
if streaming := extractStringValue(telegram["streaming"]); streaming != "" { result.Streaming = normalizeTelegramStreamingMode(telegram["streaming"], result.Streaming)
result.Streaming = streaming
}
accounts := childMap(telegram, "accounts") accounts := childMap(telegram, "accounts")
if len(accounts) == 0 { if len(accounts) == 0 {
botToken := extractStringValue(telegram["botToken"]) botToken := extractStringValue(telegram["botToken"])
@@ -839,7 +837,7 @@ func extractTelegramConfig(conf map[string]interface{}) dto.AgentTelegramConfig
BotToken: extractStringValue(account["botToken"]), BotToken: extractStringValue(account["botToken"]),
DmPolicy: extractStringValue(account["dmPolicy"]), DmPolicy: extractStringValue(account["dmPolicy"]),
GroupPolicy: extractStringValue(account["groupPolicy"]), GroupPolicy: extractStringValue(account["groupPolicy"]),
Streaming: extractStringValue(account["streaming"]), Streaming: normalizeTelegramStreamingMode(account["streaming"], result.Streaming),
}) })
} }
result.DefaultAccount = normalizeDefaultAccount(extractStringValue(telegram["defaultAccount"]), getTelegramBotAccountIDs(bots)) result.DefaultAccount = normalizeDefaultAccount(extractStringValue(telegram["defaultAccount"]), getTelegramBotAccountIDs(bots))
@@ -879,7 +877,7 @@ func setTelegramConfig(conf map[string]interface{}, config dto.AgentTelegramConf
} else { } else {
delete(telegram, "proxy") delete(telegram, "proxy")
} }
telegram["streaming"] = config.Streaming telegram["streaming"] = buildTelegramStreamingConfig(config.Streaming)
accounts := make(map[string]interface{}, len(config.Bots)) accounts := make(map[string]interface{}, len(config.Bots))
for _, bot := range config.Bots { for _, bot := range config.Bots {
account := map[string]interface{}{ account := map[string]interface{}{
@@ -888,7 +886,7 @@ func setTelegramConfig(conf map[string]interface{}, config dto.AgentTelegramConf
"botToken": bot.BotToken, "botToken": bot.BotToken,
"dmPolicy": bot.DmPolicy, "dmPolicy": bot.DmPolicy,
"groupPolicy": bot.GroupPolicy, "groupPolicy": bot.GroupPolicy,
"streaming": bot.Streaming, "streaming": buildTelegramStreamingConfig(bot.Streaming),
} }
if bot.DmPolicy == "open" { if bot.DmPolicy == "open" {
account["allowFrom"] = []string{"*"} account["allowFrom"] = []string{"*"}
@@ -899,6 +897,29 @@ func setTelegramConfig(conf map[string]interface{}, config dto.AgentTelegramConf
delete(telegram, "botToken") delete(telegram, "botToken")
} }
func normalizeTelegramStreamingMode(value interface{}, defaultMode string) string {
mode := defaultMode
switch typed := value.(type) {
case string:
mode = typed
case map[string]interface{}:
mode = extractStringValue(typed["mode"])
}
mode = strings.ToLower(strings.TrimSpace(mode))
switch mode {
case "off", "partial", "block", "progress":
return mode
default:
return "partial"
}
}
func buildTelegramStreamingConfig(mode string) map[string]interface{} {
return map[string]interface{}{
"mode": normalizeTelegramStreamingMode(mode, "partial"),
}
}
func extractDiscordConfig(conf map[string]interface{}) dto.AgentDiscordConfig { func extractDiscordConfig(conf map[string]interface{}) dto.AgentDiscordConfig {
result := dto.AgentDiscordConfig{Enabled: true, DmPolicy: "pairing", AllowFrom: []string{}, RequireMention: false, GroupPolicy: "open"} result := dto.AgentDiscordConfig{Enabled: true, DmPolicy: "pairing", AllowFrom: []string{}, RequireMention: false, GroupPolicy: "open"}
discord := getChannelConfig(conf, "discord") discord := getChannelConfig(conf, "discord")
+63 -52
View File
@@ -13,14 +13,19 @@ import (
"github.com/1Panel-dev/1Panel/agent/buserr" "github.com/1Panel-dev/1Panel/agent/buserr"
"github.com/1Panel-dev/1Panel/agent/constant" "github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/utils/common" "github.com/1Panel-dev/1Panel/agent/utils/common"
agentenv "github.com/1Panel-dev/1Panel/agent/utils/env"
"github.com/1Panel-dev/1Panel/agent/utils/files" "github.com/1Panel-dev/1Panel/agent/utils/files"
"github.com/joho/godotenv"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
) )
const hermesWorkspaceDir = "/opt/data/workspace" const hermesWorkspaceDir = "/opt/data/workspace"
const hermesExecutablePath = "/opt/hermes/.venv/bin/hermes" const hermesExecutablePath = "/opt/hermes/.venv/bin/hermes"
const hermesDashboardUsernameEnvKey = "HERMES_DASHBOARD_USERNAME"
const hermesDashboardPasswordEnvKey = "HERMES_DASHBOARD_PASSWORD"
type hermesDashboardAuth struct {
Username string
Password string
}
type hermesConfig struct { type hermesConfig struct {
Model hermesModelConfig `yaml:"model"` Model hermesModelConfig `yaml:"model"`
@@ -112,6 +117,52 @@ func prepareHermesInstallFiles(appInstall *model.AppInstall, account *model.Agen
return files.NewFileOp().ChownR(dataDir, "1000", "1000", true) return files.NewFileOp().ChownR(dataDir, "1000", "1000", true)
} }
func normalizeHermesDashboardAuth(username, password string) hermesDashboardAuth {
auth := hermesDashboardAuth{
Username: strings.TrimSpace(username),
Password: strings.TrimSpace(password),
}
if auth.Username == "" {
auth.Username = "admin"
}
if auth.Password == "" {
auth.Password = common.RandStr(8)
}
return auth
}
func writeHermesDashboardAuthEnv(envPath string, auth hermesDashboardAuth, overwrite bool) error {
return upsertAgentEnv(envPath, map[string]string{
hermesDashboardUsernameEnvKey: auth.Username,
hermesDashboardPasswordEnvKey: auth.Password,
}, []string{
hermesDashboardUsernameEnvKey,
hermesDashboardPasswordEnvKey,
}, overwrite)
}
func readHermesDashboardAuthEnv(envPath string) (hermesDashboardAuth, error) {
envMap, err := readAgentEnvMap(envPath)
if err != nil {
return hermesDashboardAuth{}, err
}
return hermesDashboardAuth{
Username: strings.TrimSpace(envMap[hermesDashboardUsernameEnvKey]),
Password: strings.TrimSpace(envMap[hermesDashboardPasswordEnvKey]),
}, nil
}
func readHermesDashboardAuthFromInstall(appInstall *model.AppInstall) hermesDashboardAuth {
if appInstall == nil || appInstall.ID == 0 {
return hermesDashboardAuth{}
}
auth, err := readHermesDashboardAuthEnv(path.Join(appInstall.GetPath(), ".env"))
if err != nil {
return hermesDashboardAuth{}
}
return auth
}
func readHermesConfig(configPath string) (*hermesConfig, error) { func readHermesConfig(configPath string) (*hermesConfig, error) {
content, err := files.NewFileOp().GetContent(configPath) content, err := files.NewFileOp().GetContent(configPath)
if err != nil { if err != nil {
@@ -152,7 +203,7 @@ func writeHermesConfigMap(configPath string, cfg map[string]interface{}) error {
} }
func readHermesTelegramChannelConfig(confDir string) (*dto.AgentTelegramConfig, error) { func readHermesTelegramChannelConfig(confDir string) (*dto.AgentTelegramConfig, error) {
envMap, err := readHermesEnvMap(path.Join(confDir, ".env")) envMap, err := readAgentEnvMap(path.Join(confDir, ".env"))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -209,7 +260,7 @@ func readHermesTelegramChannelConfig(confDir string) (*dto.AgentTelegramConfig,
func writeHermesTelegramChannelConfig(confDir string, config dto.AgentTelegramConfig) error { func writeHermesTelegramChannelConfig(confDir string, config dto.AgentTelegramConfig) error {
envPath := path.Join(confDir, ".env") envPath := path.Join(confDir, ".env")
envMap, err := readHermesEnvMap(envPath) envMap, err := readAgentEnvMap(envPath)
if err != nil { if err != nil {
return err return err
} }
@@ -229,7 +280,7 @@ func writeHermesTelegramChannelConfig(confDir string, config dto.AgentTelegramCo
envMap["TELEGRAM_ALLOWED_USERS"] = allow envMap["TELEGRAM_ALLOWED_USERS"] = allow
} }
} }
if err := writeHermesEnvMap(envPath, envMap, []string{ if err := writeAgentEnvMap(envPath, envMap, []string{
"TELEGRAM_BOT_TOKEN", "TELEGRAM_BOT_TOKEN",
"TELEGRAM_ALLOWED_USERS", "TELEGRAM_ALLOWED_USERS",
"TELEGRAM_ALLOW_ALL_USERS", "TELEGRAM_ALLOW_ALL_USERS",
@@ -248,7 +299,7 @@ func writeHermesTelegramChannelConfig(confDir string, config dto.AgentTelegramCo
} }
func readHermesDiscordChannelConfig(confDir string) (*dto.AgentDiscordConfig, error) { func readHermesDiscordChannelConfig(confDir string) (*dto.AgentDiscordConfig, error) {
envMap, err := readHermesEnvMap(path.Join(confDir, ".env")) envMap, err := readAgentEnvMap(path.Join(confDir, ".env"))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -300,7 +351,7 @@ func readHermesDiscordChannelConfig(confDir string) (*dto.AgentDiscordConfig, er
func writeHermesDiscordChannelConfig(confDir string, config dto.AgentDiscordConfig) error { func writeHermesDiscordChannelConfig(confDir string, config dto.AgentDiscordConfig) error {
envPath := path.Join(confDir, ".env") envPath := path.Join(confDir, ".env")
envMap, err := readHermesEnvMap(envPath) envMap, err := readAgentEnvMap(envPath)
if err != nil { if err != nil {
return err return err
} }
@@ -320,7 +371,7 @@ func writeHermesDiscordChannelConfig(confDir string, config dto.AgentDiscordConf
envMap["DISCORD_ALLOWED_USERS"] = allow envMap["DISCORD_ALLOWED_USERS"] = allow
} }
} }
if err := writeHermesEnvMap(envPath, envMap, []string{ if err := writeAgentEnvMap(envPath, envMap, []string{
"DISCORD_BOT_TOKEN", "DISCORD_BOT_TOKEN",
"DISCORD_ALLOWED_USERS", "DISCORD_ALLOWED_USERS",
"DISCORD_ALLOW_ALL_USERS", "DISCORD_ALLOW_ALL_USERS",
@@ -340,14 +391,14 @@ func writeHermesDiscordChannelConfig(confDir string, config dto.AgentDiscordConf
func deleteHermesEnvKeys(confDir string, keys ...string) error { func deleteHermesEnvKeys(confDir string, keys ...string) error {
envPath := path.Join(confDir, ".env") envPath := path.Join(confDir, ".env")
envMap, err := readHermesEnvMap(envPath) envMap, err := readAgentEnvMap(envPath)
if err != nil { if err != nil {
return err return err
} }
for _, key := range keys { for _, key := range keys {
delete(envMap, key) delete(envMap, key)
} }
return writeHermesEnvMap(envPath, envMap, keys) return writeAgentEnvMap(envPath, envMap, keys)
} }
func deleteHermesConfigSections(confDir string, topLevelKeys []string, platformKeys []string) error { func deleteHermesConfigSections(confDir string, topLevelKeys []string, platformKeys []string) error {
@@ -532,7 +583,7 @@ func resolveHermesEnvEntries(account *model.AgentAccount) []hermesEnvEntry {
} }
func writeHermesModelEnv(envPath string, account *model.AgentAccount) error { func writeHermesModelEnv(envPath string, account *model.AgentAccount) error {
envMap, err := readHermesEnvMap(envPath) envMap, err := readAgentEnvMap(envPath)
if err != nil { if err != nil {
return err return err
} }
@@ -548,7 +599,7 @@ func writeHermesModelEnv(envPath string, account *model.AgentAccount) error {
envMap[entry.Key] = entry.Value envMap[entry.Key] = entry.Value
order = append(order, entry.Key) order = append(order, entry.Key)
} }
return writeHermesEnvMap(envPath, envMap, order) return writeAgentEnvMap(envPath, envMap, order)
} }
func hermesManagedModelEnvKeys() []string { func hermesManagedModelEnvKeys() []string {
@@ -598,46 +649,6 @@ func hermesManagedModelEnvKeys() []string {
return result return result
} }
func writeHermesEnv(envPath string, entries []hermesEnvEntry) error {
envMap, err := readHermesEnvMap(envPath)
if err != nil {
return err
}
for _, entry := range entries {
if entry.Key == "" || entry.Value == "" {
continue
}
envMap[entry.Key] = entry.Value
}
order := make([]string, 0, len(entries))
for _, entry := range entries {
if entry.Key == "" {
continue
}
order = append(order, entry.Key)
}
return writeHermesEnvMap(envPath, envMap, order)
}
func readHermesEnvMap(envPath string) (map[string]string, error) {
fileOp := files.NewFileOp()
if !fileOp.Stat(envPath) {
return map[string]string{}, nil
}
envMap, err := godotenv.Read(envPath)
if err != nil {
return nil, err
}
return envMap, nil
}
func writeHermesEnvMap(envPath string, envMap map[string]string, order []string) error {
if len(envMap) == 0 {
return files.NewFileOp().SaveFile(envPath, "", 0600)
}
return agentenv.WriteWithOrder(envMap, envPath, order)
}
func splitHermesEnvList(value string) []string { func splitHermesEnvList(value string) []string {
if value == "" { if value == "" {
return []string{} return []string{}
+13 -13
View File
@@ -34,7 +34,7 @@ print('Restart the Hermes-Agent container to apply the new Weixin settings.')
` `
func readHermesQQBotChannelConfig(confDir string) (*dto.AgentQQBotConfig, error) { func readHermesQQBotChannelConfig(confDir string) (*dto.AgentQQBotConfig, error) {
envMap, err := readHermesEnvMap(path.Join(confDir, ".env")) envMap, err := readAgentEnvMap(path.Join(confDir, ".env"))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -78,7 +78,7 @@ func readHermesQQBotChannelConfig(confDir string) (*dto.AgentQQBotConfig, error)
func writeHermesQQBotChannelConfig(confDir string, config dto.AgentQQBotConfig) error { func writeHermesQQBotChannelConfig(confDir string, config dto.AgentQQBotConfig) error {
envPath := path.Join(confDir, ".env") envPath := path.Join(confDir, ".env")
envMap, err := readHermesEnvMap(envPath) envMap, err := readAgentEnvMap(envPath)
if err != nil { if err != nil {
return err return err
} }
@@ -102,7 +102,7 @@ func writeHermesQQBotChannelConfig(confDir string, config dto.AgentQQBotConfig)
envMap["QQ_GROUP_ALLOWED_USERS"] = allow envMap["QQ_GROUP_ALLOWED_USERS"] = allow
} }
} }
if err := writeHermesEnvMap(envPath, envMap, []string{ if err := writeAgentEnvMap(envPath, envMap, []string{
"QQ_APP_ID", "QQ_APP_ID",
"QQ_CLIENT_SECRET", "QQ_CLIENT_SECRET",
"QQ_ALLOW_ALL_USERS", "QQ_ALLOW_ALL_USERS",
@@ -163,7 +163,7 @@ func deleteHermesQQBotChannelConfig(confDir string) error {
} }
func readHermesWecomChannelConfig(confDir string) (*dto.AgentWecomConfig, error) { func readHermesWecomChannelConfig(confDir string) (*dto.AgentWecomConfig, error) {
envMap, err := readHermesEnvMap(path.Join(confDir, ".env")) envMap, err := readAgentEnvMap(path.Join(confDir, ".env"))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -194,7 +194,7 @@ func readHermesWecomChannelConfig(confDir string) (*dto.AgentWecomConfig, error)
func writeHermesWecomChannelConfig(confDir string, config dto.AgentWecomConfig) error { func writeHermesWecomChannelConfig(confDir string, config dto.AgentWecomConfig) error {
envPath := path.Join(confDir, ".env") envPath := path.Join(confDir, ".env")
envMap, err := readHermesEnvMap(envPath) envMap, err := readAgentEnvMap(envPath)
if err != nil { if err != nil {
return err return err
} }
@@ -229,7 +229,7 @@ func writeHermesWecomChannelConfig(confDir string, config dto.AgentWecomConfig)
envMap["WECOM_GROUP_ALLOWED_USERS"] = allow envMap["WECOM_GROUP_ALLOWED_USERS"] = allow
} }
} }
if err := writeHermesEnvMap(envPath, envMap, []string{ if err := writeAgentEnvMap(envPath, envMap, []string{
"WECOM_BOT_ID", "WECOM_BOT_ID",
"WECOM_SECRET", "WECOM_SECRET",
"WECOM_DM_POLICY", "WECOM_DM_POLICY",
@@ -282,7 +282,7 @@ func deleteHermesWecomChannelConfig(confDir string) error {
} }
func readHermesDingTalkChannelConfig(confDir string) (*dto.AgentDingTalkConfig, error) { func readHermesDingTalkChannelConfig(confDir string) (*dto.AgentDingTalkConfig, error) {
envMap, err := readHermesEnvMap(path.Join(confDir, ".env")) envMap, err := readAgentEnvMap(path.Join(confDir, ".env"))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -332,7 +332,7 @@ func readHermesDingTalkChannelConfig(confDir string) (*dto.AgentDingTalkConfig,
func writeHermesDingTalkChannelConfig(confDir string, config dto.AgentDingTalkConfig) error { func writeHermesDingTalkChannelConfig(confDir string, config dto.AgentDingTalkConfig) error {
envPath := path.Join(confDir, ".env") envPath := path.Join(confDir, ".env")
envMap, err := readHermesEnvMap(envPath) envMap, err := readAgentEnvMap(envPath)
if err != nil { if err != nil {
return err return err
} }
@@ -356,7 +356,7 @@ func writeHermesDingTalkChannelConfig(confDir string, config dto.AgentDingTalkCo
} else if config.DmPolicy == "open" { } else if config.DmPolicy == "open" {
envMap["DINGTALK_ALLOW_ALL_USERS"] = "true" envMap["DINGTALK_ALLOW_ALL_USERS"] = "true"
} }
if err := writeHermesEnvMap(envPath, envMap, []string{ if err := writeAgentEnvMap(envPath, envMap, []string{
"DINGTALK_CLIENT_ID", "DINGTALK_CLIENT_ID",
"DINGTALK_CLIENT_SECRET", "DINGTALK_CLIENT_SECRET",
"DINGTALK_ALLOW_ALL_USERS", "DINGTALK_ALLOW_ALL_USERS",
@@ -398,7 +398,7 @@ func deleteHermesDingTalkChannelConfig(confDir string) error {
} }
func readHermesFeishuChannelConfig(confDir string) (*dto.AgentFeishuConfig, error) { func readHermesFeishuChannelConfig(confDir string) (*dto.AgentFeishuConfig, error) {
envMap, err := readHermesEnvMap(path.Join(confDir, ".env")) envMap, err := readAgentEnvMap(path.Join(confDir, ".env"))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -452,7 +452,7 @@ func readHermesFeishuChannelConfig(confDir string) (*dto.AgentFeishuConfig, erro
func writeHermesFeishuChannelConfig(confDir string, config dto.AgentFeishuConfig) error { func writeHermesFeishuChannelConfig(confDir string, config dto.AgentFeishuConfig) error {
envPath := path.Join(confDir, ".env") envPath := path.Join(confDir, ".env")
envMap, err := readHermesEnvMap(envPath) envMap, err := readAgentEnvMap(envPath)
if err != nil { if err != nil {
return err return err
} }
@@ -488,7 +488,7 @@ func writeHermesFeishuChannelConfig(confDir string, config dto.AgentFeishuConfig
envMap["FEISHU_ALLOWED_USERS"] = allow envMap["FEISHU_ALLOWED_USERS"] = allow
} }
} }
if err := writeHermesEnvMap(envPath, envMap, []string{ if err := writeAgentEnvMap(envPath, envMap, []string{
"FEISHU_APP_ID", "FEISHU_APP_ID",
"FEISHU_APP_SECRET", "FEISHU_APP_SECRET",
"FEISHU_DOMAIN", "FEISHU_DOMAIN",
@@ -529,7 +529,7 @@ func deleteHermesFeishuChannelConfig(confDir string) error {
} }
func readHermesWeixinChannelConfig(confDir string) (*dto.AgentWeixinConfig, error) { func readHermesWeixinChannelConfig(confDir string) (*dto.AgentWeixinConfig, error) {
envMap, err := readHermesEnvMap(path.Join(confDir, ".env")) envMap, err := readAgentEnvMap(path.Join(confDir, ".env"))
if err != nil { if err != nil {
return nil, err return nil, err
} }
+50 -6
View File
@@ -20,8 +20,10 @@ import (
"github.com/1Panel-dev/1Panel/agent/constant" "github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/global" "github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/utils/common" "github.com/1Panel-dev/1Panel/agent/utils/common"
agentenv "github.com/1Panel-dev/1Panel/agent/utils/env"
"github.com/1Panel-dev/1Panel/agent/utils/files" "github.com/1Panel-dev/1Panel/agent/utils/files"
"github.com/1Panel-dev/1Panel/agent/utils/req_helper" "github.com/1Panel-dev/1Panel/agent/utils/req_helper"
"github.com/joho/godotenv"
"gorm.io/gorm" "gorm.io/gorm"
) )
@@ -376,6 +378,11 @@ func buildAgentItem(agent *model.Agent, appInstall *model.AppInstall, envMap map
item.BridgePort = toInt(bridge) item.BridgePort = toInt(bridge)
} }
} }
if agentType == constant.AppHermesAgent {
auth := readHermesDashboardAuthFromInstall(appInstall)
item.DashboardUsername = auth.Username
item.DashboardPassword = auth.Password
}
} }
return item return item
} }
@@ -860,13 +867,15 @@ func writeOpenclawConfig(confDir string, account *model.AgentAccount, modelName,
if err := writeOpenclawConfigRaw(configPath, conf); err != nil { if err := writeOpenclawConfigRaw(configPath, conf); err != nil {
return err return err
} }
envPath := path.Join(confDir, ".env") envMap := map[string]string{
lines := []string{fmt.Sprintf("OPENCLAW_GATEWAY_TOKEN=%s", token)} "OPENCLAW_GATEWAY_TOKEN": token,
if envKey := providercatalog.EnvKey(account.Provider); envKey != "" && account.APIKey != "" {
lines = append(lines, fmt.Sprintf("%s=%s", envKey, account.APIKey))
} }
content := strings.Join(lines, "\n") + "\n" order := []string{"OPENCLAW_GATEWAY_TOKEN"}
return fileOp.SaveFile(envPath, content, 0600) if envKey := providercatalog.EnvKey(account.Provider); envKey != "" && account.APIKey != "" {
envMap[envKey] = account.APIKey
order = append(order, envKey)
}
return writeAgentEnvMap(path.Join(confDir, ".env"), envMap, order)
} }
func resolveOpenclawFallbackModels(account *model.AgentAccount, primaryModel string, fallbackIDs []string) ([]string, error) { func resolveOpenclawFallbackModels(account *model.AgentAccount, primaryModel string, fallbackIDs []string) ([]string, error) {
@@ -1524,6 +1533,41 @@ func readInstallEnv(envStr string) map[string]interface{} {
return data return data
} }
func readAgentEnvMap(envPath string) (map[string]string, error) {
fileOp := files.NewFileOp()
if !fileOp.Stat(envPath) {
return map[string]string{}, nil
}
envMap, err := godotenv.Read(envPath)
if err != nil {
return nil, err
}
return envMap, nil
}
func writeAgentEnvMap(envPath string, envMap map[string]string, order []string) error {
if len(envMap) == 0 {
return files.NewFileOp().SaveFile(envPath, "", 0600)
}
return agentenv.WriteWithOrder(envMap, envPath, order)
}
func upsertAgentEnv(envPath string, values map[string]string, order []string, overwrite bool) error {
envMap, err := readAgentEnvMap(envPath)
if err != nil {
return err
}
for key, value := range values {
if key == "" {
continue
}
if overwrite || strings.TrimSpace(envMap[key]) == "" {
envMap[key] = value
}
}
return writeAgentEnvMap(envPath, envMap, order)
}
func maskKey(value string) string { func maskKey(value string) string {
trim := strings.TrimSpace(value) trim := strings.TrimSpace(value)
if len(trim) <= 6 { if len(trim) <= 6 {
-1
View File
@@ -705,7 +705,6 @@ func sendAlertsByLegacyMethod(alert dto.AlertDTO, alertType, quota, quotaType st
} }
config, err := alertRepo.GetConfig(alertRepo.WithByType(configType)) config, err := alertRepo.GetConfig(alertRepo.WithByType(configType))
if err != nil { if err != nil {
global.LOG.Errorf("alert config not found for type %s: %v", configType, err)
return return
} }
doSendAlert(alert, alertType, quota, quotaType, params, config) doSendAlert(alert, alertType, quota, quotaType, params, config)
-1
View File
@@ -93,7 +93,6 @@ func (s *AlertSender) sendByLegacyMethod(method string, quota string, params []d
} }
config, err := alertRepo.GetConfig(alertRepo.WithByType(configType)) config, err := alertRepo.GetConfig(alertRepo.WithByType(configType))
if err != nil { if err != nil {
global.LOG.Errorf("alert config not found for type %s: %v", configType, err)
return return
} }
if !alertUtil.IsAlertConfigEnabled(config) { if !alertUtil.IsAlertConfigEnabled(config) {
+1
View File
@@ -294,6 +294,7 @@ func (a *AppInstallService) Operate(req request.AppInstalledOperate) error {
DetailID: req.DetailId, DetailID: req.DetailId,
Backup: req.Backup, Backup: req.Backup,
PullImage: req.PullImage, PullImage: req.PullImage,
DeleteImage: req.DeleteImage,
DockerCompose: req.DockerCompose, DockerCompose: req.DockerCompose,
TaskID: req.TaskID, TaskID: req.TaskID,
} }
+170 -63
View File
@@ -89,7 +89,15 @@ func checkPort(key string, params map[string]interface{}) (int, error) {
return 0, nil return 0, nil
} }
func isPortInUse(port int, protocol string) bool {
return common.ScanPortWithProto(port, normalizeComposeProtocol(protocol))
}
func checkPortExist(port int) error { func checkPortExist(port int) error {
return checkPortExistWithProtocol(port, "")
}
func checkPortExistWithProtocol(port int, protocol string) error {
errMap := make(map[string]interface{}) errMap := make(map[string]interface{})
errMap["port"] = port errMap["port"] = port
appInstall, _ := appInstallRepo.GetFirst(appInstallRepo.WithPort(port)) appInstall, _ := appInstallRepo.GetFirst(appInstallRepo.WithPort(port))
@@ -110,7 +118,7 @@ func checkPortExist(port int) error {
errMap["name"] = domain.Domain errMap["name"] = domain.Domain
return buserr.WithMap("ErrPortExist", errMap, nil) return buserr.WithMap("ErrPortExist", errMap, nil)
} }
if common.ScanPort(port) { if isPortInUse(port, protocol) {
return buserr.WithDetail("ErrPortInUsed", port, nil) return buserr.WithDetail("ErrPortInUsed", port, nil)
} }
return nil return nil
@@ -357,33 +365,13 @@ func deleteAppInstall(deleteReq request.AppInstallDelete) error {
return err return err
} }
if deleteReq.DeleteImage { if deleteReq.DeleteImage {
delImageStr := i18n.GetMsgByKey("TaskDelete") + i18n.GetMsgByKey("Image")
content, err := op.GetContent(install.GetEnvPath()) content, err := op.GetContent(install.GetEnvPath())
if err != nil { if err != nil {
return err return err
} }
images, err := docker.GetImagesFromDockerCompose(content, []byte(install.DockerCompose)) if err = deleteAppImagesByCompose(t, content, []byte(install.DockerCompose), nil); err != nil {
if err != nil {
return err return err
} }
client, err := docker.NewClient()
if err != nil {
return err
}
defer client.Close()
for _, image := range images {
imageID, err := client.GetImageIDByName(image)
if err == nil {
imgStr := delImageStr + image
t.Log(imgStr)
if err = client.DeleteImage(imageID); err != nil {
t.LogFailedWithErr(imgStr, err)
continue
}
t.LogSuccess(delImageStr + image)
}
}
} }
} }
tx, ctx := helper.GetTxAndContext() tx, ctx := helper.GetTxAndContext()
@@ -468,6 +456,69 @@ func deleteAppInstall(deleteReq request.AppInstallDelete) error {
return nil return nil
} }
type appImageID struct {
name string
id string
}
func getAppImageIDsByCompose(client docker.Client, envContent, composeContent []byte) ([]appImageID, error) {
images, err := docker.GetImagesFromDockerCompose(envContent, composeContent)
if err != nil {
return nil, err
}
imageIDs := make([]appImageID, 0, len(images))
for _, image := range images {
imageID, err := client.GetImageIDByName(image)
if err == nil && imageID != "" {
imageIDs = append(imageIDs, appImageID{name: image, id: imageID})
}
}
return imageIDs, nil
}
func deleteAppImagesByCompose(t *task.Task, envContent, composeContent []byte, excludeImages []string) error {
client, err := docker.NewClient()
if err != nil {
return err
}
defer client.Close()
imageIDs, err := getAppImageIDsByCompose(client, envContent, composeContent)
if err != nil {
return err
}
return deleteAppImagesByIDs(t, client, imageIDs, excludeImages)
}
func deleteAppImagesByIDs(t *task.Task, client docker.Client, imageIDs []appImageID, excludeImages []string) error {
delImageStr := i18n.GetMsgByKey("TaskDelete") + i18n.GetMsgByKey("Image")
excludeImageIDs := make(map[string]struct{}, len(excludeImages))
for _, image := range excludeImages {
imageID, err := client.GetImageIDByName(image)
if err == nil && imageID != "" {
excludeImageIDs[imageID] = struct{}{}
}
}
deletedImageIDs := make(map[string]struct{}, len(imageIDs))
for _, image := range imageIDs {
if _, ok := excludeImageIDs[image.id]; ok {
continue
}
if _, ok := deletedImageIDs[image.id]; ok {
continue
}
deletedImageIDs[image.id] = struct{}{}
imgStr := delImageStr + image.name
t.Log(imgStr)
if err := client.DeleteImage(image.id); err != nil {
t.LogFailedWithErr(imgStr, err)
continue
}
t.LogSuccess(imgStr)
}
return nil
}
func deleteLink(del dto.DelAppLink) error { func deleteLink(del dto.DelAppLink) error {
install := del.Install install := del.Install
resources, _ := appInstallResourceRepo.GetBy(appInstallResourceRepo.WithAppInstallId(install.ID)) resources, _ := appInstallResourceRepo.GetBy(appInstallResourceRepo.WithAppInstallId(install.ID))
@@ -751,6 +802,8 @@ func upgradeInstall(req request.AppInstallUpgrade) error {
if err != nil { if err != nil {
return err return err
} }
oldEnvContent := append([]byte(nil), content...)
oldDockerCompose := install.DockerCompose
if install.App.Key == vllmAppKeyForUpgrade { if install.App.Key == vllmAppKeyForUpgrade {
envs := make(map[string]interface{}) envs := make(map[string]interface{})
if err = json.Unmarshal([]byte(install.Env), &envs); err != nil { if err = json.Unmarshal([]byte(install.Env), &envs); err != nil {
@@ -765,33 +818,6 @@ func upgradeInstall(req request.AppInstallUpgrade) error {
install.Env = string(paramByte) install.Env = string(paramByte)
content = setVllmImageInEnvContent(content, image) content = setVllmImageInEnvContent(content, image)
} }
if req.PullImage {
composeContent := []byte(detail.DockerCompose)
if install.App.Key == vllmAppKeyForUpgrade {
composeContent = []byte(install.DockerCompose)
}
if req.DockerCompose != "" {
composeContent = []byte(req.DockerCompose)
}
images, err := docker.GetImagesFromDockerCompose(content, composeContent)
if err != nil {
return err
}
dockerCLi, err := docker.NewClient()
if err != nil {
return err
}
defer dockerCLi.Close()
for _, image := range images {
t.Log(i18n.GetWithName("PullImageStart", image))
if err = dockerCLi.PullImageWithProcess(t, image); err != nil {
err = buserr.WithNameAndErr("ErrDockerPullImage", "", err)
return err
}
t.LogSuccess(i18n.GetMsgByKey("PullImage"))
}
}
_ = copyAppDetailMissing(fileOp, detailDir, install.GetPath()) _ = copyAppDetailMissing(fileOp, detailDir, install.GetPath())
if install.App.Key == constant.AppOpenresty { if install.App.Key == constant.AppOpenresty {
installBuildDir := path.Join(install.GetPath(), "build") installBuildDir := path.Join(install.GetPath(), "build")
@@ -847,6 +873,46 @@ func upgradeInstall(req request.AppInstallUpgrade) error {
install.Version = detail.Version install.Version = detail.Version
install.AppDetailId = req.DetailID install.AppDetailId = req.DetailID
var oldImageIDs []appImageID
if req.DeleteImage {
dockerCLi, err := docker.NewClient()
if err != nil {
return err
}
oldImageIDs, err = getAppImageIDsByCompose(dockerCLi, oldEnvContent, []byte(oldDockerCompose))
dockerCLi.Close()
if err != nil {
return err
}
}
if req.PullImage {
images, err := docker.GetImagesFromDockerCompose(content, []byte(install.DockerCompose))
if err != nil {
return err
}
dockerCLi, err := docker.NewClient()
if err != nil {
return err
}
defer dockerCLi.Close()
for _, image := range images {
t.Log(i18n.GetWithName("PullImageStart", image))
if pullErr := dockerCLi.PullImageWithProcess(t, image); pullErr != nil {
if exist, _ := dockerCLi.ImageExists(image); exist {
t.Log(i18n.GetMsgByKey("UseExistImage"))
continue
}
return buserr.WithNameAndErr("ErrDockerPullImage", "", pullErr)
}
exist, err := dockerCLi.ImageExists(image)
if err != nil || !exist {
return buserr.WithNameAndErr("ErrDockerPullImage", "", fmt.Errorf("image %s does not exist after pull: %v", image, err))
}
t.LogSuccess(i18n.GetMsgByKey("PullImage"))
}
}
if out, err := compose.Down(install.GetComposePath()); err != nil { if out, err := compose.Down(install.GetComposePath()); err != nil {
if out != "" { if out != "" {
upErr = errors.New(out) upErr = errors.New(out)
@@ -897,7 +963,31 @@ func upgradeInstall(req request.AppInstallUpgrade) error {
} }
t.LogSuccess(logStr) t.LogSuccess(logStr)
install.Status = constant.StatusRunning install.Status = constant.StatusRunning
return appInstallRepo.Save(context.Background(), &install) if err = appInstallRepo.Save(context.Background(), &install); err != nil {
return err
}
if req.DeleteImage {
newEnvContent, err := fileOp.GetContent(install.GetEnvPath())
if err != nil {
t.LogFailedWithErr(i18n.GetMsgByKey("TaskDelete")+i18n.GetMsgByKey("Image"), err)
return nil
}
excludeImages, err := docker.GetImagesFromDockerCompose(newEnvContent, []byte(install.DockerCompose))
if err != nil {
t.LogFailedWithErr(i18n.GetMsgByKey("TaskDelete")+i18n.GetMsgByKey("Image"), err)
return nil
}
dockerCLi, err := docker.NewClient()
if err != nil {
t.LogFailedWithErr(i18n.GetMsgByKey("TaskDelete")+i18n.GetMsgByKey("Image"), err)
return nil
}
defer dockerCLi.Close()
if err = deleteAppImagesByIDs(t, dockerCLi, oldImageIDs, excludeImages); err != nil {
t.LogFailedWithErr(i18n.GetMsgByKey("TaskDelete")+i18n.GetMsgByKey("Image"), err)
}
}
return nil
} }
rollBackApp := func(t *task.Task) { rollBackApp := func(t *task.Task) {
@@ -1624,6 +1714,9 @@ func handleInstalled(appInstallList []model.AppInstall, updated, sync, checkUpda
synAppInstall(containersMap, &installed, false) synAppInstall(containersMap, &installed, false)
} }
resourceKeys := getAppInstallResourceKeys(installed.ID)
envMap := make(map[string]interface{})
_ = json.Unmarshal([]byte(installed.Env), &envMap)
installDTO := response.AppInstallDTO{ installDTO := response.AppInstallDTO{
ID: installed.ID, ID: installed.ID,
Name: installed.Name, Name: installed.Name,
@@ -1645,14 +1738,16 @@ func handleInstalled(appInstallList []model.AppInstall, updated, sync, checkUpda
Website: installed.App.Website, Website: installed.App.Website,
Document: installed.App.Document, Document: installed.App.Document,
}, },
Favorite: installed.Favorite, Favorite: installed.Favorite,
SortOrder: installed.SortOrder, SortOrder: installed.SortOrder,
Container: installed.ContainerName, Container: installed.ContainerName,
ServiceName: strings.ToLower(installed.ServiceName), ServiceName: strings.ToLower(installed.ServiceName),
ResourceKeys: resourceKeys,
Env: envMap,
} }
if !updated && !checkUpdate { if !updated && !checkUpdate {
installDTO.LinkDB = hasLinkDB(installed.ID) installDTO.LinkDB = hasLinkDBFromKeys(resourceKeys)
res = append(res, installDTO) res = append(res, installDTO)
continue continue
} }
@@ -1660,7 +1755,7 @@ func handleInstalled(appInstallList []model.AppInstall, updated, sync, checkUpda
if installed.Version == "latest" { if installed.Version == "latest" {
if checkUpdate { if checkUpdate {
installDTO.CanUpdate = false installDTO.CanUpdate = false
installDTO.LinkDB = hasLinkDB(installed.ID) installDTO.LinkDB = hasLinkDBFromKeys(resourceKeys)
res = append(res, installDTO) res = append(res, installDTO)
} }
continue continue
@@ -1689,7 +1784,7 @@ func handleInstalled(appInstallList []model.AppInstall, updated, sync, checkUpda
if len(versions) == 0 { if len(versions) == 0 {
if checkUpdate { if checkUpdate {
installDTO.CanUpdate = false installDTO.CanUpdate = false
installDTO.LinkDB = hasLinkDB(installed.ID) installDTO.LinkDB = hasLinkDBFromKeys(resourceKeys)
res = append(res, installDTO) res = append(res, installDTO)
} }
continue continue
@@ -1721,7 +1816,7 @@ func handleInstalled(appInstallList []model.AppInstall, updated, sync, checkUpda
res = append(res, installDTO) res = append(res, installDTO)
} }
} else if checkUpdate { } else if checkUpdate {
installDTO.LinkDB = hasLinkDB(installed.ID) installDTO.LinkDB = hasLinkDBFromKeys(resourceKeys)
res = append(res, installDTO) res = append(res, installDTO)
} }
} }
@@ -2288,13 +2383,25 @@ func needsUpdate(localTag *model.Tag, remoteTag dto.Tag, translations string) bo
} }
func hasLinkDB(installID uint) bool { func hasLinkDB(installID uint) bool {
return hasLinkDBFromKeys(getAppInstallResourceKeys(installID))
}
func getAppInstallResourceKeys(installID uint) []string {
resources, _ := appInstallResourceRepo.GetBy(appInstallResourceRepo.WithAppInstallId(installID)) resources, _ := appInstallResourceRepo.GetBy(appInstallResourceRepo.WithAppInstallId(installID))
keys := make([]string, 0, len(resources))
for _, resource := range resources {
keys = append(keys, resource.Key)
}
return keys
}
func hasLinkDBFromKeys(resourceKeys []string) bool {
hasDB := false hasDB := false
if len(resources) > 0 { if len(resourceKeys) > 0 {
for _, resource := range resources { for _, resourceKey := range resourceKeys {
if resource.Key == constant.AppPostgres || resource.Key == constant.AppMysql || if resourceKey == constant.AppPostgres || resourceKey == constant.AppMysql ||
resource.Key == constant.AppMariaDB || resource.Key == constant.AppMysqlCluster || resourceKey == constant.AppMariaDB || resourceKey == constant.AppMysqlCluster ||
resource.Key == constant.AppPostgresql || resource.Key == constant.AppPostgresqlCluster { resourceKey == constant.AppPostgresql || resourceKey == constant.AppPostgresqlCluster {
hasDB = true hasDB = true
break break
} }
+22 -3
View File
@@ -63,11 +63,30 @@ func (u *BackupService) AppBackup(req dto.CommonBackup) (*model.BackupRecord, er
return nil, err return nil, err
} }
if err = handleAppBackup(&install, nil, record.ID, backupDir, fileName, "", req.Secret, req.TaskID); err != nil { if !req.IsImmediate {
global.LOG.Errorf("backup app %s failed, err: %v", req.DetailName, err) if err = handleAppBackup(&install, nil, record.ID, backupDir, fileName, "", req.Secret, req.TaskID); err != nil {
return nil, err backupRepo.UpdateRecordByMap(record.ID, map[string]interface{}{"status": constant.StatusFailed, "message": err.Error()})
global.LOG.Errorf("backup app %s failed, err: %v", req.DetailName, err)
return nil, err
}
return record, nil
} }
backupTask, err := task.NewTaskWithOps(install.Name, task.TaskBackup, task.TaskScopeBackup, req.TaskID, install.ID)
if err != nil {
backupRepo.UpdateRecordByMap(record.ID, map[string]interface{}{"status": constant.StatusFailed, "message": err.Error()})
record.Status = constant.StatusFailed
record.Message = err.Error()
return nil, err
}
if err = doAppBackup(&install, backupTask, backupDir, fileName, "", req.Secret); err != nil {
backupRepo.UpdateRecordByMap(record.ID, map[string]interface{}{"status": constant.StatusFailed, "message": err.Error()})
record.Status = constant.StatusFailed
record.Message = err.Error()
return nil, err
}
backupRepo.UpdateRecordByMap(record.ID, map[string]interface{}{"status": constant.StatusSuccess})
record.Status = constant.StatusSuccess
return record, nil return record, nil
} }
-5
View File
@@ -782,11 +782,6 @@ func buildContainerRecoverNetworkConfig(networkSettings *container.NetworkSettin
IPv4Address: endpoint.IPAMConfig.IPv4Address, IPv4Address: endpoint.IPAMConfig.IPv4Address,
IPv6Address: endpoint.IPAMConfig.IPv6Address, IPv6Address: endpoint.IPAMConfig.IPv6Address,
} }
} else if endpoint.IPAddress != "" || endpoint.GlobalIPv6Address != "" {
endpointSetting.IPAMConfig = &network.EndpointIPAMConfig{
IPv4Address: endpoint.IPAddress,
IPv6Address: endpoint.GlobalIPv6Address,
}
} }
if name == primaryName { if name == primaryName {
config.EndpointsConfig[name] = endpointSetting config.EndpointsConfig[name] = endpointSetting
+58 -31
View File
@@ -15,6 +15,7 @@ import (
"os/exec" "os/exec"
"path" "path"
"path/filepath" "path/filepath"
"regexp"
"sort" "sort"
"strconv" "strconv"
"strings" "strings"
@@ -32,7 +33,6 @@ import (
"github.com/1Panel-dev/1Panel/agent/utils/cmd" "github.com/1Panel-dev/1Panel/agent/utils/cmd"
"github.com/1Panel-dev/1Panel/agent/utils/common" "github.com/1Panel-dev/1Panel/agent/utils/common"
"github.com/1Panel-dev/1Panel/agent/utils/docker" "github.com/1Panel-dev/1Panel/agent/utils/docker"
"github.com/1Panel-dev/1Panel/agent/utils/re"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/build" "github.com/docker/docker/api/types/build"
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
@@ -53,6 +53,8 @@ import (
type ContainerService struct{} type ContainerService struct{}
var containerLogAnsiRegex = regexp.MustCompile("\x1b\\[[0-9;?]*[A-Za-z]|\x1b=|\x1b>")
type IContainerService interface { type IContainerService interface {
Page(req dto.PageContainer) (int64, interface{}, error) Page(req dto.PageContainer) (int64, interface{}, error)
List() []dto.ContainerOptions List() []dto.ContainerOptions
@@ -1036,6 +1038,7 @@ func (u *ContainerService) DownloadContainerLogs(containerType, container, since
if cmd.CheckIllegal(container, since, tail) { if cmd.CheckIllegal(container, since, tail) {
return buserr.New("ErrCmdIllegal") return buserr.New("ErrCmdIllegal")
} }
ctx := c.Request.Context()
commandArg := []string{"logs", container} commandArg := []string{"logs", container}
dockerCommand := global.CONF.DockerConfig.Command dockerCommand := global.CONF.DockerConfig.Command
if containerType == "compose" { if containerType == "compose" {
@@ -1065,10 +1068,11 @@ func (u *ContainerService) DownloadContainerLogs(containerType, container, since
} }
var dockerCmd *exec.Cmd var dockerCmd *exec.Cmd
if containerType == "compose" && dockerCommand == "docker-compose" { if containerType == "compose" && dockerCommand == "docker-compose" {
dockerCmd = exec.Command("docker-compose", commandArg...) dockerCmd = exec.CommandContext(ctx, "docker-compose", commandArg...)
} else { } else {
dockerCmd = exec.Command("docker", commandArg...) dockerCmd = exec.CommandContext(ctx, "docker", commandArg...)
} }
dockerCmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
stdout, err := dockerCmd.StdoutPipe() stdout, err := dockerCmd.StdoutPipe()
if err != nil { if err != nil {
return err return err
@@ -1077,15 +1081,20 @@ func (u *ContainerService) DownloadContainerLogs(containerType, container, since
if err := dockerCmd.Start(); err != nil { if err := dockerCmd.Start(); err != nil {
return err return err
} }
defer func() { done := make(chan struct{})
if dockerCmd.Process != nil { go func() {
_ = dockerCmd.Process.Kill() select {
_ = dockerCmd.Wait() case <-ctx.Done():
killContainerLogProcess(dockerCmd)
case <-done:
} }
}() }()
defer close(done)
tempFile, err := os.CreateTemp("", "cmd_output_*.txt") tempFile, err := os.CreateTemp("", "cmd_output_*.txt")
if err != nil { if err != nil {
killContainerLogProcess(dockerCmd)
_ = dockerCmd.Wait()
return err return err
} }
defer tempFile.Close() defer tempFile.Close()
@@ -1094,31 +1103,19 @@ func (u *ContainerService) DownloadContainerLogs(containerType, container, since
global.LOG.Errorf("os.Remove() failed: %v", err) global.LOG.Errorf("os.Remove() failed: %v", err)
} }
}() }()
errCh := make(chan error, 1) copyErr := copyContainerLogOutput(tempFile, stdout)
go func() { waitErr := dockerCmd.Wait()
scanner := bufio.NewScanner(stdout) if copyErr != nil {
var ansiRegex = re.GetRegex(re.AnsiEscapePattern) return copyErr
for scanner.Scan() { }
line := scanner.Text() if waitErr != nil {
cleanLine := ansiRegex.ReplaceAllString(line, "") if ctx.Err() != nil {
if _, err := tempFile.WriteString(cleanLine + "\n"); err != nil { return ctx.Err()
errCh <- err
return
}
} }
if err := scanner.Err(); err != nil { return waitErr
errCh <- err }
return if _, err := tempFile.Seek(0, io.SeekStart); err != nil {
} return err
errCh <- nil
}()
select {
case err := <-errCh:
if err != nil {
global.LOG.Errorf("Error: %v", err)
}
case <-time.After(40 * time.Second):
global.LOG.Errorf("Download container logs timeout reached")
} }
info, _ := tempFile.Stat() info, _ := tempFile.Stat()
@@ -1128,6 +1125,36 @@ func (u *ContainerService) DownloadContainerLogs(containerType, container, since
return nil return nil
} }
func copyContainerLogOutput(dst io.Writer, src io.Reader) error {
reader := bufio.NewReader(src)
for {
line, err := reader.ReadString('\n')
if len(line) > 0 {
cleanLine := containerLogAnsiRegex.ReplaceAllString(line, "")
if _, writeErr := io.WriteString(dst, cleanLine); writeErr != nil {
return writeErr
}
}
if err != nil {
if err == io.EOF {
return nil
}
return err
}
}
}
func killContainerLogProcess(command *exec.Cmd) {
if command == nil || command.Process == nil {
return
}
if pgid, err := syscall.Getpgid(command.Process.Pid); err == nil {
_ = syscall.Kill(-pgid, syscall.SIGKILL)
return
}
_ = command.Process.Kill()
}
func (u *ContainerService) ContainerStats(id string) (*dto.ContainerStats, error) { func (u *ContainerService) ContainerStats(id string) (*dto.ContainerStats, error) {
client, err := docker.NewDockerClient() client, err := docker.NewDockerClient()
if err != nil { if err != nil {
+4
View File
@@ -270,6 +270,10 @@ func (u *ContainerService) ComposeOperation(req dto.ComposeOperation) error {
if stdout, err := compose.Up(req.Path); err != nil { if stdout, err := compose.Up(req.Path); err != nil {
return fmt.Errorf("docker-compose up failed, std: %s, err: %v", stdout, err) return fmt.Errorf("docker-compose up failed, std: %s, err: %v", stdout, err)
} }
} else if req.Operation == "rebuild" {
if stdout, err := compose.DownAndUp(req.Path); err != nil {
return fmt.Errorf("docker-compose rebuild failed, std: %s, err: %v", stdout, err)
}
} else { } else {
if stdout, err := compose.Operate(req.Path, req.Operation); err != nil { if stdout, err := compose.Operate(req.Path, req.Operation); err != nil {
return fmt.Errorf("docker-compose %s failed, std: %s, err: %v", req.Operation, stdout, err) return fmt.Errorf("docker-compose %s failed, std: %s, err: %v", req.Operation, stdout, err)
+10
View File
@@ -187,6 +187,7 @@ func (u *DashboardService) LoadCurrentInfo(ioOption string, netOption string) *d
hostInfo, _ := psutil.HOST.GetHostInfo(false) hostInfo, _ := psutil.HOST.GetHostInfo(false)
currentInfo.Uptime = hostInfo.Uptime currentInfo.Uptime = hostInfo.Uptime
currentInfo.TimeSinceUptime = time.Unix(int64(hostInfo.BootTime), 0).Format(constant.DateTimeLayout) currentInfo.TimeSinceUptime = time.Unix(int64(hostInfo.BootTime), 0).Format(constant.DateTimeLayout)
currentInfo.RunningTime = loadRunningTime(hostInfo.Uptime)
currentInfo.Procs = hostInfo.Procs currentInfo.Procs = hostInfo.Procs
currentInfo.CPUTotal, _ = psutil.CPUInfo.GetLogicalCores(false) currentInfo.CPUTotal, _ = psutil.CPUInfo.GetLogicalCores(false)
@@ -267,6 +268,15 @@ func (u *DashboardService) LoadCurrentInfo(ioOption string, netOption string) *d
return &currentInfo return &currentInfo
} }
func loadRunningTime(uptime uint64) dto.RunningTime {
return dto.RunningTime{
Days: uptime / 86400,
Hours: (uptime % 86400) / 3600,
Minutes: (uptime % 3600) / 60,
Seconds: uptime % 60,
}
}
func (u *DashboardService) LoadTopCPU() []dto.Process { func (u *DashboardService) LoadTopCPU() []dto.Process {
return loadTopCPU() return loadTopCPU()
} }
@@ -0,0 +1,84 @@
package service
import (
"fmt"
"strconv"
"strings"
"github.com/1Panel-dev/1Panel/agent/app/dto/request"
)
func composePortEnvKeys(index int) (containerPort, hostPort, hostIP, protocol string) {
return fmt.Sprintf("CONTAINER_PORT_%d", index),
fmt.Sprintf("HOST_PORT_%d", index),
fmt.Sprintf("HOST_IP_%d", index),
fmt.Sprintf("PORT_PROTOCOL_%d", index)
}
func isComposePortEnvKey(key string) bool {
return strings.HasPrefix(key, "CONTAINER_PORT_") ||
strings.HasPrefix(key, "HOST_PORT_") ||
strings.HasPrefix(key, "HOST_IP_") ||
strings.HasPrefix(key, "PORT_PROTOCOL_")
}
func formatComposePortMapping(hostIP, hostPort, containerPort, protocol string) string {
return fmt.Sprintf("${%s}:${%s}:${%s}/%s", hostIP, hostPort, containerPort, normalizeComposeProtocol(protocol))
}
func normalizeComposeProtocol(protocol string) string {
switch strings.ToLower(strings.TrimSpace(protocol)) {
case "udp":
return "udp"
default:
return "tcp"
}
}
func formatComposeVolume(source, target, mode string) string {
return fmt.Sprintf("%s:%s:%s", source, target, normalizeComposeVolumeMode(mode))
}
func normalizeComposeVolumeMode(mode string) string {
switch strings.ToLower(strings.TrimSpace(mode)) {
case "ro":
return "ro"
default:
return "rw"
}
}
func loadComposeExposedPortsFromEnv(envs map[string]string, defaultHostIP string, strict bool) ([]request.ExposedPort, error) {
var ports []request.ExposedPort
for key, value := range envs {
if !strings.HasPrefix(key, "CONTAINER_PORT_") {
continue
}
index := strings.TrimPrefix(key, "CONTAINER_PORT_")
containerPort, err := strconv.Atoi(value)
if err != nil {
if strict {
return nil, err
}
continue
}
hostPort, err := strconv.Atoi(envs["HOST_PORT_"+index])
if err != nil {
if strict {
return nil, err
}
continue
}
hostIP := envs["HOST_IP_"+index]
if hostIP == "" {
hostIP = defaultHostIP
}
ports = append(ports, request.ExposedPort{
ContainerPort: containerPort,
HostPort: hostPort,
HostIP: hostIP,
Protocol: normalizeComposeProtocol(envs["PORT_PROTOCOL_"+index]),
})
}
return ports, nil
}
+1 -1
View File
@@ -1116,7 +1116,7 @@ func (f *FileService) ReadLogByLine(req request.FileReadByLineReq) (*response.Fi
} }
logFilePath = path.Join(global.Dir.LogDir, "ai", safeName) logFilePath = path.Join(global.Dir.LogDir, "ai", safeName)
default: default:
return nil, buserr.New("ErrNotSupportType") return nil, buserr.WithName("ErrNotSupportType", req.Type)
} }
file, err := os.Open(logFilePath) file, err := os.Open(logFilePath)
+22 -1
View File
@@ -222,7 +222,7 @@ func (u *FirewallService) OperatePortRule(req dto.PortRuleOperate, reload bool)
req.Chain = iptables.Chain1PanelBasic req.Chain = iptables.Chain1PanelBasic
} }
protos := strings.Split(req.Protocol, "/") protos := strings.Split(req.Protocol, "/")
itemAddress := strings.Split(strings.TrimSuffix(req.Address, ","), ",") itemAddress := splitFirewallRuleAddresses(req.Address)
if client.Name() == "ufw" { if client.Name() == "ufw" {
if strings.Contains(req.Port, ",") || strings.Contains(req.Port, "-") { if strings.Contains(req.Port, ",") || strings.Contains(req.Port, "-") {
@@ -515,6 +515,7 @@ func (u *FirewallService) operatePort(client firewall.FirewallClient, req dto.Po
if err := copier.Copy(&fireInfo, &req); err != nil { if err := copier.Copy(&fireInfo, &req); err != nil {
return err return err
} }
fireInfo.Address = normalizeFirewallRuleAddress(fireInfo.Address)
if client.Name() == "ufw" { if client.Name() == "ufw" {
if len(fireInfo.Address) != 0 && !strings.EqualFold(fireInfo.Address, "Anywhere") { if len(fireInfo.Address) != 0 && !strings.EqualFold(fireInfo.Address, "Anywhere") {
@@ -529,6 +530,26 @@ func (u *FirewallService) operatePort(client firewall.FirewallClient, req dto.Po
return client.Port(fireInfo, req.Operation) return client.Port(fireInfo, req.Operation)
} }
func splitFirewallRuleAddresses(address string) []string {
parts := strings.Split(strings.TrimSuffix(address, ","), ",")
addresses := make([]string, 0, len(parts))
for _, part := range parts {
addresses = append(addresses, normalizeFirewallRuleAddress(part))
}
if len(addresses) == 0 {
return []string{""}
}
return addresses
}
func normalizeFirewallRuleAddress(address string) string {
address = strings.TrimSpace(address)
if strings.EqualFold(address, "Anywhere") {
return ""
}
return address
}
type portOfApp struct { type portOfApp struct {
AppName string AppName string
HttpPort string HttpPort string
+1 -1
View File
@@ -502,7 +502,7 @@ func (u *ImageService) ImageRemove(req dto.BatchDelete) error {
return err return err
} }
defer client.Close() defer client.Close()
taskItem, err := task.NewTaskWithOps(task.TaskScopeImage, task.TaskDelete, task.TaskScopeContainer, req.TaskID, 1) taskItem, err := task.NewTaskWithOps(strings.Join(req.Names, ","), task.TaskDelete, task.TaskScopeImage, req.TaskID, 1)
if err != nil { if err != nil {
global.LOG.Errorf("new task for create container failed, err: %v", err) global.LOG.Errorf("new task for create container failed, err: %v", err)
return err return err
+367 -66
View File
@@ -1,18 +1,24 @@
package service package service
import ( import (
"bytes"
"context" "context"
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"io"
"net/http"
"path" "path"
"strconv" "strconv"
"strings" "strings"
"time"
"github.com/1Panel-dev/1Panel/agent/app/dto" "github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/app/dto/request" "github.com/1Panel-dev/1Panel/agent/app/dto/request"
"github.com/1Panel-dev/1Panel/agent/app/dto/response" "github.com/1Panel-dev/1Panel/agent/app/dto/response"
"github.com/1Panel-dev/1Panel/agent/app/model" "github.com/1Panel-dev/1Panel/agent/app/model"
"github.com/1Panel-dev/1Panel/agent/app/repo" "github.com/1Panel-dev/1Panel/agent/app/repo"
"github.com/1Panel-dev/1Panel/agent/app/task"
"github.com/1Panel-dev/1Panel/agent/buserr" "github.com/1Panel-dev/1Panel/agent/buserr"
"github.com/1Panel-dev/1Panel/agent/cmd/server/ai" "github.com/1Panel-dev/1Panel/agent/cmd/server/ai"
"github.com/1Panel-dev/1Panel/agent/cmd/server/nginx_conf" "github.com/1Panel-dev/1Panel/agent/cmd/server/nginx_conf"
@@ -25,18 +31,30 @@ import (
"github.com/1Panel-dev/1Panel/agent/utils/nginx" "github.com/1Panel-dev/1Panel/agent/utils/nginx"
"github.com/1Panel-dev/1Panel/agent/utils/nginx/components" "github.com/1Panel-dev/1Panel/agent/utils/nginx/components"
"github.com/1Panel-dev/1Panel/agent/utils/nginx/parser" "github.com/1Panel-dev/1Panel/agent/utils/nginx/parser"
"github.com/docker/docker/api/types/container"
"github.com/subosito/gotenv" "github.com/subosito/gotenv"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
) )
type McpServerService struct{} type McpServerService struct{}
const (
defaultMcpGatewayImageNpx = "supercorp/supergateway:3.4.3"
defaultMcpGatewayImageUvx = "supercorp/supergateway:uvx"
defaultMcpProtocolVersion = "2025-06-18"
mcpOutputTransportSSE = "sse"
mcpOutputTransportStreamableHTTP = "streamableHttp"
)
type IMcpServerService interface { type IMcpServerService interface {
Page(req request.McpServerSearch) response.McpServersRes Page(req request.McpServerSearch) response.McpServersRes
Detail(req request.McpServerDetail) (response.McpServerDTO, error)
Create(create request.McpServerCreate) error Create(create request.McpServerCreate) error
Update(req request.McpServerUpdate) error Update(req request.McpServerUpdate) error
Delete(id uint) error Delete(id uint) error
Operate(req request.McpServerOperate) error Operate(req request.McpServerOperate) error
SyncStatus(req request.McpServerStatusSync) ([]response.McpServerStatusDTO, error)
TestConnection(req request.McpServerConnectionTest) (response.McpServerConnectionTestRes, error)
GetBindDomain() (response.McpBindDomainRes, error) GetBindDomain() (response.McpBindDomainRes, error)
BindDomain(req request.McpBindDomain) error BindDomain(req request.McpBindDomain) error
UpdateBindDomain(req request.McpBindDomainUpdate) error UpdateBindDomain(req request.McpBindDomainUpdate) error
@@ -54,44 +72,36 @@ func (m McpServerService) Page(req request.McpServerSearch) response.McpServersR
total, data, _ := mcpServerRepo.Page(req.PageInfo.Page, req.PageInfo.PageSize) total, data, _ := mcpServerRepo.Page(req.PageInfo.Page, req.PageInfo.PageSize)
for _, item := range data { for _, item := range data {
_ = syncMcpServerContainerStatus(&item) normalizeMcpServerGateway(&item)
serverDTO := response.McpServerDTO{ items = append(items, response.McpServerDTO{
McpServer: item, McpServer: item,
Environments: make([]request.Environment, 0), Environments: make([]request.Environment, 0),
Volumes: make([]request.Volume, 0), Volumes: make([]request.Volume, 0),
} })
project, err := docker.GetComposeProject(item.Name, path.Join(global.Dir.McpDir, item.Name), []byte(item.DockerCompose), []byte(item.Env), true)
if err != nil {
global.LOG.Errorf("get mcp compose project error: %s", err.Error())
continue
}
for _, service := range project.Services {
if service.Environment != nil {
for key, value := range service.Environment {
serverDTO.Environments = append(serverDTO.Environments, request.Environment{
Key: key,
Value: *value,
})
}
}
if service.Volumes != nil {
for _, volume := range service.Volumes {
serverDTO.Volumes = append(serverDTO.Volumes, request.Volume{
Source: volume.Source,
Target: volume.Target,
})
}
}
}
items = append(items, serverDTO)
} }
res.Total = total res.Total = total
res.Items = items res.Items = items
return res return res
} }
func (m McpServerService) Detail(req request.McpServerDetail) (response.McpServerDTO, error) {
mcpServer, err := mcpServerRepo.GetFirst(repo.WithByID(req.ID))
if err != nil {
return response.McpServerDTO{}, err
}
normalizeMcpServerGateway(mcpServer)
serverDTO := response.McpServerDTO{
McpServer: *mcpServer,
Environments: make([]request.Environment, 0),
Volumes: make([]request.Volume, 0),
}
if err := loadMcpServerComposeConfig(&serverDTO); err != nil {
return response.McpServerDTO{}, err
}
return serverDTO, nil
}
func (m McpServerService) Update(req request.McpServerUpdate) error { func (m McpServerService) Update(req request.McpServerUpdate) error {
go pullImage(req.Type)
mcpServer, err := mcpServerRepo.GetFirst(repo.WithByID(req.ID)) mcpServer, err := mcpServerRepo.GetFirst(repo.WithByID(req.ID))
if err != nil { if err != nil {
return err return err
@@ -115,7 +125,10 @@ func (m McpServerService) Update(req request.McpServerUpdate) error {
mcpServer.HostIP = req.HostIP mcpServer.HostIP = req.HostIP
mcpServer.OutputTransport = req.OutputTransport mcpServer.OutputTransport = req.OutputTransport
mcpServer.Type = req.Type mcpServer.Type = req.Type
if req.OutputTransport == "sse" { mcpServer.GatewayImage = req.GatewayImage
mcpServer.ProtocolVersion = req.ProtocolVersion
normalizeMcpServerGateway(mcpServer)
if req.OutputTransport == mcpOutputTransportSSE {
mcpServer.SsePath = req.SsePath mcpServer.SsePath = req.SsePath
} else { } else {
mcpServer.StreamableHttpPath = req.StreamableHttpPath mcpServer.StreamableHttpPath = req.StreamableHttpPath
@@ -137,12 +150,11 @@ func (m McpServerService) Update(req request.McpServerUpdate) error {
if err := mcpServerRepo.Save(mcpServer); err != nil { if err := mcpServerRepo.Save(mcpServer); err != nil {
return err return err
} }
go startMcp(mcpServer) go runMcpServerTask(mcpServer, req.TaskID, task.TaskUpdate)
return nil return nil
} }
func (m McpServerService) Create(create request.McpServerCreate) error { func (m McpServerService) Create(create request.McpServerCreate) error {
go pullImage(create.Type)
servers, _ := mcpServerRepo.List() servers, _ := mcpServerRepo.List()
for _, server := range servers { for _, server := range servers {
if server.Port == create.Port { if server.Port == create.Port {
@@ -177,8 +189,11 @@ func (m McpServerService) Create(create request.McpServerCreate) error {
HostIP: create.HostIP, HostIP: create.HostIP,
OutputTransport: create.OutputTransport, OutputTransport: create.OutputTransport,
Type: create.Type, Type: create.Type,
GatewayImage: create.GatewayImage,
ProtocolVersion: create.ProtocolVersion,
} }
if create.OutputTransport == "sse" { normalizeMcpServerGateway(mcpServer)
if create.OutputTransport == mcpOutputTransportSSE {
mcpServer.SsePath = create.SsePath mcpServer.SsePath = create.SsePath
} else { } else {
mcpServer.StreamableHttpPath = create.StreamableHttpPath mcpServer.StreamableHttpPath = create.StreamableHttpPath
@@ -205,7 +220,7 @@ func (m McpServerService) Create(create request.McpServerCreate) error {
return err return err
} }
addProxy(mcpServer) addProxy(mcpServer)
go startMcp(mcpServer) go runMcpServerTask(mcpServer, create.TaskID, task.TaskCreate)
return nil return nil
} }
@@ -235,6 +250,9 @@ func (m McpServerService) Operate(req request.McpServerOperate) error {
if err != nil { if err != nil {
return err return err
} }
if err := refreshMcpServerFiles(mcpServer); err != nil {
return err
}
composePath := path.Join(mcpServer.Dir, "docker-compose.yml") composePath := path.Join(mcpServer.Dir, "docker-compose.yml")
var out string var out string
switch req.Operate { switch req.Operate {
@@ -255,6 +273,148 @@ func (m McpServerService) Operate(req request.McpServerOperate) error {
return mcpServerRepo.Save(mcpServer) return mcpServerRepo.Save(mcpServer)
} }
func (m McpServerService) SyncStatus(req request.McpServerStatusSync) ([]response.McpServerStatusDTO, error) {
var (
servers []model.McpServer
err error
)
if len(req.IDs) > 0 {
servers, err = mcpServerRepo.List(repo.WithByIDs(req.IDs))
} else {
servers, err = mcpServerRepo.List()
}
if err != nil {
return nil, err
}
if len(servers) == 0 {
return []response.McpServerStatusDTO{}, nil
}
containerNames := make([]string, 0, len(servers))
for _, server := range servers {
if server.ContainerName != "" {
containerNames = append(containerNames, server.ContainerName)
}
}
containerMap := make(map[string]*container.Summary)
if len(containerNames) > 0 {
cli, err := docker.NewClient()
if err != nil {
return nil, err
}
defer cli.Close()
containers, err := cli.ListContainersByName(containerNames)
if err != nil {
return nil, err
}
for i := range containers {
for _, name := range containers[i].Names {
containerMap[strings.TrimPrefix(name, "/")] = &containers[i]
}
}
}
res := make([]response.McpServerStatusDTO, 0, len(servers))
for i := range servers {
oldStatus := servers[i].Status
applyMcpContainerStatus(&servers[i], containerMap[servers[i].ContainerName])
if servers[i].Status != oldStatus {
if err := mcpServerRepo.Save(&servers[i]); err != nil {
return nil, err
}
}
res = append(res, response.McpServerStatusDTO{
ID: servers[i].ID,
Status: servers[i].Status,
Message: servers[i].Message,
})
}
return res, nil
}
func (m McpServerService) TestConnection(req request.McpServerConnectionTest) (response.McpServerConnectionTestRes, error) {
mcpServer, err := mcpServerRepo.GetFirst(repo.WithByID(req.ID))
if err != nil {
return response.McpServerConnectionTestRes{}, err
}
normalizeMcpServerGateway(mcpServer)
endpoint := buildMcpEndpoint(mcpServer)
res := response.McpServerConnectionTestRes{
Endpoint: endpoint,
OutputTransport: mcpServer.OutputTransport,
ProtocolVersion: mcpServer.ProtocolVersion,
}
if endpoint == "" {
res.Message = "empty endpoint"
return res, nil
}
client := &http.Client{Timeout: 10 * time.Second}
if mcpServer.OutputTransport == mcpOutputTransportSSE {
httpReq, err := http.NewRequest(http.MethodGet, endpoint, nil)
if err != nil {
res.Message = err.Error()
return res, nil
}
httpRes, err := client.Do(httpReq)
if err != nil {
res.Message = err.Error()
return res, nil
}
defer httpRes.Body.Close()
contentType := httpRes.Header.Get("Content-Type")
if httpRes.StatusCode >= 200 && httpRes.StatusCode < 300 && strings.Contains(contentType, "text/event-stream") {
res.Success = true
res.Message = "ok"
return res, nil
}
res.Message = fmt.Sprintf("unexpected response: status=%d content-type=%s", httpRes.StatusCode, contentType)
return res, nil
}
payload := map[string]interface{}{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": map[string]interface{}{
"protocolVersion": mcpServer.ProtocolVersion,
"capabilities": map[string]interface{}{},
"clientInfo": map[string]string{
"name": "1Panel",
"version": "1.0.0",
},
},
}
body, _ := json.Marshal(payload)
httpReq, err := http.NewRequest(http.MethodPost, endpoint, bytes.NewReader(body))
if err != nil {
res.Message = err.Error()
return res, nil
}
httpReq.Header.Set("Content-Type", "application/json")
httpReq.Header.Set("Accept", "application/json, text/event-stream")
httpRes, err := client.Do(httpReq)
if err != nil {
res.Message = err.Error()
return res, nil
}
defer httpRes.Body.Close()
res.Success, res.Message = handleMcpConnectionHTTPResponse(httpRes)
return res, nil
}
func handleMcpConnectionHTTPResponse(httpRes *http.Response) (bool, string) {
if httpRes.StatusCode >= 200 && httpRes.StatusCode < 300 {
return true, "ok"
}
respBody, _ := io.ReadAll(httpRes.Body)
message := strings.TrimSpace(string(respBody))
if message == "" {
message = httpRes.Status
}
return false, message
}
func (m McpServerService) GetBindDomain() (response.McpBindDomainRes, error) { func (m McpServerService) GetBindDomain() (response.McpBindDomainRes, error) {
var res response.McpBindDomainRes var res response.McpBindDomainRes
websiteID := GetWebsiteID() websiteID := GetWebsiteID()
@@ -534,11 +694,9 @@ func addMCPProxy(websiteID uint) error {
} }
func updateMcpServer(mcpServer *model.McpServer) error { func updateMcpServer(mcpServer *model.McpServer) error {
env := handleEnv(mcpServer) if err := refreshMcpServerFiles(mcpServer); err != nil {
if err := gotenv.Write(env, path.Join(mcpServer.Dir, ".env")); err != nil {
return err return err
} }
_ = mcpServerRepo.Save(mcpServer)
composePath := path.Join(global.Dir.McpDir, mcpServer.Name, "docker-compose.yml") composePath := path.Join(global.Dir.McpDir, mcpServer.Name, "docker-compose.yml")
_, _ = compose.Down(composePath) _, _ = compose.Down(composePath)
if _, err := compose.Up(composePath); err != nil { if _, err := compose.Up(composePath); err != nil {
@@ -548,6 +706,106 @@ func updateMcpServer(mcpServer *model.McpServer) error {
return mcpServerRepo.Save(mcpServer) return mcpServerRepo.Save(mcpServer)
} }
func refreshMcpServerFiles(mcpServer *model.McpServer) error {
normalizeMcpServerGateway(mcpServer)
if err := handleCreateParams(mcpServer, nil, nil); err != nil {
return err
}
env := handleEnv(mcpServer)
if err := gotenv.Write(env, path.Join(mcpServer.Dir, ".env")); err != nil {
return err
}
composePath := path.Join(mcpServer.Dir, "docker-compose.yml")
if err := files.NewFileOp().SaveFile(composePath, mcpServer.DockerCompose, 0644); err != nil {
return err
}
return mcpServerRepo.Save(mcpServer)
}
func normalizeMcpServerGateway(mcpServer *model.McpServer) {
if mcpServer.Type == "" {
mcpServer.Type = "npx"
}
if strings.TrimSpace(mcpServer.GatewayImage) == "" {
if mcpServer.Type == "uvx" {
mcpServer.GatewayImage = defaultMcpGatewayImageUvx
} else {
mcpServer.GatewayImage = defaultMcpGatewayImageNpx
}
}
if strings.TrimSpace(mcpServer.ProtocolVersion) == "" {
mcpServer.ProtocolVersion = defaultMcpProtocolVersion
}
}
func buildSupergatewayCommand(mcpServer *model.McpServer) []string {
normalizeMcpServerGateway(mcpServer)
command := []string{
"--stdio", mcpServer.Command,
"--outputTransport", mcpServer.OutputTransport,
"--port", strconv.Itoa(mcpServer.Port),
}
if mcpServer.OutputTransport == mcpOutputTransportSSE {
return append(command,
"--baseUrl", mcpServer.BaseURL,
"--ssePath", mcpServer.SsePath,
"--messagePath", fmt.Sprintf("%s/messages", mcpServer.SsePath),
)
}
command = append(command, "--streamableHttpPath", mcpServer.StreamableHttpPath)
return append(command, "--protocolVersion", mcpServer.ProtocolVersion)
}
func buildMcpEndpoint(mcpServer *model.McpServer) string {
if mcpServer.BaseURL == "" {
return ""
}
if mcpServer.OutputTransport == mcpOutputTransportSSE {
return strings.TrimRight(mcpServer.BaseURL, "/") + "/" + strings.TrimLeft(mcpServer.SsePath, "/")
}
return strings.TrimRight(mcpServer.BaseURL, "/") + "/" + strings.TrimLeft(mcpServer.StreamableHttpPath, "/")
}
func loadMcpServerComposeConfig(serverDTO *response.McpServerDTO) error {
serverDTO.Environments = make([]request.Environment, 0)
serverDTO.Volumes = make([]request.Volume, 0)
dir := serverDTO.Dir
if dir == "" {
dir = path.Join(global.Dir.McpDir, serverDTO.Name)
}
project, err := docker.GetComposeProject(serverDTO.Name, dir, []byte(serverDTO.DockerCompose), []byte(serverDTO.Env), true)
if err != nil {
return err
}
for _, service := range project.Services {
if service.Environment != nil {
for key, value := range service.Environment {
if value == nil {
continue
}
serverDTO.Environments = append(serverDTO.Environments, request.Environment{
Key: key,
Value: *value,
})
}
}
if service.Volumes != nil {
for _, volume := range service.Volumes {
mode := "rw"
if volume.ReadOnly {
mode = "ro"
}
serverDTO.Volumes = append(serverDTO.Volumes, request.Volume{
Source: volume.Source,
Target: volume.Target,
Mode: mode,
})
}
}
}
return nil
}
func handleEnv(mcpServer *model.McpServer) gotenv.Env { func handleEnv(mcpServer *model.McpServer) gotenv.Env {
env := make(gotenv.Env) env := make(gotenv.Env)
env["CONTAINER_NAME"] = mcpServer.ContainerName env["CONTAINER_NAME"] = mcpServer.ContainerName
@@ -558,6 +816,7 @@ func handleEnv(mcpServer *model.McpServer) gotenv.Env {
env["HOST_IP"] = mcpServer.HostIP env["HOST_IP"] = mcpServer.HostIP
env["STREAMABLE_HTTP_PATH"] = mcpServer.StreamableHttpPath env["STREAMABLE_HTTP_PATH"] = mcpServer.StreamableHttpPath
env["OUTPUT_TRANSPORT"] = mcpServer.OutputTransport env["OUTPUT_TRANSPORT"] = mcpServer.OutputTransport
env["GATEWAY_IMAGE"] = mcpServer.GatewayImage
envStr, _ := gotenv.Marshal(env) envStr, _ := gotenv.Marshal(env)
mcpServer.Env = envStr mcpServer.Env = envStr
return env return env
@@ -592,26 +851,39 @@ func handleCreateParams(mcpServer *model.McpServer, environments []request.Envir
} }
delete(services, serviceName) delete(services, serviceName)
} }
normalizeMcpServerGateway(mcpServer)
serviceValue["command"] = buildSupergatewayCommand(mcpServer)
serviceValue["image"] = mcpServer.GatewayImage
serviceValue["ports"] = []string{
formatComposePortMapping("HOST_IP", "PANEL_APP_PORT_HTTP", "PANEL_APP_PORT_HTTP", ""),
}
oldEnv, hasOldEnv := serviceValue["environment"]
delete(serviceValue, "environment") delete(serviceValue, "environment")
if len(environments) > 0 { if environments != nil && len(environments) > 0 {
envMap := make(map[string]string) envMap := make(map[string]string)
for _, env := range environments { for _, env := range environments {
envMap[env.Key] = env.Value envMap[env.Key] = env.Value
} }
serviceValue["environment"] = envMap serviceValue["environment"] = envMap
} else if environments == nil {
// Preserve existing custom environment when regenerating compose during start/restart.
if mcpServer.ID > 0 && hasOldEnv {
serviceValue["environment"] = oldEnv
}
} }
oldVolumes, hasOldVolumes := serviceValue["volumes"]
delete(serviceValue, "volumes") delete(serviceValue, "volumes")
if len(volumes) > 0 { if volumes != nil && len(volumes) > 0 {
volumeList := make([]string, 0) volumeList := make([]string, 0)
for _, volume := range volumes { for _, volume := range volumes {
volumeList = append(volumeList, fmt.Sprintf("%s:%s", volume.Source, volume.Target)) volumeList = append(volumeList, formatComposeVolume(volume.Source, volume.Target, volume.Mode))
} }
serviceValue["volumes"] = volumeList serviceValue["volumes"] = volumeList
} } else if volumes == nil {
if mcpServer.Type == "npx" { // Preserve existing custom volumes when regenerating compose during start/restart.
serviceValue["image"] = "supercorp/supergateway:latest" if mcpServer.ID > 0 && hasOldVolumes {
} else { serviceValue["volumes"] = oldVolumes
serviceValue["image"] = "supercorp/supergateway:uvx" }
} }
services[mcpServer.Name] = serviceValue services[mcpServer.Name] = serviceValue
@@ -623,19 +895,56 @@ func handleCreateParams(mcpServer *model.McpServer, environments []request.Envir
return nil return nil
} }
func runMcpServerTask(mcpServer *model.McpServer, taskID, operate string) {
mcpTask, err := task.NewTaskWithOps(mcpServer.Name, operate, task.TaskScopeAI, taskID, mcpServer.ID)
if err != nil {
mcpServer.Status = constant.StatusError
mcpServer.Message = err.Error()
_ = mcpServerRepo.Save(mcpServer)
return
}
mcpTask.AddSubTask(task.GetTaskName(mcpServer.Name, operate, task.TaskScopeAI), func(t *task.Task) error {
return startMcpWithTask(mcpServer, t)
}, nil)
_ = mcpTask.Execute()
}
func startMcp(mcpServer *model.McpServer) { func startMcp(mcpServer *model.McpServer) {
_ = startMcpWithTask(mcpServer, nil)
}
func startMcpWithTask(mcpServer *model.McpServer, taskItem *task.Task) error {
if err := refreshMcpServerFiles(mcpServer); err != nil {
mcpServer.Status = constant.StatusError
mcpServer.Message = err.Error()
_ = mcpServerRepo.Save(mcpServer)
return err
}
composePath := path.Join(global.Dir.McpDir, mcpServer.Name, "docker-compose.yml") composePath := path.Join(global.Dir.McpDir, mcpServer.Name, "docker-compose.yml")
if mcpServer.Status != constant.StatusNormal { if mcpServer.Status != constant.StatusNormal {
_, _ = compose.Down(composePath) _, _ = compose.Down(composePath)
} }
if out, err := compose.Up(composePath); err != nil { var err error
var out string
if taskItem != nil {
err = compose.UpWithTask(composePath, taskItem, false)
} else {
out, err = compose.Up(composePath)
}
if err != nil {
mcpServer.Status = constant.StatusError mcpServer.Status = constant.StatusError
mcpServer.Message = out if out != "" {
mcpServer.Message = out
} else {
mcpServer.Message = err.Error()
}
_ = mcpServerRepo.Save(mcpServer)
return err
} else { } else {
mcpServer.Status = constant.StatusRunning mcpServer.Status = constant.StatusRunning
mcpServer.Message = "" mcpServer.Message = ""
} }
_ = syncMcpServerContainerStatus(mcpServer) return syncMcpServerContainerStatus(mcpServer)
} }
func syncMcpServerContainerStatus(mcpServer *model.McpServer) error { func syncMcpServerContainerStatus(mcpServer *model.McpServer) error {
@@ -650,11 +959,19 @@ func syncMcpServerContainerStatus(mcpServer *model.McpServer) error {
return err return err
} }
if len(containers) == 0 { if len(containers) == 0 {
mcpServer.Status = constant.StatusStopped applyMcpContainerStatus(mcpServer, nil)
return mcpServerRepo.Save(mcpServer) return mcpServerRepo.Save(mcpServer)
} }
container := containers[0] applyMcpContainerStatus(mcpServer, &containers[0])
switch container.State { return mcpServerRepo.Save(mcpServer)
}
func applyMcpContainerStatus(mcpServer *model.McpServer, containerSummary *container.Summary) {
if containerSummary == nil {
mcpServer.Status = constant.StatusStopped
return
}
switch containerSummary.State {
case "exited": case "exited":
mcpServer.Status = constant.StatusError mcpServer.Status = constant.StatusError
case "running": case "running":
@@ -668,7 +985,6 @@ func syncMcpServerContainerStatus(mcpServer *model.McpServer) error {
mcpServer.Status = constant.StatusStopped mcpServer.Status = constant.StatusStopped
} }
} }
return mcpServerRepo.Save(mcpServer)
} }
func GetWebsiteID() uint { func GetWebsiteID() uint {
@@ -679,18 +995,3 @@ func GetWebsiteID() uint {
websiteIDUint, _ := strconv.ParseUint(websiteID.Value, 10, 64) websiteIDUint, _ := strconv.ParseUint(websiteID.Value, 10, 64)
return uint(websiteIDUint) return uint(websiteIDUint)
} }
func pullImage(imageType string) {
if global.CONF.Base.IsOffline {
return
}
if imageType == "npx" {
if err := docker.PullImage("supercorp/supergateway:latest"); err != nil {
global.LOG.Errorf("docker pull mcp image error: %s", err.Error())
}
} else {
if err := docker.PullImage("supercorp/supergateway:uvx"); err != nil {
global.LOG.Errorf("docker pull mcp image error: %s", err.Error())
}
}
}
+294 -74
View File
@@ -29,6 +29,7 @@ import (
"github.com/1Panel-dev/1Panel/agent/buserr" "github.com/1Panel-dev/1Panel/agent/buserr"
"github.com/1Panel-dev/1Panel/agent/constant" "github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/global" "github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/i18n"
"github.com/1Panel-dev/1Panel/agent/utils/cmd" "github.com/1Panel-dev/1Panel/agent/utils/cmd"
"github.com/1Panel-dev/1Panel/agent/utils/compose" "github.com/1Panel-dev/1Panel/agent/utils/compose"
"github.com/1Panel-dev/1Panel/agent/utils/docker" "github.com/1Panel-dev/1Panel/agent/utils/docker"
@@ -82,6 +83,47 @@ func NewRuntimeService() IRuntimeService {
return &RuntimeService{} return &RuntimeService{}
} }
var pullRuntimeComposeImages = compose.PullComposeImages
var downRuntimeCompose = compose.Down
type runtimeTaskMeta struct {
resourceName string
operate string
scope string
taskID string
resourceID uint
}
func buildRuntimeCreateTaskMeta(create request.RuntimeCreate, runtimeID uint) runtimeTaskMeta {
return runtimeTaskMeta{
resourceName: create.Name,
operate: task.TaskCreate,
scope: task.TaskScopeRuntime,
taskID: create.TaskID,
resourceID: runtimeID,
}
}
func buildRuntimeDeleteTaskMeta(deleteReq request.RuntimeDelete, runtime *model.Runtime) runtimeTaskMeta {
return runtimeTaskMeta{
resourceName: runtime.Name,
operate: task.TaskDelete,
scope: task.TaskScopeRuntime,
taskID: deleteReq.TaskID,
resourceID: deleteReq.ID,
}
}
func runtimeCreateInitialStatus(create request.RuntimeCreate) string {
if create.Type == constant.RuntimePHP {
if create.Resource == constant.ResourceLocal {
return constant.StatusNormal
}
return constant.StatusBuilding
}
return constant.StatusCreating
}
func (r *RuntimeService) Create(create request.RuntimeCreate) (*model.Runtime, error) { func (r *RuntimeService) Create(create request.RuntimeCreate) (*model.Runtime, error) {
var ( var (
opts []repo.DBOption opts []repo.DBOption
@@ -104,20 +146,29 @@ func (r *RuntimeService) Create(create request.RuntimeCreate) (*model.Runtime, e
return nil, err return nil, err
} }
} }
if create.Type == constant.RuntimePHP && create.Resource == constant.ResourceLocal {
runtime := &model.Runtime{
Name: create.Name,
Resource: create.Resource,
Type: create.Type,
Version: create.Version,
Status: runtimeCreateInitialStatus(create),
Remark: create.Remark,
}
if err := runtimeRepo.Create(context.Background(), runtime); err != nil {
return nil, err
}
if err := startRuntimeCreateTask(create, runtime, model.App{}, model.AppDetail{}, ""); err != nil {
runtime.Status = constant.StatusError
runtime.Message = err.Error()
_ = runtimeRepo.Save(runtime)
return nil, err
}
return runtime, nil
}
var hostPorts []string var hostPorts []string
switch create.Type { switch create.Type {
case constant.RuntimePHP: case constant.RuntimePHP:
if create.Resource == constant.ResourceLocal {
runtime := &model.Runtime{
Name: create.Name,
Resource: create.Resource,
Type: create.Type,
Version: create.Version,
Status: constant.StatusNormal,
Remark: create.Remark,
}
return nil, runtimeRepo.Create(context.Background(), runtime)
}
exist, _ = runtimeRepo.GetFirst(context.Background(), runtimeRepo.WithImage(create.Image)) exist, _ = runtimeRepo.GetFirst(context.Background(), runtimeRepo.WithImage(create.Image))
if exist != nil { if exist != nil {
return nil, buserr.New("ErrImageExist") return nil, buserr.New("ErrImageExist")
@@ -134,10 +185,9 @@ func (r *RuntimeService) Create(create request.RuntimeCreate) (*model.Runtime, e
if !fileOp.Stat(create.CodeDir) { if !fileOp.Stat(create.CodeDir) {
return nil, buserr.New("ErrPathNotFound") return nil, buserr.New("ErrPathNotFound")
} }
create.Install = true
for _, export := range create.ExposedPorts { for _, export := range create.ExposedPorts {
hostPorts = append(hostPorts, strconv.Itoa(export.HostPort)) hostPorts = append(hostPorts, strconv.Itoa(export.HostPort))
if err := checkPortExist(export.HostPort); err != nil { if err := checkPortExistWithProtocol(export.HostPort, export.Protocol); err != nil {
return nil, err return nil, err
} }
} }
@@ -160,11 +210,6 @@ func (r *RuntimeService) Create(create request.RuntimeCreate) (*model.Runtime, e
} }
appVersionDir := filepath.Join(app.GetAppResourcePath(), appDetail.Version) appVersionDir := filepath.Join(app.GetAppResourcePath(), appDetail.Version)
if !fileOp.Stat(appVersionDir) {
if err = downloadApp(app, appDetail, nil, nil); err != nil {
return nil, err
}
}
runtime := &model.Runtime{ runtime := &model.Runtime{
Name: create.Name, Name: create.Name,
@@ -176,24 +221,92 @@ func (r *RuntimeService) Create(create request.RuntimeCreate) (*model.Runtime, e
ContainerName: containerName.(string), ContainerName: containerName.(string),
Port: strings.Join(hostPorts, ","), Port: strings.Join(hostPorts, ","),
Remark: create.Remark, Remark: create.Remark,
} Status: runtimeCreateInitialStatus(create),
switch create.Type {
case constant.RuntimePHP:
if err = handlePHP(create, runtime, fileOp, appVersionDir); err != nil {
return nil, err
}
case constant.RuntimeNode, constant.RuntimeJava, constant.RuntimeGo, constant.RuntimePython, constant.RuntimeDotNet:
if err = handleRuntime(create, runtime, fileOp, appVersionDir); err != nil {
return nil, err
}
} }
if err := runtimeRepo.Create(context.Background(), runtime); err != nil { if err := runtimeRepo.Create(context.Background(), runtime); err != nil {
return nil, err return nil, err
} }
if err := startRuntimeCreateTask(create, runtime, app, appDetail, appVersionDir); err != nil {
runtime.Status = constant.StatusError
runtime.Message = err.Error()
_ = runtimeRepo.Save(runtime)
return nil, err
}
return runtime, nil return runtime, nil
} }
func startRuntimeCreateTask(create request.RuntimeCreate, runtime *model.Runtime, app model.App, appDetail model.AppDetail, appVersionDir string) error {
meta := buildRuntimeCreateTaskMeta(create, runtime.ID)
createTask, err := task.NewTaskWithOps(meta.resourceName, meta.operate, meta.scope, meta.taskID, meta.resourceID)
if err != nil {
return err
}
createTask.AddSubTask(task.GetTaskName(create.Name, task.TaskCreate, task.TaskScopeRuntime), func(t *task.Task) error {
return executeRuntimeCreateTask(create, runtime, app, appDetail, appVersionDir, t)
}, nil)
go func() {
_ = createTask.Execute()
}()
return nil
}
func executeRuntimeCreateTask(create request.RuntimeCreate, runtime *model.Runtime, app model.App, appDetail model.AppDetail, appVersionDir string, taskItem *task.Task) error {
if create.Type == constant.RuntimePHP && create.Resource == constant.ResourceLocal {
runtime.Status = constant.StatusNormal
runtime.Message = ""
return runtimeRepo.Save(runtime)
}
if err := downloadApp(app, appDetail, nil, taskItem.Logger); err != nil {
return markRuntimeCreateFailed(runtime, err)
}
go func() {
RequestDownloadCallBack(appDetail.DownloadCallBackUrl)
}()
fileOp := files.NewFileOp()
var err error
switch create.Type {
case constant.RuntimePHP:
err = handlePHP(create, runtime, fileOp, appVersionDir)
case constant.RuntimeNode, constant.RuntimeJava, constant.RuntimeGo, constant.RuntimePython, constant.RuntimeDotNet:
err = handleRuntime(create, runtime, fileOp, appVersionDir)
}
if err != nil {
return markRuntimeCreateFailed(runtime, err)
}
if err = runtimeRepo.Save(runtime); err != nil {
return err
}
switch create.Type {
case constant.RuntimePHP:
return buildRuntimeWithResult(runtime, "", "", false)
case constant.RuntimeNode, constant.RuntimeJava, constant.RuntimeGo, constant.RuntimePython, constant.RuntimeDotNet:
if err := pullRuntimeImagesBeforeStart(create, runtime, taskItem); err != nil {
return markRuntimeCreateFailed(runtime, err)
}
return startRuntimeWithResult(runtime)
}
return nil
}
func pullRuntimeImagesBeforeStart(create request.RuntimeCreate, runtime *model.Runtime, taskItem *task.Task) error {
switch create.Type {
case constant.RuntimeNode, constant.RuntimeJava, constant.RuntimeGo, constant.RuntimePython, constant.RuntimeDotNet:
return pullRuntimeComposeImages(runtime.GetComposePath(), false, taskItem)
default:
return nil
}
}
func markRuntimeCreateFailed(runtime *model.Runtime, err error) error {
runtime.Status = constant.StatusError
runtime.Message = err.Error()
_ = runtimeRepo.Save(runtime)
return err
}
func (r *RuntimeService) Page(req request.RuntimeSearch) (int64, []response.RuntimeDTO, error) { func (r *RuntimeService) Page(req request.RuntimeSearch) (int64, []response.RuntimeDTO, error) {
var ( var (
opts []repo.DBOption opts []repo.DBOption
@@ -241,30 +354,11 @@ func (r *RuntimeService) Page(req request.RuntimeSearch) (int64, []response.Runt
runtimeDTO.AppID = detail.AppId runtimeDTO.AppID = detail.AppId
} }
for k, v := range envs { for k, v := range envs {
runtimeDTO.Params[k] = v if !isComposePortEnvKey(k) {
if strings.Contains(k, "CONTAINER_PORT") || strings.Contains(k, "HOST_PORT") { runtimeDTO.Params[k] = v
if strings.Contains(k, "CONTAINER_PORT") {
matches := re.GetRegex(re.TrailingDigitsPattern).FindStringSubmatch(k)
if len(matches) < 2 {
continue
}
containerPort, err := strconv.Atoi(v)
if err != nil {
continue
}
hostPort, err := strconv.Atoi(envs[fmt.Sprintf("HOST_PORT_%s", matches[1])])
if err != nil {
continue
}
hostIP := envs[fmt.Sprintf("HOST_IP_%s", matches[1])]
runtimeDTO.ExposedPorts = append(runtimeDTO.ExposedPorts, request.ExposedPort{
ContainerPort: containerPort,
HostPort: hostPort,
HostIP: hostIP,
})
}
} }
} }
runtimeDTO.ExposedPorts, _ = loadComposeExposedPortsFromEnv(envs, "", false)
res = append(res, runtimeDTO) res = append(res, runtimeDTO)
} }
return total, res, nil return total, res, nil
@@ -291,31 +385,37 @@ func (r *RuntimeService) Delete(runtimeDelete request.RuntimeDelete) error {
if website.ID > 0 { if website.ID > 0 {
return buserr.New("ErrDelWithWebsite") return buserr.New("ErrDelWithWebsite")
} }
return startRuntimeDeleteTask(runtimeDelete, runtime)
}
func startRuntimeDeleteTask(runtimeDelete request.RuntimeDelete, runtime *model.Runtime) error {
meta := buildRuntimeDeleteTaskMeta(runtimeDelete, runtime)
deleteTask, err := task.NewTaskWithOps(meta.resourceName, meta.operate, meta.scope, meta.taskID, meta.resourceID)
if err != nil {
return err
}
deleteTask.AddSubTask(task.GetTaskName(runtime.Name, task.TaskDelete, task.TaskScopeRuntime), func(t *task.Task) error {
return executeRuntimeDeleteTask(runtimeDelete, runtime, t)
}, nil)
go func() {
_ = deleteTask.Execute()
}()
return nil
}
func executeRuntimeDeleteTask(runtimeDelete request.RuntimeDelete, runtime *model.Runtime, taskItem *task.Task) error {
if runtime.Resource != constant.ResourceAppstore { if runtime.Resource != constant.ResourceAppstore {
if runtimeDelete.DeleteImage {
deleteRuntimeImages(runtime, taskItem)
}
return runtimeRepo.DeleteBy(repo.WithByID(runtimeDelete.ID)) return runtimeRepo.DeleteBy(repo.WithByID(runtimeDelete.ID))
} }
projectDir := runtime.GetPath() projectDir := runtime.GetPath()
if out, err := compose.Down(runtime.GetComposePath()); err != nil && !runtimeDelete.ForceDelete { if err := stopRuntimeBeforeDelete(runtime, runtimeDelete.ForceDelete, taskItem); err != nil {
if out != "" {
return errors.New(out)
}
return err return err
} }
if runtime.Type == constant.RuntimePHP { if runtimeDelete.DeleteImage {
client, err := docker.NewClient() deleteRuntimeImages(runtime, taskItem)
if err != nil {
return err
}
defer client.Close()
imageID, err := client.GetImageIDByName(runtime.Image)
if err != nil {
return err
}
if imageID != "" {
if err := client.DeleteImage(imageID); err != nil {
global.LOG.Errorf("delete image id [%s] error %v", imageID, err)
}
}
} }
if err := files.NewFileOp().DeleteDir(projectDir); err != nil && !runtimeDelete.ForceDelete { if err := files.NewFileOp().DeleteDir(projectDir); err != nil && !runtimeDelete.ForceDelete {
return err return err
@@ -323,6 +423,121 @@ func (r *RuntimeService) Delete(runtimeDelete request.RuntimeDelete) error {
return runtimeRepo.DeleteBy(repo.WithByID(runtimeDelete.ID)) return runtimeRepo.DeleteBy(repo.WithByID(runtimeDelete.ID))
} }
func getRuntimeStopLog() string {
logStr := i18n.GetMsgByKey("Stop") + i18n.GetMsgByKey("Runtime")
if strings.TrimSpace(logStr) == "" {
return "StopRuntime"
}
return logStr
}
func stopRuntimeBeforeDelete(runtime *model.Runtime, forceDelete bool, taskItem *task.Task) error {
logStr := getRuntimeStopLog()
if taskItem != nil {
taskItem.Log(logStr)
}
out, err := downRuntimeCompose(runtime.GetComposePath())
if err != nil && !forceDelete {
if out != "" {
err = errors.New(out)
}
if taskItem != nil {
taskItem.LogFailedWithErr(logStr, err)
}
return err
}
if taskItem != nil {
taskItem.LogSuccess(logStr)
}
return nil
}
func getRuntimeDeleteImages(runtime *model.Runtime) ([]string, error) {
var images []string
imageMap := make(map[string]struct{})
appendImage := func(image string) {
image = strings.TrimSpace(image)
if image == "" {
return
}
if _, ok := imageMap[image]; ok {
return
}
imageMap[image] = struct{}{}
images = append(images, image)
}
appendImage(runtime.Image)
if runtime.DockerCompose != "" {
composeImages, err := docker.GetImagesFromDockerCompose([]byte(runtime.Env), []byte(runtime.DockerCompose))
if err != nil {
return nil, err
}
for _, image := range composeImages {
appendImage(image)
}
}
return images, nil
}
func deleteRuntimeImages(runtime *model.Runtime, taskItem *task.Task) {
logPrefix := i18n.GetMsgByKey("TaskDelete") + i18n.GetMsgByKey("Image")
images, err := getRuntimeDeleteImages(runtime)
if err != nil {
global.LOG.Errorf("get runtime [%s] delete images error %v", runtime.Name, err)
if taskItem != nil {
taskItem.LogFailedWithErr(logPrefix, err)
}
return
}
if len(images) == 0 {
if taskItem != nil {
taskItem.LogFailedWithErr(logPrefix, errors.New(i18n.GetWithName("ErrImageNotExist", runtime.Name)))
}
return
}
client, err := docker.NewClient()
if err != nil {
global.LOG.Errorf("delete runtime images [%s] error %v", runtime.Name, err)
if taskItem != nil {
taskItem.LogFailedWithErr(logPrefix, err)
}
return
}
defer client.Close()
for _, imageName := range images {
logStr := logPrefix + imageName
if taskItem != nil {
taskItem.Log(logStr)
}
imageID, err := client.GetImageIDByName(imageName)
if err != nil {
global.LOG.Errorf("get runtime image [%s] error %v", imageName, err)
if taskItem != nil {
taskItem.LogFailedWithErr(logStr, err)
}
continue
}
if imageID == "" {
if taskItem != nil {
taskItem.LogFailedWithErr(logStr, errors.New(i18n.GetWithName("ErrImageNotExist", imageName)))
}
continue
}
if err := client.DeleteImage(imageID); err != nil {
global.LOG.Errorf("delete image id [%s] error %v", imageID, err)
if taskItem != nil {
taskItem.LogFailedWithErr(logStr, err)
}
continue
}
if taskItem != nil {
taskItem.LogSuccess(logStr)
}
}
}
func (r *RuntimeService) Get(id uint) (*response.RuntimeDTO, error) { func (r *RuntimeService) Get(id uint) (*response.RuntimeDTO, error) {
runtime, err := runtimeRepo.GetFirst(context.Background(), repo.WithByID(id)) runtime, err := runtimeRepo.GetFirst(context.Background(), repo.WithByID(id))
if err != nil { if err != nil {
@@ -435,9 +650,11 @@ func (r *RuntimeService) Update(req request.RuntimeUpdate) error {
return buserr.New("ErrImageExist") return buserr.New("ErrImageExist")
} }
case constant.RuntimeNode, constant.RuntimeJava, constant.RuntimeGo, constant.RuntimePython, constant.RuntimeDotNet: case constant.RuntimeNode, constant.RuntimeJava, constant.RuntimeGo, constant.RuntimePython, constant.RuntimeDotNet:
ownedPortKeys := runtimeOwnedPortKeys(runtime.Env)
for _, export := range req.ExposedPorts { for _, export := range req.ExposedPorts {
hostPorts = append(hostPorts, strconv.Itoa(export.HostPort)) hostPorts = append(hostPorts, strconv.Itoa(export.HostPort))
if err = checkRuntimePortExist(export.HostPort, false, runtime.ID); err != nil { _, owned := ownedPortKeys[composePortCheckKey(export.HostPort, export.Protocol)]
if err = checkRuntimePortExistWithProtocol(export.HostPort, export.Protocol, !owned, runtime.ID); err != nil {
return err return err
} }
} }
@@ -478,7 +695,7 @@ func (r *RuntimeService) Update(req request.RuntimeUpdate) error {
Version: req.Version, Version: req.Version,
Remark: req.Remark, Remark: req.Remark,
NodeConfig: request.NodeConfig{ NodeConfig: request.NodeConfig{
Install: true, Install: req.Install,
ExposedPorts: req.ExposedPorts, ExposedPorts: req.ExposedPorts,
Environments: req.Environments, Environments: req.Environments,
Volumes: req.Volumes, Volumes: req.Volumes,
@@ -1058,6 +1275,7 @@ func (r *RuntimeService) UpdatePHPContainer(req request.PHPContainerConfig) erro
var ( var (
composeContent []byte composeContent []byte
) )
ownedPortKeys := runtimeOwnedPortKeys(runtime.Env)
for _, export := range req.ExposedPorts { for _, export := range req.ExposedPorts {
if strconv.Itoa(export.HostPort) == runtime.Port { if strconv.Itoa(export.HostPort) == runtime.Port {
return buserr.WithName("ErrPHPRuntimePortFailed", strconv.Itoa(export.HostPort)) return buserr.WithName("ErrPHPRuntimePortFailed", strconv.Itoa(export.HostPort))
@@ -1065,7 +1283,8 @@ func (r *RuntimeService) UpdatePHPContainer(req request.PHPContainerConfig) erro
if export.ContainerPort == 9000 { if export.ContainerPort == 9000 {
return buserr.New("ErrPHPPortIsDefault") return buserr.New("ErrPHPPortIsDefault")
} }
if err = checkRuntimePortExist(export.HostPort, false, runtime.ID); err != nil { _, owned := ownedPortKeys[composePortCheckKey(export.HostPort, export.Protocol)]
if err = checkRuntimePortExistWithProtocol(export.HostPort, export.Protocol, !owned, runtime.ID); err != nil {
return err return err
} }
} }
@@ -1090,7 +1309,7 @@ func (r *RuntimeService) UpdatePHPContainer(req request.PHPContainerConfig) erro
return err return err
} }
for k := range envs { for k := range envs {
if strings.HasPrefix(k, "CONTAINER_PORT_") || strings.HasPrefix(k, "HOST_PORT_") || strings.HasPrefix(k, "HOST_IP_") || strings.Contains(k, "APP_PORT") { if isComposePortEnvKey(k) || strings.Contains(k, "APP_PORT") {
delete(envs, k) delete(envs, k)
} }
} }
@@ -1102,6 +1321,7 @@ func (r *RuntimeService) UpdatePHPContainer(req request.PHPContainerConfig) erro
ExposedPorts: req.ExposedPorts, ExposedPorts: req.ExposedPorts,
Environments: req.Environments, Environments: req.Environments,
Volumes: req.Volumes, Volumes: req.Volumes,
ExtraHosts: req.ExtraHosts,
}, },
} }
composeContent, err = handleCompose(envs, composeContent, create, projectDir) composeContent, err = handleCompose(envs, composeContent, create, projectDir)
+79 -68
View File
@@ -19,7 +19,6 @@ import (
cmd2 "github.com/1Panel-dev/1Panel/agent/utils/cmd" cmd2 "github.com/1Panel-dev/1Panel/agent/utils/cmd"
"github.com/1Panel-dev/1Panel/agent/i18n" "github.com/1Panel-dev/1Panel/agent/i18n"
"github.com/1Panel-dev/1Panel/agent/utils/common"
"github.com/1Panel-dev/1Panel/agent/app/dto" "github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/app/dto/request" "github.com/1Panel-dev/1Panel/agent/app/dto/request"
@@ -33,7 +32,6 @@ import (
"github.com/1Panel-dev/1Panel/agent/utils/compose" "github.com/1Panel-dev/1Panel/agent/utils/compose"
"github.com/1Panel-dev/1Panel/agent/utils/docker" "github.com/1Panel-dev/1Panel/agent/utils/docker"
"github.com/1Panel-dev/1Panel/agent/utils/files" "github.com/1Panel-dev/1Panel/agent/utils/files"
"github.com/1Panel-dev/1Panel/agent/utils/re"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/subosito/gotenv" "github.com/subosito/gotenv"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
@@ -67,20 +65,13 @@ func handleRuntime(create request.RuntimeCreate, runtime *model.Runtime, fileOp
runtime.Env = string(envContent) runtime.Env = string(envContent)
runtime.Status = constant.StatusCreating runtime.Status = constant.StatusCreating
runtime.CodeDir = create.CodeDir runtime.CodeDir = create.CodeDir
nodeDetail, err := appDetailRepo.GetFirst(repo.WithByID(runtime.AppDetailID))
if err != nil {
return err
}
go func() {
RequestDownloadCallBack(nodeDetail.DownloadCallBackUrl)
}()
go startRuntime(runtime)
return return
} }
func runtimeNodeShouldInstallDependencies(create request.RuntimeCreate) bool {
return create.NodeConfig.Install == nil || *create.NodeConfig.Install
}
func isPathInsideOrEqual(baseDir, targetDir string) bool { func isPathInsideOrEqual(baseDir, targetDir string) bool {
baseAbs := resolveRuntimePath(baseDir) baseAbs := resolveRuntimePath(baseDir)
targetAbs := resolveRuntimePath(targetDir) targetAbs := resolveRuntimePath(targetDir)
@@ -131,32 +122,28 @@ func handlePHP(create request.RuntimeCreate, runtime *model.Runtime, fileOp file
runtime.Env = string(envContent) runtime.Env = string(envContent)
runtime.Params = string(forms) runtime.Params = string(forms)
runtime.Status = constant.StatusBuilding runtime.Status = constant.StatusBuilding
go func() {
appDetail, err := appDetailRepo.GetFirst(repo.WithByID(runtime.AppDetailID))
if err == nil {
RequestDownloadCallBack(appDetail.DownloadCallBackUrl)
}
}()
go buildRuntime(runtime, "", "", false)
return return
} }
func startRuntime(runtime *model.Runtime) { func startRuntime(runtime *model.Runtime) {
_ = startRuntimeWithResult(runtime)
}
func startRuntimeWithResult(runtime *model.Runtime) error {
if err := runComposeCmdWithLog("up", runtime.GetComposePath(), runtime.GetLogPath()); err != nil { if err := runComposeCmdWithLog("up", runtime.GetComposePath(), runtime.GetLogPath()); err != nil {
runtime.Status = constant.StatusError runtime.Status = constant.StatusError
runtime.Message = err.Error() runtime.Message = err.Error()
_ = runtimeRepo.Save(runtime) _ = runtimeRepo.Save(runtime)
return return err
} }
if err := SyncRuntimeContainerStatus(runtime); err != nil { if err := SyncRuntimeContainerStatus(runtime); err != nil {
runtime.Status = constant.StatusError runtime.Status = constant.StatusError
runtime.Message = err.Error() runtime.Message = err.Error()
_ = runtimeRepo.Save(runtime) _ = runtimeRepo.Save(runtime)
return return err
} }
return nil
} }
func reCreateRuntime(runtime *model.Runtime) { func reCreateRuntime(runtime *model.Runtime) {
@@ -328,6 +315,10 @@ func deleteImageByID(oldImageID, imageName string, client docker.Client) {
} }
func buildRuntime(runtime *model.Runtime, oldImageID string, oldEnv string, rebuild bool) { func buildRuntime(runtime *model.Runtime, oldImageID string, oldEnv string, rebuild bool) {
_ = buildRuntimeWithResult(runtime, oldImageID, oldEnv, rebuild)
}
func buildRuntimeWithResult(runtime *model.Runtime, oldImageID string, oldEnv string, rebuild bool) error {
runtimePath := runtime.GetPath() runtimePath := runtime.GetPath()
composePath := runtime.GetComposePath() composePath := runtime.GetComposePath()
logPath := path.Join(runtimePath, "build.log") logPath := path.Join(runtimePath, "build.log")
@@ -335,11 +326,17 @@ func buildRuntime(runtime *model.Runtime, oldImageID string, oldEnv string, rebu
logFile, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, constant.FilePerm) logFile, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, constant.FilePerm)
if err != nil { if err != nil {
global.LOG.Errorf("failed to open log file: %v", err) global.LOG.Errorf("failed to open log file: %v", err)
return runtime.Status = constant.StatusError
runtime.Message = err.Error()
_ = runtimeRepo.Save(runtime)
return err
} }
defer func() { defer func() {
_ = logFile.Close() _ = logFile.Close()
}() }()
defer func() {
_ = runtimeRepo.Save(runtime)
}()
newPHPVersion := getRuntimeEnv(runtime.Env, "PHP_VERSION") newPHPVersion := getRuntimeEnv(runtime.Env, "PHP_VERSION")
oldPHPVersion := getRuntimeEnv(oldEnv, "PHP_VERSION") oldPHPVersion := getRuntimeEnv(oldEnv, "PHP_VERSION")
@@ -371,16 +368,19 @@ func buildRuntime(runtime *model.Runtime, oldImageID string, oldEnv string, rebu
} else { } else {
runtime.Message = buserr.New("ErrImageBuildErr").Error() + ":" + stderrBuf.String() runtime.Message = buserr.New("ErrImageBuildErr").Error() + ":" + stderrBuf.String()
} }
_ = runtimeRepo.Save(runtime) return err
return
} }
if err = runComposeCmdWithLog(constant.RuntimeDown, runtime.GetComposePath(), runtime.GetLogPath()); err != nil { if err = runComposeCmdWithLog(constant.RuntimeDown, runtime.GetComposePath(), runtime.GetLogPath()); err != nil {
return runtime.Status = constant.StatusError
runtime.Message = err.Error()
return err
} }
client, err := docker.NewClient() client, err := docker.NewClient()
if err != nil { if err != nil {
_, _ = logFile.WriteString(fmt.Sprintf("failed to connect to docker client: %v", err)) _, _ = logFile.WriteString(fmt.Sprintf("failed to connect to docker client: %v", err))
return runtime.Status = constant.StatusError
runtime.Message = err.Error()
return err
} }
runtime.Message = "" runtime.Message = ""
if rebuild && runtime.ID > 0 { if rebuild && runtime.ID > 0 {
@@ -406,14 +406,10 @@ func buildRuntime(runtime *model.Runtime, oldImageID string, oldEnv string, rebu
} }
} }
defer func() {
_ = runtimeRepo.Save(runtime)
}()
if out, err := compose.Up(composePath); err != nil { if out, err := compose.Up(composePath); err != nil {
runtime.Status = constant.StatusStartErr runtime.Status = constant.StatusStartErr
runtime.Message = out runtime.Message = out
return return err
} }
deleteImageID := "" deleteImageID := ""
extensions := getRuntimeEnv(runtime.Env, "PHP_EXTENSIONS") extensions := getRuntimeEnv(runtime.Env, "PHP_EXTENSIONS")
@@ -423,14 +419,14 @@ func buildRuntime(runtime *model.Runtime, oldImageID string, oldEnv string, rebu
if err = cmdMgr.Run("docker", "exec", "-i", runtime.ContainerName, "install-ext", extensions); err != nil { if err = cmdMgr.Run("docker", "exec", "-i", runtime.ContainerName, "install-ext", extensions); err != nil {
runtime.Status = constant.StatusError runtime.Status = constant.StatusError
runtime.Message = buserr.New("ErrImageBuildErr").Error() + ":" + err.Error() runtime.Message = buserr.New("ErrImageBuildErr").Error() + ":" + err.Error()
return return err
} }
commitMgr := cmd2.NewCommandMgr(cmd2.WithTimeout(10*time.Minute), cmd2.WithOutputFile(logPath)) commitMgr := cmd2.NewCommandMgr(cmd2.WithTimeout(10*time.Minute), cmd2.WithOutputFile(logPath))
err = commitMgr.Run("docker", "commit", runtime.ContainerName, runtime.Image) err = commitMgr.Run("docker", "commit", runtime.ContainerName, runtime.Image)
if err != nil { if err != nil {
runtime.Status = constant.StatusError runtime.Status = constant.StatusError
runtime.Message = buserr.New("ErrImageBuildErr").Error() + ":" + err.Error() runtime.Message = buserr.New("ErrImageBuildErr").Error() + ":" + err.Error()
return return err
} }
} }
if oldImageID != "" { if oldImageID != "" {
@@ -443,10 +439,10 @@ func buildRuntime(runtime *model.Runtime, oldImageID string, oldEnv string, rebu
if out, err := compose.DownAndUp(composePath); err != nil { if out, err := compose.DownAndUp(composePath); err != nil {
runtime.Status = constant.StatusStartErr runtime.Status = constant.StatusStartErr
runtime.Message = out runtime.Message = out
return return err
} }
runtime.Status = constant.StatusRunning runtime.Status = constant.StatusRunning
_ = runtimeRepo.Save(runtime) return nil
} }
func handleParams(create request.RuntimeCreate, projectDir string) (composeContent []byte, envContent []byte, forms []byte, err error) { func handleParams(create request.RuntimeCreate, projectDir string) (composeContent []byte, envContent []byte, forms []byte, err error) {
@@ -464,7 +460,7 @@ func handleParams(create request.RuntimeCreate, projectDir string) (composeConte
return return
} }
for k := range env { for k := range env {
if strings.HasPrefix(k, "CONTAINER_PORT_") || strings.HasPrefix(k, "HOST_PORT_") || strings.HasPrefix(k, "HOST_IP_") || strings.Contains(k, "APP_PORT") { if isComposePortEnvKey(k) || strings.Contains(k, "APP_PORT") {
delete(env, k) delete(env, k)
} }
} }
@@ -510,7 +506,7 @@ func handleParams(create request.RuntimeCreate, projectDir string) (composeConte
case constant.RuntimeNode: case constant.RuntimeNode:
create.Params["CODE_DIR"] = create.CodeDir create.Params["CODE_DIR"] = create.CodeDir
create.Params["NODE_VERSION"] = create.Version create.Params["NODE_VERSION"] = create.Version
if create.NodeConfig.Install { if runtimeNodeShouldInstallDependencies(create) {
create.Params["RUN_INSTALL"] = "1" create.Params["RUN_INSTALL"] = "1"
} else { } else {
create.Params["RUN_INSTALL"] = "0" create.Params["RUN_INSTALL"] = "0"
@@ -621,15 +617,16 @@ func handleCompose(env gotenv.Env, composeContent []byte, create request.Runtime
if len(create.ExposedPorts) > 0 { if len(create.ExposedPorts) > 0 {
var ports []interface{} var ports []interface{}
for i, port := range create.ExposedPorts { for i, port := range create.ExposedPorts {
containerPortStr := fmt.Sprintf("CONTAINER_PORT_%d", i) containerPortStr, hostPortStr, hostIPStr, protocolStr := composePortEnvKeys(i)
hostPortStr := fmt.Sprintf("HOST_PORT_%d", i)
existMap[containerPortStr] = struct{}{} existMap[containerPortStr] = struct{}{}
existMap[hostPortStr] = struct{}{} existMap[hostPortStr] = struct{}{}
hostIPStr := fmt.Sprintf("HOST_IP_%d", i) existMap[hostIPStr] = struct{}{}
ports = append(ports, fmt.Sprintf("${%s}:${%s}:${%s}", hostIPStr, hostPortStr, containerPortStr)) existMap[protocolStr] = struct{}{}
ports = append(ports, formatComposePortMapping(hostIPStr, hostPortStr, containerPortStr, port.Protocol))
create.Params[containerPortStr] = port.ContainerPort create.Params[containerPortStr] = port.ContainerPort
create.Params[hostPortStr] = port.HostPort create.Params[hostPortStr] = port.HostPort
create.Params[hostIPStr] = port.HostIP create.Params[hostIPStr] = port.HostIP
create.Params[protocolStr] = normalizeComposeProtocol(port.Protocol)
} }
if create.Type == constant.RuntimePHP { if create.Type == constant.RuntimePHP {
ports = append(ports, "127.0.0.1:${PANEL_APP_PORT_HTTP}:9000") ports = append(ports, "127.0.0.1:${PANEL_APP_PORT_HTTP}:9000")
@@ -662,7 +659,7 @@ func handleCompose(env gotenv.Env, composeContent []byte, create request.Runtime
volumes = append(volumes, fmt.Sprintf("%s:%s", k, v)) volumes = append(volumes, fmt.Sprintf("%s:%s", k, v))
} }
for _, volume := range create.Volumes { for _, volume := range create.Volumes {
volumes = append(volumes, fmt.Sprintf("%s:%s", volume.Source, volume.Target)) volumes = append(volumes, formatComposeVolume(volume.Source, volume.Target, volume.Mode))
} }
var extraHosts []interface{} var extraHosts []interface{}
@@ -678,7 +675,7 @@ func handleCompose(env gotenv.Env, composeContent []byte, create request.Runtime
break break
} }
for k := range env { for k := range env {
if strings.Contains(k, "CONTAINER_PORT_") || strings.Contains(k, "HOST_PORT_") { if isComposePortEnvKey(k) {
if _, ok := existMap[k]; !ok { if _, ok := existMap[k]; !ok {
delete(env, k) delete(env, k)
} }
@@ -872,9 +869,14 @@ func getDockerComposeVolumes(yml []byte) ([]request.Volume, error) {
if len(envArray) > 1 { if len(envArray) > 1 {
target = envArray[1] target = envArray[1]
} }
mode := ""
if len(envArray) > 2 {
mode = envArray[2]
}
res = append(res, request.Volume{ res = append(res, request.Volume{
Source: source, Source: source,
Target: target, Target: target,
Mode: normalizeComposeVolumeMode(mode),
}) })
} }
} }
@@ -908,7 +910,31 @@ func getDockerComposeExtraHosts(yml []byte) ([]request.ExtraHost, error) {
return res, nil return res, nil
} }
func composePortCheckKey(port int, protocol string) string {
return fmt.Sprintf("%d/%s", port, normalizeComposeProtocol(protocol))
}
func runtimeOwnedPortKeys(envStr string) map[string]struct{} {
portKeys := make(map[string]struct{})
envs, err := gotenv.Unmarshal(envStr)
if err != nil {
return portKeys
}
exposedPorts, err := loadComposeExposedPortsFromEnv(envs, "", false)
if err != nil {
return portKeys
}
for _, port := range exposedPorts {
portKeys[composePortCheckKey(port.HostPort, port.Protocol)] = struct{}{}
}
return portKeys
}
func checkRuntimePortExist(port int, scanPort bool, runtimeID uint) error { func checkRuntimePortExist(port int, scanPort bool, runtimeID uint) error {
return checkRuntimePortExistWithProtocol(port, "", scanPort, runtimeID)
}
func checkRuntimePortExistWithProtocol(port int, protocol string, scanPort bool, runtimeID uint) error {
errMap := make(map[string]interface{}) errMap := make(map[string]interface{})
errMap["port"] = port errMap["port"] = port
appInstall, _ := appInstallRepo.GetFirst(appInstallRepo.WithPort(port)) appInstall, _ := appInstallRepo.GetFirst(appInstallRepo.WithPort(port))
@@ -933,7 +959,7 @@ func checkRuntimePortExist(port int, scanPort bool, runtimeID uint) error {
errMap["name"] = domain.Domain errMap["name"] = domain.Domain
return buserr.WithMap("ErrPortExist", errMap, nil) return buserr.WithMap("ErrPortExist", errMap, nil)
} }
if scanPort && common.ScanPort(port) { if scanPort && isPortInUse(port, protocol) {
return buserr.WithDetail("ErrPortInUsed", port, nil) return buserr.WithDetail("ErrPortInUsed", port, nil)
} }
return nil return nil
@@ -1006,31 +1032,16 @@ func handleRuntimeDTO(res *response.RuntimeDTO, runtime model.Runtime) error {
return err return err
} }
for k, v := range envs { for k, v := range envs {
if strings.Contains(k, "CONTAINER_PORT") || strings.Contains(k, "HOST_PORT") { if isComposePortEnvKey(k) {
if strings.Contains(k, "CONTAINER_PORT") { continue
matches := re.GetRegex(re.TrailingDigitsPattern).FindStringSubmatch(k)
if len(matches) < 2 {
return fmt.Errorf("invalid container port key: %s", k)
}
containerPort, err := strconv.Atoi(v)
if err != nil {
return err
}
hostPort, err := strconv.Atoi(envs[fmt.Sprintf("HOST_PORT_%s", matches[1])])
if err != nil {
return err
}
hostIP := envs[fmt.Sprintf("HOST_IP_%s", matches[1])]
res.ExposedPorts = append(res.ExposedPorts, request.ExposedPort{
ContainerPort: containerPort,
HostPort: hostPort,
HostIP: hostIP,
})
}
} else { } else {
res.Params[k] = v res.Params[k] = v
} }
} }
res.ExposedPorts, err = loadComposeExposedPortsFromEnv(envs, "", true)
if err != nil {
return err
}
if v, ok := envs["CONTAINER_PACKAGE_URL"]; ok { if v, ok := envs["CONTAINER_PACKAGE_URL"]; ok {
res.Source = v res.Source = v
} }
+8 -38
View File
@@ -23,7 +23,6 @@ import (
"github.com/1Panel-dev/1Panel/agent/utils/docker" "github.com/1Panel-dev/1Panel/agent/utils/docker"
"github.com/1Panel-dev/1Panel/agent/utils/env" "github.com/1Panel-dev/1Panel/agent/utils/env"
"github.com/1Panel-dev/1Panel/agent/utils/files" "github.com/1Panel-dev/1Panel/agent/utils/files"
"github.com/1Panel-dev/1Panel/agent/utils/re"
) )
type TensorRTLLMService struct{} type TensorRTLLMService struct{}
@@ -59,33 +58,7 @@ func (t TensorRTLLMService) Page(req request.TensorRTLLMSearch) response.TensorR
serverDTO.Image = envs["IMAGE"] serverDTO.Image = envs["IMAGE"]
serverDTO.Command = getCommand(item.Env) serverDTO.Command = getCommand(item.Env)
for k, v := range envs { serverDTO.ExposedPorts, _ = loadComposeExposedPortsFromEnv(envs, "0.0.0.0", false)
if strings.Contains(k, "CONTAINER_PORT") || strings.Contains(k, "HOST_PORT") {
if strings.Contains(k, "CONTAINER_PORT") {
matches := re.GetRegex(re.TrailingDigitsPattern).FindStringSubmatch(k)
if len(matches) < 2 {
continue
}
containerPort, err := strconv.Atoi(v)
if err != nil {
continue
}
hostPort, err := strconv.Atoi(envs[fmt.Sprintf("HOST_PORT_%s", matches[1])])
if err != nil {
continue
}
hostIP := envs[fmt.Sprintf("HOST_IP_%s", matches[1])]
if hostIP == "" {
hostIP = "0.0.0.0"
}
serverDTO.ExposedPorts = append(serverDTO.ExposedPorts, request.ExposedPort{
ContainerPort: containerPort,
HostPort: hostPort,
HostIP: hostIP,
})
}
}
}
composeByte, err := files.NewFileOp().GetContent(path.Join(global.Dir.TensorRTLLMDir, item.Name, "docker-compose.yml")) composeByte, err := files.NewFileOp().GetContent(path.Join(global.Dir.TensorRTLLMDir, item.Name, "docker-compose.yml"))
if err == nil { if err == nil {
@@ -149,11 +122,9 @@ func handleLLMParams(llm *model.TensorRTLLM, create request.TensorRTLLMCreate) e
delete(serviceValue, "ports") delete(serviceValue, "ports")
if len(create.ExposedPorts) > 0 { if len(create.ExposedPorts) > 0 {
var ports []interface{} var ports []interface{}
for i := range create.ExposedPorts { for i, port := range create.ExposedPorts {
containerPortStr := fmt.Sprintf("CONTAINER_PORT_%d", i) containerPortStr, hostPortStr, hostIPStr, _ := composePortEnvKeys(i)
hostPortStr := fmt.Sprintf("HOST_PORT_%d", i) ports = append(ports, formatComposePortMapping(hostIPStr, hostPortStr, containerPortStr, port.Protocol))
hostIPStr := fmt.Sprintf("HOST_IP_%d", i)
ports = append(ports, fmt.Sprintf("${%s}:${%s}:${%s}", hostIPStr, hostPortStr, containerPortStr))
} }
serviceValue["ports"] = ports serviceValue["ports"] = ports
} }
@@ -174,7 +145,7 @@ func handleLLMParams(llm *model.TensorRTLLM, create request.TensorRTLLMCreate) e
volumes = append(volumes, fmt.Sprintf("%s:%s", k, v)) volumes = append(volumes, fmt.Sprintf("%s:%s", k, v))
} }
for _, volume := range create.Volumes { for _, volume := range create.Volumes {
volumes = append(volumes, fmt.Sprintf("%s:%s", volume.Source, volume.Target)) volumes = append(volumes, formatComposeVolume(volume.Source, volume.Target, volume.Mode))
} }
serviceValue["volumes"] = volumes serviceValue["volumes"] = volumes
@@ -195,12 +166,11 @@ func handleLLMEnv(llm *model.TensorRTLLM, create request.TensorRTLLMCreate) gote
envMap["IMAGE"] = create.Image envMap["IMAGE"] = create.Image
envMap["COMMAND"] = create.Command envMap["COMMAND"] = create.Command
for i, port := range create.ExposedPorts { for i, port := range create.ExposedPorts {
containerPortStr := fmt.Sprintf("CONTAINER_PORT_%d", i) containerPortStr, hostPortStr, hostIPStr, protocolStr := composePortEnvKeys(i)
hostPortStr := fmt.Sprintf("HOST_PORT_%d", i)
hostIPStr := fmt.Sprintf("HOST_IP_%d", i)
envMap[containerPortStr] = strconv.Itoa(port.ContainerPort) envMap[containerPortStr] = strconv.Itoa(port.ContainerPort)
envMap[hostPortStr] = strconv.Itoa(port.HostPort) envMap[hostPortStr] = strconv.Itoa(port.HostPort)
envMap[hostIPStr] = port.HostIP envMap[hostIPStr] = port.HostIP
envMap[protocolStr] = normalizeComposeProtocol(port.Protocol)
} }
orders := []string{"MODEL_PATH", "COMMAND"} orders := []string{"MODEL_PATH", "COMMAND"}
envStr, _ := env.MarshalWithOrder(envMap, orders) envStr, _ := env.MarshalWithOrder(envMap, orders)
@@ -219,7 +189,7 @@ func (t TensorRTLLMService) Create(create request.TensorRTLLMCreate) error {
} }
} }
for _, export := range create.ExposedPorts { for _, export := range create.ExposedPorts {
if err := checkPortExist(export.HostPort); err != nil { if err := checkPortExistWithProtocol(export.HostPort, export.Protocol); err != nil {
return err return err
} }
} }
+16 -3
View File
@@ -12,6 +12,7 @@ const (
vllmImageEnvKey = "IMAGE" vllmImageEnvKey = "IMAGE"
vllmImageTypeNvidia = "nvidia" vllmImageTypeNvidia = "nvidia"
vllmImageTypeIntel = "intel" vllmImageTypeIntel = "intel"
vllmImageTypeAscend = "ascend"
) )
func resolveVllmVersionFamily(version, image string) string { func resolveVllmVersionFamily(version, image string) string {
@@ -19,6 +20,9 @@ func resolveVllmVersionFamily(version, image string) string {
if strings.HasPrefix(normalizedVersion, vllmImageTypeIntel+"-") { if strings.HasPrefix(normalizedVersion, vllmImageTypeIntel+"-") {
return vllmImageTypeIntel return vllmImageTypeIntel
} }
if strings.HasPrefix(normalizedVersion, vllmImageTypeAscend+"-") {
return vllmImageTypeAscend
}
if strings.HasPrefix(normalizedVersion, vllmImageTypeNvidia+"-") { if strings.HasPrefix(normalizedVersion, vllmImageTypeNvidia+"-") {
return vllmImageTypeNvidia return vllmImageTypeNvidia
} }
@@ -26,13 +30,16 @@ func resolveVllmVersionFamily(version, image string) string {
if strings.Contains(normalizedImage, "intel/") || strings.Contains(normalizedImage, "llm-scaler-vllm") { if strings.Contains(normalizedImage, "intel/") || strings.Contains(normalizedImage, "llm-scaler-vllm") {
return vllmImageTypeIntel return vllmImageTypeIntel
} }
if strings.Contains(normalizedImage, "ascend/") || strings.Contains(normalizedImage, "vllm-ascend") {
return vllmImageTypeAscend
}
return vllmImageTypeNvidia return vllmImageTypeNvidia
} }
func trimVllmVersionFamily(version string) string { func trimVllmVersionFamily(version string) string {
trimmed := strings.TrimSpace(version) trimmed := strings.TrimSpace(version)
normalized := strings.ToLower(trimmed) normalized := strings.ToLower(trimmed)
for _, family := range []string{vllmImageTypeNvidia, vllmImageTypeIntel} { for _, family := range []string{vllmImageTypeNvidia, vllmImageTypeIntel, vllmImageTypeAscend} {
prefix := family + "-" prefix := family + "-"
if strings.HasPrefix(normalized, prefix) { if strings.HasPrefix(normalized, prefix) {
return strings.TrimSpace(trimmed[len(prefix):]) return strings.TrimSpace(trimmed[len(prefix):])
@@ -43,12 +50,16 @@ func trimVllmVersionFamily(version string) string {
func buildDefaultVllmImageByVersion(version string) string { func buildDefaultVllmImageByVersion(version string) string {
tag := trimVllmVersionFamily(version) tag := trimVllmVersionFamily(version)
if resolveVllmVersionFamily(version, "") == vllmImageTypeIntel { family := resolveVllmVersionFamily(version, "")
if family == vllmImageTypeIntel {
return "intel/llm-scaler-vllm:" + tag return "intel/llm-scaler-vllm:" + tag
} }
if tag != "" && !strings.HasPrefix(strings.ToLower(tag), "v") { if tag != "" && !strings.HasPrefix(strings.ToLower(tag), "v") {
tag = "v" + tag tag = "v" + tag
} }
if family == vllmImageTypeAscend {
return "quay.io/ascend/vllm-ascend:" + tag
}
return "vllm/vllm-openai:" + tag return "vllm/vllm-openai:" + tag
} }
@@ -60,7 +71,9 @@ func isVllmUpgradeVersionAllowed(currentVersion, targetVersion, currentImage str
func hasVllmVersionFamilyPrefix(version string) bool { func hasVllmVersionFamilyPrefix(version string) bool {
normalized := strings.ToLower(strings.TrimSpace(version)) normalized := strings.ToLower(strings.TrimSpace(version))
return strings.HasPrefix(normalized, vllmImageTypeNvidia+"-") || strings.HasPrefix(normalized, vllmImageTypeIntel+"-") return strings.HasPrefix(normalized, vllmImageTypeNvidia+"-") ||
strings.HasPrefix(normalized, vllmImageTypeIntel+"-") ||
strings.HasPrefix(normalized, vllmImageTypeAscend+"-")
} }
func isVllmUpgradeCandidate(currentVersion, targetVersion, currentImage string) bool { func isVllmUpgradeCandidate(currentVersion, targetVersion, currentImage string) bool {
+2 -4
View File
@@ -168,15 +168,13 @@ func (w WebsiteService) PageWebsite(req request.WebsiteSearch) (int64, []respons
opts = append(opts, repo.WithOrderRuleBy(req.OrderBy, req.Order), repo.WithOrderRuleBy("updated_at", "descending")) opts = append(opts, repo.WithOrderRuleBy(req.OrderBy, req.Order), repo.WithOrderRuleBy("updated_at", "descending"))
if req.Name != "" { if req.Name != "" {
domains, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithDomainLike(req.Name)) domains, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithDomainLike(req.Name))
var websiteIds []uint
if len(domains) > 0 { if len(domains) > 0 {
var websiteIds []uint
for _, domain := range domains { for _, domain := range domains {
websiteIds = append(websiteIds, domain.WebsiteID) websiteIds = append(websiteIds, domain.WebsiteID)
} }
opts = append(opts, repo.WithByIDs(websiteIds))
} else {
opts = append(opts, websiteRepo.WithDomainLike(req.Name))
} }
opts = append(opts, websiteRepo.WithSearchKeyword(req.Name, websiteIds))
} }
if req.WebsiteGroupID != 0 { if req.WebsiteGroupID != 0 {
opts = append(opts, websiteRepo.WithGroupID(req.WebsiteGroupID)) opts = append(opts, websiteRepo.WithGroupID(req.WebsiteGroupID))
+6
View File
@@ -207,6 +207,7 @@ func (w WebsiteCAService) ObtainSSL(req request.WebsiteCAObtain) (*model.Website
Description: req.Description, Description: req.Description,
ExecShell: req.ExecShell, ExecShell: req.ExecShell,
} }
setSSLPushConfig(websiteSSL, req.PushNode, req.Nodes)
if req.ExecShell { if req.ExecShell {
websiteSSL.Shell = req.Shell websiteSSL.Shell = req.Shell
} }
@@ -384,6 +385,11 @@ func (w WebsiteCAService) ObtainSSL(req request.WebsiteCAObtain) (*model.Website
} }
} }
reloadSystemSSL(websiteSSL, logger) reloadSystemSSL(websiteSSL, logger)
if websiteSSL.PushNode {
if err = pushSSLToNode(websiteSSL, logger); err != nil {
return nil, err
}
}
return websiteSSL, nil return websiteSSL, nil
} }
+120 -18
View File
@@ -18,12 +18,12 @@ import (
"github.com/go-acme/lego/v5/certificate" "github.com/go-acme/lego/v5/certificate"
legoLogger "github.com/go-acme/lego/v5/log" legoLogger "github.com/go-acme/lego/v5/log"
"github.com/jinzhu/gorm"
"github.com/1Panel-dev/1Panel/agent/app/dto/request" "github.com/1Panel-dev/1Panel/agent/app/dto/request"
"github.com/1Panel-dev/1Panel/agent/app/dto/response" "github.com/1Panel-dev/1Panel/agent/app/dto/response"
"github.com/1Panel-dev/1Panel/agent/app/model" "github.com/1Panel-dev/1Panel/agent/app/model"
"github.com/1Panel-dev/1Panel/agent/app/repo" "github.com/1Panel-dev/1Panel/agent/app/repo"
"github.com/1Panel-dev/1Panel/agent/app/task"
"github.com/1Panel-dev/1Panel/agent/buserr" "github.com/1Panel-dev/1Panel/agent/buserr"
"github.com/1Panel-dev/1Panel/agent/constant" "github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/global" "github.com/1Panel-dev/1Panel/agent/global"
@@ -104,6 +104,7 @@ type IWebsiteSSLService interface {
Delete(ids []uint) error Delete(ids []uint) error
Update(update request.WebsiteSSLUpdate) error Update(update request.WebsiteSSLUpdate) error
Upload(req request.WebsiteSSLUpload) error Upload(req request.WebsiteSSLUpload) error
PushToNode(req request.WebsiteSSLPush) error
ObtainSSL(apply request.WebsiteSSLApply) error ObtainSSL(apply request.WebsiteSSLApply) error
AutoRenewSSL(id uint) error AutoRenewSSL(id uint) error
SyncForRestart() error SyncForRestart() error
@@ -214,10 +215,7 @@ func (w WebsiteSSLService) Create(create request.WebsiteSSLCreate) (request.Webs
} }
websiteSSL.Dir = create.Dir websiteSSL.Dir = create.Dir
} }
if create.PushNode && global.IsMaster && len(create.Nodes) > 0 { setSSLPushConfig(&websiteSSL, create.PushNode, create.Nodes)
websiteSSL.PushNode = true
websiteSSL.Nodes = create.Nodes
}
var domains []string var domains []string
if create.OtherDomains != "" { if create.OtherDomains != "" {
@@ -282,6 +280,47 @@ func printSSLLog(logger *log.Logger, msgKey string, params map[string]interface{
logger.Println(i18n.GetMsgWithMap(msgKey, params)) logger.Println(i18n.GetMsgWithMap(msgKey, params))
} }
func normalizeSSLPushConfig(pushNode bool, nodes string) (bool, string) {
nodes = strings.TrimSpace(nodes)
if !pushNode || nodes == "" {
return false, ""
}
return true, nodes
}
func setSSLPushConfig(websiteSSL *model.WebsiteSSL, pushNode bool, nodes string) {
pushNode, nodes = normalizeSSLPushConfig(pushNode, nodes)
if !global.IsMaster || !xpack.MultiNodeProvider.IsXpack() {
pushNode = false
nodes = ""
}
websiteSSL.PushNode = pushNode
websiteSSL.Nodes = nodes
}
func pushSSLToNode(websiteSSL *model.WebsiteSSL, logger *log.Logger) error {
printSSLLog(logger, "StartPushSSLToNode", nil)
if err := xpack.MultiNodeProvider.PushSSLToNode(websiteSSL); err != nil {
printSSLLog(logger, "PushSSLToNodeFailed", map[string]interface{}{"err": err.Error()})
return err
}
printSSLLog(logger, "PushSSLToNodeSuccess", nil)
return nil
}
func pushSSLToNodeWithNewLogger(websiteSSL *model.WebsiteSSL) error {
if !websiteSSL.PushNode {
return nil
}
logFile, logger := newWebsiteSSLLogger(websiteSSL, false)
if logFile != nil {
defer func() {
_ = logFile.Close()
}()
}
return pushSSLToNode(websiteSSL, logger)
}
func newWebsiteSSLLogger(websiteSSL *model.WebsiteSSL, autoRenew bool) (*os.File, *log.Logger) { func newWebsiteSSLLogger(websiteSSL *model.WebsiteSSL, autoRenew bool) (*os.File, *log.Logger) {
flags := os.O_CREATE | os.O_WRONLY | os.O_TRUNC flags := os.O_CREATE | os.O_WRONLY | os.O_TRUNC
if autoRenew { if autoRenew {
@@ -422,7 +461,7 @@ func (w WebsiteSSLService) obtainSSL(id uint, autoRenew bool) error {
case constant.Http: case constant.Http:
appInstall, err := getAppInstallByKey(constant.AppOpenresty) appInstall, err := getAppInstallByKey(constant.AppOpenresty)
if err != nil { if err != nil {
if gorm.IsRecordNotFoundError(err) { if errors.Is(err, gormv2.ErrRecordNotFound) {
return buserr.New("ErrOpenrestyNotFound") return buserr.New("ErrOpenrestyNotFound")
} }
return err return err
@@ -567,12 +606,9 @@ func (w WebsiteSSLService) obtainSSL(id uint, autoRenew bool) error {
} }
reloadSystemSSL(websiteSSL, logger) reloadSystemSSL(websiteSSL, logger)
if websiteSSL.PushNode { if websiteSSL.PushNode {
printSSLLog(logger, "StartPushSSLToNode", nil) if err = pushSSLToNode(websiteSSL, logger); err != nil {
if err = xpack.MultiNodeProvider.PushSSLToNode(websiteSSL); err != nil {
printSSLLog(logger, "PushSSLToNodeFailed", map[string]interface{}{"err": err.Error()})
return return
} }
printSSLLog(logger, "PushSSLToNodeSuccess", nil)
} }
}(logFile, logger) }(logFile, logger)
@@ -740,13 +776,13 @@ func (w WebsiteSSLService) Update(update request.WebsiteSSLUpdate) error {
} else { } else {
updateParams["shell"] = "" updateParams["shell"] = ""
} }
if update.PushNode { pushNode, nodes := normalizeSSLPushConfig(update.PushNode, update.Nodes)
updateParams["push_node"] = true if !global.IsMaster || !xpack.MultiNodeProvider.IsXpack() {
updateParams["nodes"] = update.Nodes pushNode = false
} else { nodes = ""
updateParams["push_node"] = false
updateParams["nodes"] = ""
} }
updateParams["push_node"] = pushNode
updateParams["nodes"] = nodes
if websiteSSL.Provider != constant.SelfSigned && websiteSSL.Provider != constant.Manual { if websiteSSL.Provider != constant.SelfSigned && websiteSSL.Provider != constant.Manual {
acmeAccount, err := websiteAcmeRepo.GetFirst(repo.WithByID(update.AcmeAccountID)) acmeAccount, err := websiteAcmeRepo.GetFirst(repo.WithByID(update.AcmeAccountID))
@@ -797,6 +833,7 @@ func (w WebsiteSSLService) Upload(req request.WebsiteSSLUpload) error {
Description: req.Description, Description: req.Description,
Status: constant.SSLReady, Status: constant.SSLReady,
} }
setSSLPushConfig(websiteSSL, req.PushNode, req.Nodes)
var err error var err error
if req.SSLID > 0 { if req.SSLID > 0 {
websiteSSL, err = websiteSSLRepo.GetFirst(repo.WithByID(req.SSLID)) websiteSSL, err = websiteSSLRepo.GetFirst(repo.WithByID(req.SSLID))
@@ -804,6 +841,7 @@ func (w WebsiteSSLService) Upload(req request.WebsiteSSLUpload) error {
return err return err
} }
websiteSSL.Description = req.Description websiteSSL.Description = req.Description
setSSLPushConfig(websiteSSL, req.PushNode, req.Nodes)
} }
if req.Type == "local" { if req.Type == "local" {
fileOp := files.NewFileOp() fileOp := files.NewFileOp()
@@ -891,9 +929,73 @@ func (w WebsiteSSLService) Upload(req request.WebsiteSSLUpload) error {
if err := UpdateSSLConfig(*websiteSSL); err != nil { if err := UpdateSSLConfig(*websiteSSL); err != nil {
return err return err
} }
return websiteSSLRepo.Save(websiteSSL) if err := websiteSSLRepo.Save(websiteSSL); err != nil {
return err
}
return pushSSLToNodeWithNewLogger(websiteSSL)
} }
return websiteSSLRepo.Create(context.Background(), websiteSSL) if err := websiteSSLRepo.Create(context.Background(), websiteSSL); err != nil {
return err
}
return pushSSLToNodeWithNewLogger(websiteSSL)
}
func (w WebsiteSSLService) PushToNode(req request.WebsiteSSLPush) error {
if !global.IsMaster {
return errors.New("only master node can push SSL to nodes")
}
if !xpack.MultiNodeProvider.IsXpack() {
return errors.New("SSL node push is an XPack feature")
}
pushNode, nodes := normalizeSSLPushConfig(req.PushNode, req.Nodes)
if !pushNode {
return errors.New("please select nodes to push SSL")
}
websiteSSL, err := websiteSSLRepo.GetFirst(repo.WithByID(req.ID))
if err != nil {
return err
}
if websiteSSL.Provider == constant.FromMaster {
return errors.New("SSL imported from master node can not be pushed")
}
if websiteSSL.Status != constant.SSLReady {
return errors.New("only ready SSL can be pushed")
}
if task.CheckResourceTaskIsExecuting(task.TaskPush, task.TaskScopeWebsite, websiteSSL.ID) {
return buserr.New("TaskIsExecuting")
}
if err := websiteSSLRepo.SaveByMap(websiteSSL, map[string]interface{}{
"push_node": pushNode,
"nodes": nodes,
}); err != nil {
return err
}
websiteSSL.PushNode = pushNode
websiteSSL.Nodes = nodes
if req.Sync {
return xpack.MultiNodeProvider.PushSSLToNode(websiteSSL)
}
pushTask, err := task.NewTask(task.GetTaskName(websiteSSL.PrimaryDomain, task.TaskPush, "SSL"), task.TaskPush, task.TaskScopeWebsite, req.TaskID, websiteSSL.ID)
if err != nil {
return err
}
pushTask.AddSubTask(i18n.GetMsgByKey("StartPushSSLToNode"), func(t *task.Task) error {
t.Log(i18n.GetMsgByKey("StartPushSSLToNode"))
if err := xpack.MultiNodeProvider.PushSSLToNode(websiteSSL); err != nil {
t.Log(i18n.GetMsgWithMap("PushSSLToNodeFailed", map[string]interface{}{"err": err.Error()}))
return err
}
t.Log(i18n.GetMsgByKey("PushSSLToNodeSuccess"))
return nil
}, nil)
go func() {
if err := pushTask.Execute(); err != nil {
global.LOG.Errorf("push ssl to node failed, sslID: %d, err: %v", websiteSSL.ID, err)
}
}()
return nil
} }
func (w WebsiteSSLService) DownloadFile(id uint) (*os.File, error) { func (w WebsiteSSLService) DownloadFile(id uint) (*os.File, error) {
+358 -53
View File
@@ -1247,6 +1247,33 @@
"formatZH": "更新 AI 网关分组 [name]", "formatZH": "更新 AI 网关分组 [name]",
"formatEN": "update AI proxy group [name]" "formatEN": "update AI proxy group [name]"
}, },
"/core/enterprise/ai-proxy/model-groups/create": {
"bodyKeys": [
"name"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "创建 AI 网关模型组 [name]",
"formatEN": "create AI proxy model group [name]"
},
"/core/enterprise/ai-proxy/model-groups/delete": {
"bodyKeys": [
"id"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "删除 AI 网关模型组 [id]",
"formatEN": "delete AI proxy model group [id]"
},
"/core/enterprise/ai-proxy/model-groups/update": {
"bodyKeys": [
"name"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "更新 AI 网关模型组 [name]",
"formatEN": "update AI proxy model group [name]"
},
"/core/enterprise/ai-proxy/service/operate": { "/core/enterprise/ai-proxy/service/operate": {
"bodyKeys": [ "bodyKeys": [
"operate" "operate"
@@ -1368,13 +1395,14 @@
"/core/enterprise/skills-hub/import": { "/core/enterprise/skills-hub/import": {
"bodyKeys": [ "bodyKeys": [
"type", "type",
"version",
"repoURL", "repoURL",
"packageURL" "packageURL"
], ],
"paramKeys": [], "paramKeys": [],
"beforeFunctions": [], "beforeFunctions": [],
"formatZH": "导入 Skills Hub 技能 [type]", "formatZH": "导入 Skills Hub 技能版本 [version]",
"formatEN": "import Skills Hub skill [type]" "formatEN": "import Skills Hub skill version [version]"
}, },
"/core/enterprise/skills-hub/status": { "/core/enterprise/skills-hub/status": {
"bodyKeys": [ "bodyKeys": [
@@ -1478,11 +1506,13 @@
"formatEN": "update Skills Hub install target [name]" "formatEN": "update Skills Hub install target [name]"
}, },
"/core/enterprise/skills-hub/upload": { "/core/enterprise/skills-hub/upload": {
"bodyKeys": [], "bodyKeys": [
"version"
],
"paramKeys": [], "paramKeys": [],
"beforeFunctions": [], "beforeFunctions": [],
"formatZH": "上传 Skills Hub 技能包", "formatZH": "上传 Skills Hub 技能包版本 [version]",
"formatEN": "upload Skills Hub package" "formatEN": "upload Skills Hub package version [version]"
}, },
"/core/enterprise/users": { "/core/enterprise/users": {
"bodyKeys": [ "bodyKeys": [
@@ -1493,6 +1523,25 @@
"formatZH": "添加用户 [name]", "formatZH": "添加用户 [name]",
"formatEN": "add user [name]" "formatEN": "add user [name]"
}, },
"/core/enterprise/users/api/update": {
"bodyKeys": [
"id",
"ipWhiteList"
],
"paramKeys": [],
"beforeFunctions": [
{
"input_column": "id",
"input_value": "id",
"isList": false,
"db": "users",
"output_column": "name",
"output_value": "name"
}
],
"formatZH": "更新用户 [name] API 接口配置 =\u003e IP 白名单: [ipWhiteList]",
"formatEN": "update user [name] api config =\u003e IP White List: [ipWhiteList]"
},
"/core/enterprise/users/del": { "/core/enterprise/users/del": {
"bodyKeys": [ "bodyKeys": [
"ids" "ids"
@@ -1529,6 +1578,255 @@
"formatZH": "更新 [name]", "formatZH": "更新 [name]",
"formatEN": "update user [name]" "formatEN": "update user [name]"
}, },
"/core/enterprise/vms": {
"bodyKeys": [
"name"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "创建虚拟机 [name]",
"formatEN": "create VM [name]"
},
"/core/enterprise/vms/del": {
"bodyKeys": [
"name"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "删除虚拟机 [name]",
"formatEN": "delete VM [name]"
},
"/core/enterprise/vms/iso": {
"bodyKeys": [
"name",
"type"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "创建虚拟机镜像 [name] [type]",
"formatEN": "create VM ISO [name] [type]"
},
"/core/enterprise/vms/iso/del": {
"bodyKeys": [
"id"
],
"paramKeys": [],
"beforeFunctions": [
{
"input_column": "id",
"input_value": "id",
"isList": false,
"db": "vm_isos",
"output_column": "name",
"output_value": "name"
}
],
"formatZH": "删除虚拟机镜像 [name]",
"formatEN": "delete VM ISO [name]"
},
"/core/enterprise/vms/iso/update": {
"bodyKeys": [
"name",
"type"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "更新虚拟机镜像 [name] [type]",
"formatEN": "update VM ISO [name] [type]"
},
"/core/enterprise/vms/networks": {
"bodyKeys": [
"name",
"type"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "创建虚拟机网络 [name] [type]",
"formatEN": "create VM network [name] [type]"
},
"/core/enterprise/vms/networks/del": {
"bodyKeys": [
"id"
],
"paramKeys": [],
"beforeFunctions": [
{
"input_column": "id",
"input_value": "id",
"isList": false,
"db": "vm_networks",
"output_column": "name",
"output_value": "name"
}
],
"formatZH": "删除虚拟机网络 [name]",
"formatEN": "delete VM network [name]"
},
"/core/enterprise/vms/networks/sync": {
"bodyKeys": [],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "同步虚拟机网络",
"formatEN": "sync VM networks"
},
"/core/enterprise/vms/networks/update": {
"bodyKeys": [
"id"
],
"paramKeys": [],
"beforeFunctions": [
{
"input_column": "id",
"input_value": "id",
"isList": false,
"db": "vm_networks",
"output_column": "name",
"output_value": "name"
}
],
"formatZH": "更新虚拟机网络 [name]",
"formatEN": "update VM network [name]"
},
"/core/enterprise/vms/operate": {
"bodyKeys": [
"name",
"operate"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "操作虚拟机 [name] [operate]",
"formatEN": "operate VM [name] [operate]"
},
"/core/enterprise/vms/rename": {
"bodyKeys": [
"name",
"newName"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "重命名虚拟机 [name] 为 [newName]",
"formatEN": "rename VM [name] to [newName]"
},
"/core/enterprise/vms/snapshots": {
"bodyKeys": [
"name",
"snapshotName"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "创建虚拟机 [name] 快照 [snapshotName]",
"formatEN": "create VM [name] snapshot [snapshotName]"
},
"/core/enterprise/vms/snapshots/del": {
"bodyKeys": [
"name",
"snapshotName"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "删除虚拟机 [name] 快照 [snapshotName]",
"formatEN": "delete VM [name] snapshot [snapshotName]"
},
"/core/enterprise/vms/snapshots/recover": {
"bodyKeys": [
"name",
"snapshotName"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "恢复虚拟机 [name] 快照 [snapshotName]",
"formatEN": "recover VM [name] snapshot [snapshotName]"
},
"/core/enterprise/vms/storages": {
"bodyKeys": [
"name",
"type"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "创建虚拟机存储 [name] [type]",
"formatEN": "create VM storage [name] [type]"
},
"/core/enterprise/vms/storages/del": {
"bodyKeys": [
"id"
],
"paramKeys": [],
"beforeFunctions": [
{
"input_column": "id",
"input_value": "id",
"isList": false,
"db": "vm_storages",
"output_column": "name",
"output_value": "name"
}
],
"formatZH": "删除虚拟机存储 [name]",
"formatEN": "delete VM storage [name]"
},
"/core/enterprise/vms/storages/sync": {
"bodyKeys": [],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "同步虚拟机存储",
"formatEN": "sync VM storages"
},
"/core/enterprise/vms/storages/update": {
"bodyKeys": [
"id"
],
"paramKeys": [],
"beforeFunctions": [
{
"input_column": "id",
"input_value": "id",
"isList": false,
"db": "vm_storages",
"output_column": "name",
"output_value": "name"
}
],
"formatZH": "更新虚拟机存储 [name]",
"formatEN": "update VM storage [name]"
},
"/core/enterprise/vms/templates": {
"bodyKeys": [
"name",
"templateName"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "创建虚拟机 [name] 模板 [templateName]",
"formatEN": "create VM [name] template [templateName]"
},
"/core/enterprise/vms/templates/del": {
"bodyKeys": [
"id"
],
"paramKeys": [],
"beforeFunctions": [
{
"input_column": "id",
"input_value": "id",
"isList": false,
"db": "vm_templates",
"output_column": "name",
"output_value": "name"
}
],
"formatZH": "删除虚拟机模板 [name]",
"formatEN": "delete VM template [name]"
},
"/core/enterprise/vms/update": {
"bodyKeys": [
"name"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "更新虚拟机 [name]",
"formatEN": "update VM [name]"
},
"/core/groups": { "/core/groups": {
"bodyKeys": [ "bodyKeys": [
"name", "name",
@@ -1853,15 +2151,22 @@
}, },
"/core/xpack/exchange/file": { "/core/xpack/exchange/file": {
"bodyKeys": [ "bodyKeys": [
"source", "sourceNode",
"dest", "targetNode",
"sourcePath", "sourcePath",
"destPath" "targetPath"
], ],
"paramKeys": [], "paramKeys": [],
"beforeFunctions": [], "beforeFunctions": [],
"formatZH": "交换文件 [sourcePath] 到 [destPath]", "formatZH": "交换文件 [sourcePath] 到 [targetPath]",
"formatEN": "exchange file [sourcePath] to [destPath]" "formatEN": "exchange file [sourcePath] to [targetPath]"
},
"/core/xpack/exchange/image": {
"bodyKeys": [],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "同步节点镜像",
"formatEN": "sync images"
}, },
"/core/xpack/nodes": { "/core/xpack/nodes": {
"bodyKeys": [ "bodyKeys": [
@@ -2166,6 +2471,15 @@
"formatZH": "更新自定义应用配置 [status]", "formatZH": "更新自定义应用配置 [status]",
"formatEN": "update custom app config [status]" "formatEN": "update custom app config [status]"
}, },
"/core/xpack/settings/app/image-prefix": {
"bodyKeys": [
"imagePrefix"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "更新应用镜像前缀 [imagePrefix]",
"formatEN": "update app image prefix [imagePrefix]"
},
"/core/xpack/settings/reset": { "/core/xpack/settings/reset": {
"bodyKeys": [], "bodyKeys": [],
"paramKeys": [], "paramKeys": [],
@@ -2191,27 +2505,11 @@
"formatEN": "update xpack setting [key]" "formatEN": "update xpack setting [key]"
}, },
"/core/xpack/sync/app": { "/core/xpack/sync/app": {
"bodyKeys": [ "bodyKeys": [],
"sourceNode",
"targetNode",
"appInstallID",
"appBackupID"
],
"paramKeys": [], "paramKeys": [],
"beforeFunctions": [], "beforeFunctions": [],
"formatZH": "同步应用备份 [appInstallID] 到节点 [targetNode]", "formatZH": "同步节点应用",
"formatEN": "sync app backup [appInstallID] to node [targetNode]" "formatEN": "sync app"
},
"/core/xpack/sync/app/install": {
"bodyKeys": [
"appKey",
"version",
"nodes"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "安装应用 [appKey] [version] 到节点 [nodes]",
"formatEN": "install app [appKey] [version] to nodes [nodes]"
}, },
"/core/xpack/sync/ssl": { "/core/xpack/sync/ssl": {
"bodyKeys": [ "bodyKeys": [
@@ -2352,34 +2650,14 @@
"formatZH": "更新自定义应用配置 [status]", "formatZH": "更新自定义应用配置 [status]",
"formatEN": "update custom app config [status]" "formatEN": "update custom app config [status]"
}, },
"/custom/app/install": { "/custom/app/image-prefix": {
"bodyKeys": [ "bodyKeys": [
"name", "imagePrefix"
"appKey"
], ],
"paramKeys": [], "paramKeys": [],
"beforeFunctions": [], "beforeFunctions": [],
"formatZH": "从节点安装应用 [name]", "formatZH": "更新应用镜像前缀 [imagePrefix]",
"formatEN": "install app [name] from node" "formatEN": "update app image prefix [imagePrefix]"
},
"/custom/app/install/check": {
"bodyKeys": [
"name",
"appKey"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "检查应用安装 [name]",
"formatEN": "check app install [name]"
},
"/custom/app/push": {
"bodyKeys": [
"appBackupID"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "推送应用备份 [appBackupID] 到节点",
"formatEN": "push app backup [appBackupID] to node"
}, },
"/custom/app/sync": { "/custom/app/sync": {
"bodyKeys": [], "bodyKeys": [],
@@ -4440,6 +4718,24 @@
"formatZH": "申请证书 [domain]", "formatZH": "申请证书 [domain]",
"formatEN": "apply ssl [domain]" "formatEN": "apply ssl [domain]"
}, },
"/websites/ssl/push": {
"bodyKeys": [
"id"
],
"paramKeys": [],
"beforeFunctions": [
{
"input_column": "id",
"input_value": "id",
"isList": false,
"db": "website_ssls",
"output_column": "primary_domain",
"output_value": "domain"
}
],
"formatZH": "推送证书到节点 [domain]",
"formatEN": "Push ssl to nodes [domain]"
},
"/websites/ssl/update": { "/websites/ssl/update": {
"bodyKeys": [ "bodyKeys": [
"id" "id"
@@ -4935,6 +5231,15 @@
"formatZH": "更新[scope]频率访问限制", "formatZH": "更新[scope]频率访问限制",
"formatEN": "update [scope] CC config" "formatEN": "update [scope] CC config"
}, },
"/xpack/waf/rule/common/apply": {
"bodyKeys": [
"scope"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "应用规则 [scope] 到网站",
"formatEN": "apply rule [scope] to websites"
},
"/xpack/waf/rule/common/create": { "/xpack/waf/rule/common/create": {
"bodyKeys": [ "bodyKeys": [
"scope" "scope"
@@ -434,5 +434,12 @@
"file": "lz4.so", "file": "lz4.so",
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"], "versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
"installed": false "installed": false
},
{
"name": "msgpack",
"check": "msgpack",
"file": "msgpack.so",
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
"installed": false
} }
] ]
+8 -8
View File
@@ -6,9 +6,9 @@ replace github.com/moby/go-archive => github.com/moby/go-archive v0.1.0
require ( require (
github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible
github.com/compose-spec/compose-go/v2 v2.11.0 github.com/compose-spec/compose-go/v2 v2.12.1
github.com/creack/pty v1.1.24 github.com/creack/pty v1.1.24
github.com/docker/cli v29.5.3+incompatible github.com/docker/cli v29.6.1+incompatible
github.com/docker/docker v28.5.2+incompatible github.com/docker/docker v28.5.2+incompatible
github.com/docker/go-connections v0.7.0 github.com/docker/go-connections v0.7.0
github.com/fsnotify/fsnotify v1.10.1 github.com/fsnotify/fsnotify v1.10.1
@@ -30,14 +30,14 @@ require (
github.com/klauspost/compress v1.18.6 github.com/klauspost/compress v1.18.6
github.com/mholt/archiver/v4 v4.0.0-alpha.8 github.com/mholt/archiver/v4 v4.0.0-alpha.8
github.com/miekg/dns v1.1.72 github.com/miekg/dns v1.1.72
github.com/minio/minio-go/v7 v7.2.0 github.com/minio/minio-go/v7 v7.2.1
github.com/nicksnyder/go-i18n/v2 v2.6.1 github.com/nicksnyder/go-i18n/v2 v2.6.1
github.com/opencontainers/image-spec v1.1.1 github.com/opencontainers/image-spec v1.1.1
github.com/oschwald/maxminddb-golang v1.13.1 github.com/oschwald/maxminddb-golang v1.13.1
github.com/patrickmn/go-cache v2.1.0+incompatible github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/pkg/errors v0.9.1 github.com/pkg/errors v0.9.1
github.com/pkg/sftp v1.13.10 github.com/pkg/sftp v1.13.10
github.com/qiniu/go-sdk/v7 v7.26.12 github.com/qiniu/go-sdk/v7 v7.26.13
github.com/robfig/cron/v3 v3.0.1 github.com/robfig/cron/v3 v3.0.1
github.com/shirou/gopsutil/v4 v4.26.5 github.com/shirou/gopsutil/v4 v4.26.5
github.com/sirupsen/logrus v1.9.4 github.com/sirupsen/logrus v1.9.4
@@ -46,12 +46,12 @@ require (
github.com/spf13/cobra v1.10.2 github.com/spf13/cobra v1.10.2
github.com/spf13/viper v1.21.0 github.com/spf13/viper v1.21.0
github.com/subosito/gotenv v1.6.0 github.com/subosito/gotenv v1.6.0
github.com/tencentyun/cos-go-sdk-v5 v0.7.73 github.com/tencentyun/cos-go-sdk-v5 v0.7.74
github.com/tomasen/fcgi_client v0.0.0-20180423082037-2bb3d819fd19 github.com/tomasen/fcgi_client v0.0.0-20180423082037-2bb3d819fd19
github.com/upyun/go-sdk v2.1.0+incompatible github.com/upyun/go-sdk v2.1.0+incompatible
go.mongodb.org/mongo-driver/v2 v2.6.0 go.mongodb.org/mongo-driver/v2 v2.7.0
golang.org/x/crypto v0.53.0 golang.org/x/crypto v0.53.0
golang.org/x/net v0.55.0 golang.org/x/net v0.56.0
golang.org/x/oauth2 v0.36.0 golang.org/x/oauth2 v0.36.0
golang.org/x/sync v0.21.0 golang.org/x/sync v0.21.0
golang.org/x/sys v0.46.0 golang.org/x/sys v0.46.0
@@ -60,7 +60,7 @@ require (
google.golang.org/genproto v0.0.0-20260414002931-afd174a4e478 google.golang.org/genproto v0.0.0-20260414002931-afd174a4e478
gopkg.in/ini.v1 v1.67.3 gopkg.in/ini.v1 v1.67.3
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
gorm.io/gorm v1.31.1 gorm.io/gorm v1.31.2
) )
require ( require (
+18 -16
View File
@@ -204,8 +204,8 @@ github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gE
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/compose-spec/compose-go/v2 v2.11.0 h1:xoq/ootgIL6TsHmbJHrkuh7+bzjhPV3NHftHRPPyVXM= github.com/compose-spec/compose-go/v2 v2.12.1 h1:+xBZNxcgSus4atQJwXPEdhHRgCEyZmj/BuqN5m33Ou0=
github.com/compose-spec/compose-go/v2 v2.11.0/go.mod h1:ZU6zlcweCZKyiB7BVfCizQT9XmkEIMFE+PRZydVcsZg= github.com/compose-spec/compose-go/v2 v2.12.1/go.mod h1:ZU6zlcweCZKyiB7BVfCizQT9XmkEIMFE+PRZydVcsZg=
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=
@@ -230,8 +230,8 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/dlclark/regexp2 v1.12.0 h1:0j4c5qQmnC6XOWNjP3PIXURXN2gWx76rd3KvgdPkCz8= github.com/dlclark/regexp2 v1.12.0 h1:0j4c5qQmnC6XOWNjP3PIXURXN2gWx76rd3KvgdPkCz8=
github.com/dlclark/regexp2 v1.12.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/dlclark/regexp2 v1.12.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/docker/cli v29.5.3+incompatible h1:nbEFfz774vBwQ5KRYv7c/AghjReqnGISvrRhzjV0evs= github.com/docker/cli v29.6.1+incompatible h1:oO7F4nn3Ovr/5TlfTUWFbMwBSS/B7Xs6Epv26gBrUP8=
github.com/docker/cli v29.5.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/cli v29.6.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/docker v28.5.2+incompatible h1:DBX0Y0zAjZbSrm1uzOkdr1onVghKaftjlSWt4AFexzM= github.com/docker/docker v28.5.2+incompatible h1:DBX0Y0zAjZbSrm1uzOkdr1onVghKaftjlSWt4AFexzM=
github.com/docker/docker v28.5.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v28.5.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.9.5 h1:EFNN8DHvaiK8zVqFA2DT6BjXE0GzfLOZ38ggPTKePkY= github.com/docker/docker-credential-helpers v0.9.5 h1:EFNN8DHvaiK8zVqFA2DT6BjXE0GzfLOZ38ggPTKePkY=
@@ -608,8 +608,8 @@ github.com/minio/highwayhash v1.0.1/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLT
github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY=
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
github.com/minio/minio-go/v7 v7.2.0 h1:RCJM0R1XOsRs+A3x3UCaf3ZYbByDaLjFeAi+YCQEPhs= github.com/minio/minio-go/v7 v7.2.1 h1:PfBfwvKB/MmqyN8Vb1G9voWisaM9OrLv+WwOvMwS9Dw=
github.com/minio/minio-go/v7 v7.2.0/go.mod h1:EU9hENAStx/xXduNdrGO5e4X5vk19NtgB+RIPjZO8o0= github.com/minio/minio-go/v7 v7.2.1/go.mod h1:EU9hENAStx/xXduNdrGO5e4X5vk19NtgB+RIPjZO8o0=
github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
@@ -746,8 +746,8 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/qiniu/go-sdk/v7 v7.26.12 h1:AnWiKjBY62XpULoB/MySKdNmlUo9S9pQB7/0s7QueCo= github.com/qiniu/go-sdk/v7 v7.26.13 h1:U4usDKoLldAqJntLN4wv4pkAjwvM9dueOUY/wbbO/yM=
github.com/qiniu/go-sdk/v7 v7.26.12/go.mod h1:ri7fGwbio0pRDFr8EK5TUpx0DbnpIMJ2bMSDxGWfCbk= github.com/qiniu/go-sdk/v7 v7.26.13/go.mod h1:ri7fGwbio0pRDFr8EK5TUpx0DbnpIMJ2bMSDxGWfCbk=
github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8= github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8=
github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII= github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII=
github.com/quic-go/quic-go v0.59.0 h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw= github.com/quic-go/quic-go v0.59.0 h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw=
@@ -833,8 +833,8 @@ github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.24/go.mod h
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.106 h1:YjsxDQwoiB+C0ISjnVk22Wbks02Ir+7Z5wmujcz69Vg= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.106 h1:YjsxDQwoiB+C0ISjnVk22Wbks02Ir+7Z5wmujcz69Vg=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.106/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.106/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/kms v1.0.563/go.mod h1:uom4Nvi9W+Qkom0exYiJ9VWJjXwyxtPYTkKkaLMlfE0= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/kms v1.0.563/go.mod h1:uom4Nvi9W+Qkom0exYiJ9VWJjXwyxtPYTkKkaLMlfE0=
github.com/tencentyun/cos-go-sdk-v5 v0.7.73 h1:uFfgp1A7cQaAGR6QP9DsIkoEQ67b8ewj5r1RV6XB540= github.com/tencentyun/cos-go-sdk-v5 v0.7.74 h1:YCsGhIK+Q5vMcmAiQqPuMyhSQ3zN1p7U+dhlHQD++6c=
github.com/tencentyun/cos-go-sdk-v5 v0.7.73/go.mod h1:STbTNaNKq03u+gscPEGOahKzLcGSYOj6Dzc5zNay7Pg= github.com/tencentyun/cos-go-sdk-v5 v0.7.74/go.mod h1:STbTNaNKq03u+gscPEGOahKzLcGSYOj6Dzc5zNay7Pg=
github.com/tencentyun/qcloud-cos-sts-sdk v0.0.0-20250515025012-e0eec8a5d123/go.mod h1:b18KQa4IxHbxeseW1GcZox53d7J0z39VNONTxvvlkXw= github.com/tencentyun/qcloud-cos-sts-sdk v0.0.0-20250515025012-e0eec8a5d123/go.mod h1:b18KQa4IxHbxeseW1GcZox53d7J0z39VNONTxvvlkXw=
github.com/therootcompany/xz v1.0.1 h1:CmOtsn1CbtmyYiusbfmhmkpAAETj0wBIH6kCYaX+xzw= github.com/therootcompany/xz v1.0.1 h1:CmOtsn1CbtmyYiusbfmhmkpAAETj0wBIH6kCYaX+xzw=
github.com/therootcompany/xz v1.0.1/go.mod h1:3K3UH1yCKgBneZYhuQUvJ9HPD19UEXEI0BWbMn8qNMY= github.com/therootcompany/xz v1.0.1/go.mod h1:3K3UH1yCKgBneZYhuQUvJ9HPD19UEXEI0BWbMn8qNMY=
@@ -898,8 +898,8 @@ go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lL
go.mongodb.org/mongo-driver v1.13.1/go.mod h1:wcDf1JBCXy2mOW0bWHwO/IOYqdca1MPCwDtFu/Z9+eo= go.mongodb.org/mongo-driver v1.13.1/go.mod h1:wcDf1JBCXy2mOW0bWHwO/IOYqdca1MPCwDtFu/Z9+eo=
go.mongodb.org/mongo-driver v1.17.9 h1:IexDdCuuNJ3BHrELgBlyaH9p60JXAvdzWR128q+U5tU= go.mongodb.org/mongo-driver v1.17.9 h1:IexDdCuuNJ3BHrELgBlyaH9p60JXAvdzWR128q+U5tU=
go.mongodb.org/mongo-driver v1.17.9/go.mod h1:LlOhpH5NUEfhxcAwG0UEkMqwYcc4JU18gtCdGudk/tQ= go.mongodb.org/mongo-driver v1.17.9/go.mod h1:LlOhpH5NUEfhxcAwG0UEkMqwYcc4JU18gtCdGudk/tQ=
go.mongodb.org/mongo-driver/v2 v2.6.0 h1:b9sJOYrkmt4l8bY43ZenFBcPlhYIjaOfYHLtbB/5qi8= go.mongodb.org/mongo-driver/v2 v2.7.0 h1:RO+zqavD2/GCL3cxOMyZhx6R9Irzr8/6gsoqx5tcY/c=
go.mongodb.org/mongo-driver/v2 v2.6.0/go.mod h1:yOI9kBsufol30iFsl1slpdq1I0eHPzybRWdyYUs8K/0= go.mongodb.org/mongo-driver/v2 v2.7.0/go.mod h1:yOI9kBsufol30iFsl1slpdq1I0eHPzybRWdyYUs8K/0=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
@@ -1073,8 +1073,8 @@ golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8= golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o=
golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww= golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -1409,8 +1409,10 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/gorm v1.31.1 h1:7CA8FTFz/gRfgqgpeKIBcervUn3xSyPUmr6B2WXJ7kg= gorm.io/driver/sqlite v1.6.0 h1:WHRRrIiulaPiPFmDcod6prc4l2VGVWHz80KspNsxSfQ=
gorm.io/gorm v1.31.1/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs= gorm.io/driver/sqlite v1.6.0/go.mod h1:AO9V1qIQddBESngQUKWL9yoH93HIeA1X6V633rBwyT8=
gorm.io/gorm v1.31.2 h1:3o8FXNo9v9S858gil+3LlZA1LkCOzgb4g5BL64FgaCo=
gorm.io/gorm v1.31.2/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs=
gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+1
View File
@@ -24,6 +24,7 @@ var langFiles = map[string]string{
"ko": "lang/ko.yaml", "ko": "lang/ko.yaml",
"tr": "lang/tr.yaml", "tr": "lang/tr.yaml",
"es-ES": "lang/es-ES.yaml", "es-ES": "lang/es-ES.yaml",
"fa": "lang/fa.yaml",
} }
func GetMsgWithMap(key string, maps map[string]interface{}) string { func GetMsgWithMap(key string, maps map[string]interface{}) string {
+49 -39
View File
@@ -1,32 +1,47 @@
# base errors
ErrInvalidParams: 'Bad request: {{ .detail }}' ErrInvalidParams: 'Bad request: {{ .detail }}'
ErrTokenParse: 'Token error: {{ .detail }}' ErrTokenParse: 'Token error: {{ .detail }}'
ErrInitialPassword: 'Original password is incorrect' ErrInitialPassword: 'Original password is incorrect'
ErrInternalServer: 'Internal server error: {{ .detail }}' ErrInternalServer: 'Internal server error: {{ .detail }}'
ErrRecordExist: 'Record already exists'
ErrRecordNotFound: 'Record not found'
ErrStructTransform: 'Type conversion failed: {{ .err }}'
ErrNotSupportType: 'Unsupported type: {{ .name }}'
# file AI
ErrFileAINotEnabled: 'File-management AI summary requires an enabled AI account in File Management. Content-only search still works when AI is off.' ErrFileAINotEnabled: 'File-management AI summary requires an enabled AI account in File Management. Content-only search still works when AI is off.'
ErrFileAISearchBadPattern: 'Invalid file search pattern (regex or whole word): {{ .detail }}' ErrFileAISearchBadPattern: 'Invalid file search pattern (regex or whole word): {{ .detail }}'
FileAISearchEmptyDir: 'No files or directories found under this path (or all entries were filtered).'
# remote download
ErrWgetRemoteFailed: 'Remote download failed or URL is unreachable: {{ .detail }}' ErrWgetRemoteFailed: 'Remote download failed or URL is unreachable: {{ .detail }}'
ErrWgetInvalidContentType: 'Remote URL did not return a file (possibly an error page), {{ .detail }}' ErrWgetInvalidContentType: 'Remote URL did not return a file (possibly an error page), {{ .detail }}'
ErrWgetProxyNotConfigured: 'Configure a proxy server in panel settings first' ErrWgetProxyNotConfigured: 'Configure a proxy server in panel settings first'
ErrWgetProxyInvalid: 'Invalid proxy server address: {{ .detail }}' ErrWgetProxyInvalid: 'Invalid proxy server address: {{ .detail }}'
ErrRecordExist: 'Record already exists'
ErrRecordNotFound: 'Record not found' # login and security
ErrStructTransform: 'Type conversion failed: {{ .err }}'
ErrNotLogin: 'Not logged in: {{ .detail }}' ErrNotLogin: 'Not logged in: {{ .detail }}'
ErrPasswordExpired: 'Password expired: {{ .detail }}' ErrPasswordExpired: 'Password expired: {{ .detail }}'
ErrNotSupportType: 'Unsupported type: {{ .name }}'
ErrAlertMethodNotSupported: 'This version does not support this alert method' # request and API
ErrProxy: 'Request failed: {{ .detail }}' ErrProxy: 'Request failed: {{ .detail }}'
ErrApiConfigStatusInvalid: 'API access disabled: {{ .detail }}' ErrApiConfigStatusInvalid: 'API access disabled: {{ .detail }}'
ErrApiConfigKeyInvalid: 'Invalid API key: {{ .detail }}' ErrApiConfigKeyInvalid: 'Invalid API key: {{ .detail }}'
ErrApiConfigIPInvalid: 'IP not in API allowlist: {{ .detail }}' ErrApiConfigIPInvalid: 'IP not in API allowlist: {{ .detail }}'
ErrApiConfigDisable: 'Endpoint not allowed via API: {{ .detail }}' ErrApiConfigDisable: 'Endpoint not allowed via API: {{ .detail }}'
ErrApiConfigKeyTimeInvalid: 'Invalid API timestamp: {{ .detail }}' ErrApiConfigKeyTimeInvalid: 'Invalid API timestamp: {{ .detail }}'
ErrShutDown: 'Command stopped manually' ErrCreateHttpClient: 'Failed to create HTTP request: {{ .err }}'
ErrHttpReqTimeOut: 'HTTP request timed out: {{ .err }}'
ErrHttpReqFailed: 'HTTP request failed: {{ .err }}'
ErrNoSuchHost: 'Host resolve failed: {{ .err }}'
ErrHttpReqNotFound: 'Requested resource not found: {{ .err }}'
# quick jump
ErrMinQuickJump: 'Set at least one quick jump entry' ErrMinQuickJump: 'Set at least one quick jump entry'
ErrMaxQuickJump: 'At most 4 quick jump entries' ErrMaxQuickJump: 'At most 4 quick jump entries'
#common # common
ErrShutDown: 'Command stopped manually'
ErrUsernameIsExist: 'Username already exists' ErrUsernameIsExist: 'Username already exists'
ErrNameIsExist: 'Name already exists' ErrNameIsExist: 'Name already exists'
ErrDemoEnvironment: 'Disabled in demo environment' ErrDemoEnvironment: 'Disabled in demo environment'
@@ -45,7 +60,7 @@ ErrGroupIsDefault: 'Default group, cannot be deleted'
ErrGroupIsInWebsiteUse: 'Group is in use by a website' ErrGroupIsInWebsiteUse: 'Group is in use by a website'
Decrypt: "Decrypt" Decrypt: "Decrypt"
#agent # agent
ErrAgentAccountBound: 'Account is bound to an agent and cannot be deleted' ErrAgentAccountBound: 'Account is bound to an agent and cannot be deleted'
ErrTerminalAIAccountInUse: 'This model account is currently used by Terminal AI. Switch the account in Terminal AI settings or disable Terminal AI and try again.' ErrTerminalAIAccountInUse: 'This model account is currently used by Terminal AI. Switch the account in Terminal AI settings or disable Terminal AI and try again.'
ErrAgentAccountUnavailable: 'Account connection unavailable: {{ .err }}' ErrAgentAccountUnavailable: 'Account connection unavailable: {{ .err }}'
@@ -71,7 +86,7 @@ ErrAgentWebsiteUnbindUnsupported: 'Deployment websites cannot be unbound manuall
ErrHermesPairingCodeUnavailable: 'The pairing code is temporarily unavailable in Hermes, possibly due to network issues. Please try again later.' ErrHermesPairingCodeUnavailable: 'The pairing code is temporarily unavailable in Hermes, possibly due to network issues. Please try again later.'
ErrHermesFeishuGroupAllowlistRequiresAllowlist: 'When the Feishu group policy is Allowlist, the DM policy cannot be Pairing Code.' ErrHermesFeishuGroupAllowlistRequiresAllowlist: 'When the Feishu group policy is Allowlist, the DM policy cannot be Pairing Code.'
#backup # backup and alert settings
Localhost: 'Local' Localhost: 'Local'
ErrBackupInUsed: 'Backup account is in use by a scheduled task' ErrBackupInUsed: 'Backup account is in use by a scheduled task'
ErrBackupCheck: 'Backup account connectivity test failed: {{ .err }}' ErrBackupCheck: 'Backup account connectivity test failed: {{ .err }}'
@@ -80,7 +95,7 @@ ErrBackupLocalCreate: 'Local backup accounts cannot be created'
ErrAlertConfigInUse: 'Alert configuration is in use and cannot be deleted' ErrAlertConfigInUse: 'Alert configuration is in use and cannot be deleted'
ErrAlertConfigPhoneExist: 'Phone number already exists' ErrAlertConfigPhoneExist: 'Phone number already exists'
#app # app
ErrPortInUsed: '{{ .detail }} port is already occupied!' ErrPortInUsed: '{{ .detail }} port is already occupied!'
ErrAppLimit: 'App install limit reached' ErrAppLimit: 'App install limit reached'
ErrNotInstall: 'Application not installed' ErrNotInstall: 'Application not installed'
@@ -98,16 +113,12 @@ ErrFileParseApp: 'Failed to parse {{ .name }}: {{ .err }}'
ErrAppDirNull: 'The version folder does not exist' ErrAppDirNull: 'The version folder does not exist'
LocalAppErr: 'Failed to sync app {{ .name }}: {{ .err }}' LocalAppErr: 'Failed to sync app {{ .name }}: {{ .err }}'
ErrContainerName: 'Container name already exists' ErrContainerName: 'Container name already exists'
ErrCreateHttpClient: 'Failed to create HTTP request: {{ .err }}'
ErrHttpReqTimeOut: 'HTTP request timed out: {{ .err }}'
ErrHttpReqFailed: 'HTTP request failed: {{ .err }}'
ErrNoSuchHost: 'Host resolve failed: {{ .err }}'
ErrHttpReqNotFound: 'Requested resource not found: {{ .err }}'
ErrContainerNotFound: '{{ .name }} container does not exist' ErrContainerNotFound: '{{ .name }} container does not exist'
ErrContainerMsg: 'Container {{ .name }} is abnormal; check logs' ErrContainerMsg: 'Container {{ .name }} is abnormal; check logs'
ErrAppBackup: 'App backup failed: {{ .name }} {{ .err }}' ErrAppBackup: 'App backup failed: {{ .name }} {{ .err }}'
ErrVersionTooLow: '1Panel version too low to update App Store' ErrVersionTooLow: '1Panel version too low to update App Store'
ErrAppNameExist: 'The application name already exists' ErrAppNameExist: 'The application name already exists'
ErrAppInstallNameExist: 'App install name {{ .name }} already exists'
AppStoreIsSyncing: 'App Store is syncing; try again later' AppStoreIsSyncing: 'App Store is syncing; try again later'
ErrGetCompose: 'Failed to read docker-compose.yml: {{ .detail }}' ErrGetCompose: 'Failed to read docker-compose.yml: {{ .detail }}'
ErrAppWarn: 'App status abnormal; check logs' ErrAppWarn: 'App status abnormal; check logs'
@@ -133,7 +144,7 @@ ErrDockerComposeCmdNotFound: 'Docker Compose not found on host'
UseExistImage: 'Image exists; using existing image' UseExistImage: 'Image exists; using existing image'
ErrDatabaseNotFound: 'Database not found: {{ .name }}' ErrDatabaseNotFound: 'Database not found: {{ .name }}'
#ssh # SSH
ExportIP: "Login IP" ExportIP: "Login IP"
ExportArea: "Location" ExportArea: "Location"
ExportPort: "Port" ExportPort: "Port"
@@ -142,7 +153,7 @@ ExportUser: "User"
ExportStatus: "Login Status" ExportStatus: "Login Status"
ExportDate: "Time" ExportDate: "Time"
#file # file
ErrFileCanNotRead: 'File preview is not supported' ErrFileCanNotRead: 'File preview is not supported'
ErrSensitiveFileRead: 'Reading sensitive files is not allowed' ErrSensitiveFileRead: 'Reading sensitive files is not allowed'
ErrFileToLarge: 'File is larger than 10 MB' ErrFileToLarge: 'File is larger than 10 MB'
@@ -170,7 +181,7 @@ FileDropSuccess: 'Cleaned {{ .name }}; files: {{ .count }}, freed: {{ .size }}'
FileDropSum: 'Cleanup done; files: {{ .count }}, freed: {{ .size }}' FileDropSum: 'Cleanup done; files: {{ .count }}, freed: {{ .size }}'
ErrBadDecrypt: 'Wrong archive password; extract failed' ErrBadDecrypt: 'Wrong archive password; extract failed'
#website # website
ErrAliasIsExist: 'Alias already exists' ErrAliasIsExist: 'Alias already exists'
ErrBackupMatch: 'Backup data mismatch: {{ .detail }}' ErrBackupMatch: 'Backup data mismatch: {{ .detail }}'
ErrBackupExist: 'Backup source data missing: {{ .detail }}' ErrBackupExist: 'Backup source data missing: {{ .detail }}'
@@ -201,7 +212,7 @@ ErrDefaultWebsite: 'Default website already set; unset it first'
SSL: 'Certificate' SSL: 'Certificate'
Set: 'Settings' Set: 'Settings'
#ssl # SSL certificate
ErrSSLCannotDelete: 'Certificate {{ .name }} is in use by a website' ErrSSLCannotDelete: 'Certificate {{ .name }} is in use by a website'
ErrAccountCannotDelete: 'Account is linked to a certificate and cannot be deleted' ErrAccountCannotDelete: 'Account is linked to a certificate and cannot be deleted'
ErrSSLApply: 'Certificate renewed; OpenResty reload failed' ErrSSLApply: 'Certificate renewed; OpenResty reload failed'
@@ -237,7 +248,7 @@ StartPushSSLToNode: 'Push certificate to node'
PushSSLToNodeFailed: "Failed to push certificate to node: {{ .err }}" PushSSLToNodeFailed: "Failed to push certificate to node: {{ .err }}"
PushSSLToNodeSuccess: 'Certificate pushed to node' PushSSLToNodeSuccess: 'Certificate pushed to node'
#mysql # MySQL
ErrUserIsExist: 'User already exists' ErrUserIsExist: 'User already exists'
ErrDatabaseIsExist: 'Database already exists' ErrDatabaseIsExist: 'Database already exists'
ErrExecTimeOut: 'SQL execution timed out' ErrExecTimeOut: 'SQL execution timed out'
@@ -247,10 +258,10 @@ RemoteBackup: 'Start local DB container with image {{ .name }} before backing up
RemoteRecover: 'Start local DB container with image {{ .name }} before restoring remote DB' RemoteRecover: 'Start local DB container with image {{ .name }} before restoring remote DB'
Arg: "Argument" Arg: "Argument"
#redis # Redis
ErrTypeOfRedis: 'Backup file type does not match current persistence mode' ErrTypeOfRedis: 'Backup file type does not match current persistence mode'
#container # container
ErrInUsed: "{{ .detail }} is in use and cannot be deleted!" ErrInUsed: "{{ .detail }} is in use and cannot be deleted!"
ErrObjectInUsed: "This object is in use and cannot be deleted!" ErrObjectInUsed: "This object is in use and cannot be deleted!"
ErrObjectBeDependent: "This image is referenced by other images and cannot be deleted!" ErrObjectBeDependent: "This image is referenced by other images and cannot be deleted!"
@@ -293,7 +304,7 @@ ComposeRecoverContainers: 'Restore compose containers'
ComposeRecoverRecord: 'Save compose record' ComposeRecoverRecord: 'Save compose record'
ComposeRecoverCleanup: 'Cleanup compose restore workspace' ComposeRecoverCleanup: 'Cleanup compose restore workspace'
#runtime # runtime
ErrFileNotExist: 'Source file not found: {{ .detail }}' ErrFileNotExist: 'Source file not found: {{ .detail }}'
ErrImageBuildErr: 'Image build failed' ErrImageBuildErr: 'Image build failed'
ErrImageExist: "Image already exists. Use a different image name." ErrImageExist: "Image already exists. Use a different image name."
@@ -307,7 +318,7 @@ ErrContainerNameIsNull: 'Container name is empty'
ErrPHPPortIsDefault: 'Port 9000 is reserved as default; use another port' ErrPHPPortIsDefault: 'Port 9000 is reserved as default; use another port'
ErrPHPRuntimePortFailed: 'Port {{ .name }} is already used by this runtime' ErrPHPRuntimePortFailed: 'Port {{ .name }} is already used by this runtime'
#tool # tool
ErrConfigNotFound: 'Configuration file does not exist' ErrConfigNotFound: 'Configuration file does not exist'
ErrConfigParse: 'Invalid configuration file format' ErrConfigParse: 'Invalid configuration file format'
ErrConfigIsNull: 'Configuration file cannot be empty' ErrConfigIsNull: 'Configuration file cannot be empty'
@@ -315,7 +326,7 @@ ErrConfigDirNotFound: 'Run directory not found'
ErrConfigAlreadyExist: 'Configuration file with the same name already exists' ErrConfigAlreadyExist: 'Configuration file with the same name already exists'
ErrUserFindErr: 'Failed to find user {{ .name }}: {{ .err }}' ErrUserFindErr: 'Failed to find user {{ .name }}: {{ .err }}'
#cronjob # cron job
CutWebsiteLogSuccess: 'Website log rotated: {{ .name }} (backup: {{ .path }})' CutWebsiteLogSuccess: 'Website log rotated: {{ .name }} (backup: {{ .path }})'
HandleShell: 'Run script {{ .name }}' HandleShell: 'Run script {{ .name }}'
HandleCurl: 'Request URL {{ .name }}' HandleCurl: 'Request URL {{ .name }}'
@@ -335,7 +346,7 @@ CleanLog: 'Clean logs'
CleanLogByName: 'Clean {{ .name }} logs' CleanLogByName: 'Clean {{ .name }} logs'
WafIpGroupNotFound: "WAF IP group not found. Go to [Advanced Features -> WAF -> Black/White List -> IP Group] and add one using Remote Download." WafIpGroupNotFound: "WAF IP group not found. Go to [Advanced Features -> WAF -> Black/White List -> IP Group] and add one using Remote Download."
#toolbox # toolbox
ErrNotExistUser: 'User does not exist' ErrNotExistUser: 'User does not exist'
ErrBanAction: 'Config failed: service {{ .name }} unavailable' ErrBanAction: 'Config failed: service {{ .name }} unavailable'
ErrClamdscanNotFound: 'clamdscan command not found' ErrClamdscanNotFound: 'clamdscan command not found'
@@ -345,14 +356,14 @@ CreateSwap: 'Create swap file'
FormatSwap: 'Format swap file' FormatSwap: 'Format swap file'
EnableSwap: 'Enable swap' EnableSwap: 'Enable swap'
#tamper # tamper protection
CleanTamperSetting: 'Clean historical protection settings' CleanTamperSetting: 'Clean historical protection settings'
SetTamperWithRules: 'Enable directory protection by rules' SetTamperWithRules: 'Enable directory protection by rules'
ProtectDir: "Protect directory {{ .name }}" ProtectDir: "Protect directory {{ .name }}"
IgnoreFile: "Protect file {{ .name }}" IgnoreFile: "Protect file {{ .name }}"
TamperSetSuccessful: 'Protection set. Monitoring these directories:' TamperSetSuccessful: 'Protection set. Monitoring these directories:'
#waf # WAF
ErrScope: 'This config cannot be changed' ErrScope: 'This config cannot be changed'
ErrStateChange: 'Failed to change state' ErrStateChange: 'Failed to change state'
ErrRuleExist: 'Rule already exists' ErrRuleExist: 'Rule already exists'
@@ -408,7 +419,7 @@ remoteIpIsNull: "IP list is empty"
OpenrestyVersionErr: 'OpenResty version too low; upgrade to 1.27.1.2-2-2-focal' OpenrestyVersionErr: 'OpenResty version too low; upgrade to 1.27.1.2-2-2-focal'
ErrFileTooLarge: 'File is larger than 1 MB and cannot be uploaded' ErrFileTooLarge: 'File is larger than 1 MB and cannot be uploaded'
#task # task
TaskStart: '{{ .name }} [START]' TaskStart: '{{ .name }} [START]'
TaskEnd: '{{ .name }} [DONE]' TaskEnd: '{{ .name }} [DONE]'
TaskFailed: '{{ .name }} task failed' TaskFailed: '{{ .name }} task failed'
@@ -470,16 +481,16 @@ TaskExec: 'Execute'
TaskBatch: "Batch Operation" TaskBatch: "Batch Operation"
FileConvert: 'File Conversion' FileConvert: 'File Conversion'
# task - clam # task - ClamAV
Clamscan: "Scan {{ .name }}" Clamscan: "Scan {{ .name }}"
TaskScan: "Scan" TaskScan: "Scan"
# task - ai # task - AI
OllamaModelPull: 'Pull Ollama model {{ .name }}' OllamaModelPull: 'Pull Ollama model {{ .name }}'
OllamaModelSize: 'Get Ollama model size: {{ .name }}' OllamaModelSize: 'Get Ollama model size: {{ .name }}'
AIBenchmarkRun: 'Run AI benchmark' AIBenchmarkRun: 'Run AI benchmark'
# task-snapshot # task - snapshot
Snapshot: 'Snapshot' Snapshot: 'Snapshot'
SnapDBInfo: 'Write 1Panel DB info' SnapDBInfo: 'Write 1Panel DB info'
SnapCopy: 'Copy files/directories {{ .name }}' SnapCopy: 'Copy files/directories {{ .name }}'
@@ -505,7 +516,6 @@ SnapCompressSize: 'Snapshot size {{ .name }}'
SnapUpload: 'Upload snapshot file' SnapUpload: 'Upload snapshot file'
SnapUploadTo: 'Upload snapshot to {{ .name }}' SnapUploadTo: 'Upload snapshot to {{ .name }}'
SnapUploadRes: 'Upload snapshot to {{ .name }}' SnapUploadRes: 'Upload snapshot to {{ .name }}'
SnapshotRecover: 'Recover snapshot' SnapshotRecover: 'Recover snapshot'
RecoverDownload: 'Download snapshot file' RecoverDownload: 'Download snapshot file'
Download: 'Download' Download: 'Download'
@@ -562,10 +572,11 @@ RecoverFailedStartRollBack: 'Recovery failed; starting rollback'
AppBackupFileIncomplete: 'Backup is incomplete: missing app.json or app.tar.gz' AppBackupFileIncomplete: 'Backup is incomplete: missing app.json or app.tar.gz'
AppAttributesNotMatch: 'Application type or name does not match' AppAttributesNotMatch: 'Application type or name does not match'
#alert # alert
ErrAlertMethodNotSupported: 'This version does not support this alert method'
ErrAlertSync: 'Failed to sync alert message' ErrAlertSync: 'Failed to sync alert message'
#task - runtime # task - runtime
ErrInstallExtension: 'Another extension install task is running' ErrInstallExtension: 'Another extension install task is running'
# alert mail template # alert mail template
@@ -586,7 +597,7 @@ NodeExceptionAlert: "Panel {{ .node }}{{ .ip }}: {{ .num }} nodes are abnormal.
LicenseExceptionAlert: "Panel {{ .node }}{{ .ip }}: {{ .num }} licenses are abnormal. Log in to view details." LicenseExceptionAlert: "Panel {{ .node }}{{ .ip }}: {{ .num }} licenses are abnormal. Log in to view details."
SSHAndPanelLoginAlert: "Panel {{ .node }}{{ .ip }}: abnormal {{ .name }} login from {{ .loginIp }}. Log in to view details." SSHAndPanelLoginAlert: "Panel {{ .node }}{{ .ip }}: abnormal {{ .name }} login from {{ .loginIp }}. Log in to view details."
#disk # disk
DeviceNotFound: "Device {{ .name }} not found" DeviceNotFound: "Device {{ .name }} not found"
DeviceIsMounted: 'Device {{ .name }} is mounted; unmount first' DeviceIsMounted: 'Device {{ .name }} is mounted; unmount first'
PartitionDiskErr: 'Partition failed: {{ .err }}' PartitionDiskErr: 'Partition failed: {{ .err }}'
@@ -599,9 +610,8 @@ TerminalAIBlockedRiskyCommand: 'blocked risky command: {{ .command }}'
TerminalAIThinking: 'AI is thinking...' TerminalAIThinking: 'AI is thinking...'
TerminalAIReadyToExecute: 'Thinking complete, press Enter to execute (duration: {{ .duration }}, tokens: {{ .tokens }})' TerminalAIReadyToExecute: 'Thinking complete, press Enter to execute (duration: {{ .duration }}, tokens: {{ .tokens }})'
TerminalAIRequestFailed: 'AI request failed: {{ .err }}' TerminalAIRequestFailed: 'AI request failed: {{ .err }}'
FileAISearchEmptyDir: 'No files or directories found under this path (or all entries were filtered).'
# ai proxy # AI gateway
ErrAIProxyServiceNotInstalled: '{{ .name }} service is not installed' ErrAIProxyServiceNotInstalled: '{{ .name }} service is not installed'
ErrAIProxyModelAccountNotFound: 'Model account {{ .id }} not found' ErrAIProxyModelAccountNotFound: 'Model account {{ .id }} not found'
ErrAIProxyModelMapRequired: 'This field is required.' ErrAIProxyModelMapRequired: 'This field is required.'
@@ -609,4 +619,4 @@ ErrAIProxyModelMapInvalid: 'Model mapping must be a valid JSON object: {{ .err }
ErrAIProxyModelMapEmpty: 'Model mapping cannot be empty' ErrAIProxyModelMapEmpty: 'Model mapping cannot be empty'
ErrAIProxyModelMapEmptyExternalModel: 'Model mapping contains an empty request model' ErrAIProxyModelMapEmptyExternalModel: 'Model mapping contains an empty request model'
ErrAIProxyModelMapEmptyUpstreamModel: 'Upstream model for {{ .model }} cannot be empty' ErrAIProxyModelMapEmptyUpstreamModel: 'Upstream model for {{ .model }} cannot be empty'
AIProxyUserFallback: 'User {{ .id }}' AIProxyUserFallback: 'Deleted user (ID: {{ .id }})'
+91 -20
View File
@@ -1,29 +1,47 @@
# errores básicos
ErrInvalidParams: 'Solicitud inválida: {{ .detail }}' ErrInvalidParams: 'Solicitud inválida: {{ .detail }}'
ErrTokenParse: 'Token inválido: {{ .detail }}' ErrTokenParse: 'Token inválido: {{ .detail }}'
ErrInitialPassword: 'Contraseña original incorrecta' ErrInitialPassword: 'Contraseña original incorrecta'
ErrInternalServer: 'Error interno: {{ .detail }}' ErrInternalServer: 'Error interno: {{ .detail }}'
ErrRecordExist: 'Registro ya existe'
ErrRecordNotFound: 'Registro no encontrado'
ErrStructTransform: 'Error de conversión: {{ .err }}'
ErrNotSupportType: 'Tipo no soportado: {{ .name }}'
# IA de archivos
ErrFileAINotEnabled: 'La búsqueda con IA de archivos está desactivada o sin cuenta. En Gestión de archivos, use Cuenta de IA, active y elija una cuenta.' ErrFileAINotEnabled: 'La búsqueda con IA de archivos está desactivada o sin cuenta. En Gestión de archivos, use Cuenta de IA, active y elija una cuenta.'
ErrFileAISearchBadPattern: 'Patrón de búsqueda no válido (regex u otra opción): {{ .detail }}' ErrFileAISearchBadPattern: 'Patrón de búsqueda no válido (regex u otra opción): {{ .detail }}'
FileAISearchEmptyDir: 'No hay archivos ni carpetas bajo esta ruta (o todos fueron filtrados).'
# descarga remota
ErrWgetRemoteFailed: 'La descarga remota falló o la URL no es accesible: {{ .detail }}' ErrWgetRemoteFailed: 'La descarga remota falló o la URL no es accesible: {{ .detail }}'
ErrWgetInvalidContentType: 'La URL remota no devolvió un archivo (posiblemente una página de error), {{ .detail }}' ErrWgetInvalidContentType: 'La URL remota no devolvió un archivo (posiblemente una página de error), {{ .detail }}'
ErrWgetProxyNotConfigured: 'Configure primero un servidor proxy en los ajustes del panel' ErrWgetProxyNotConfigured: 'Configure primero un servidor proxy en los ajustes del panel'
ErrWgetProxyInvalid: 'Dirección del servidor proxy no válida: {{ .detail }}' ErrWgetProxyInvalid: 'Dirección del servidor proxy no válida: {{ .detail }}'
ErrRecordExist: 'Registro ya existe'
ErrRecordNotFound: 'Registro no encontrado' # inicio de sesión y seguridad
ErrStructTransform: 'Error de conversión: {{ .err }}'
ErrNotLogin: 'No has iniciado sesión: {{ .detail }}' ErrNotLogin: 'No has iniciado sesión: {{ .detail }}'
ErrPasswordExpired: 'Contraseña expirada: {{ .detail }}' ErrPasswordExpired: 'Contraseña expirada: {{ .detail }}'
ErrNotSupportType: 'Tipo no soportado: {{ .name }}'
ErrAlertMethodNotSupported: 'Esta versión no admite este método de alerta' # solicitud y API
ErrProxy: 'Solicitud fallida: {{ .detail }}' ErrProxy: 'Solicitud fallida: {{ .detail }}'
ErrApiConfigStatusInvalid: 'API desactivada: {{ .detail }}' ErrApiConfigStatusInvalid: 'API desactivada: {{ .detail }}'
ErrApiConfigKeyInvalid: 'Clave API inválida: {{ .detail }}' ErrApiConfigKeyInvalid: 'Clave API inválida: {{ .detail }}'
ErrApiConfigIPInvalid: 'IP no permitida: {{ .detail }}' ErrApiConfigIPInvalid: 'IP no permitida: {{ .detail }}'
ErrApiConfigDisable: 'API no permitida: {{ .detail }}' ErrApiConfigDisable: 'API no permitida: {{ .detail }}'
ErrApiConfigKeyTimeInvalid: 'Timestamp inválido: {{ .detail }}' ErrApiConfigKeyTimeInvalid: 'Timestamp inválido: {{ .detail }}'
ErrShutDown: 'Comando detenido manualmente' ErrCreateHttpClient: 'Fallo al crear la solicitud {{ .err }}'
ErrHttpReqTimeOut: 'La solicitud superó el tiempo de espera {{ .err }}'
ErrHttpReqFailed: 'La solicitud falló {{ .err }}'
ErrNoSuchHost: 'No se pudo encontrar el servidor solicitado {{ .err }}'
ErrHttpReqNotFound: 'No se pudo encontrar el recurso solicitado {{ .err }}'
# salto rápido
ErrMinQuickJump: 'Agrega al menos una entrada rápida' ErrMinQuickJump: 'Agrega al menos una entrada rápida'
ErrMaxQuickJump: 'Máximo 4 entradas rápidas' ErrMaxQuickJump: 'Máximo 4 entradas rápidas'
# común
ErrShutDown: 'Comando detenido manualmente'
ErrUsernameIsExist: 'Usuario ya existe' ErrUsernameIsExist: 'Usuario ya existe'
ErrNameIsExist: 'Nombre ya existe' ErrNameIsExist: 'Nombre ya existe'
ErrDemoEnvironment: 'No disponible en demo' ErrDemoEnvironment: 'No disponible en demo'
@@ -41,6 +59,8 @@ SystemRestart: 'La tarea fue interrumpida debido a un reinicio del sistema'
ErrGroupIsDefault: 'Grupo predeterminado, no se puede eliminar' ErrGroupIsDefault: 'Grupo predeterminado, no se puede eliminar'
ErrGroupIsInWebsiteUse: 'El grupo está siendo usado por otro sitio web y no se puede eliminar.' ErrGroupIsInWebsiteUse: 'El grupo está siendo usado por otro sitio web y no se puede eliminar.'
Decrypt: 'Descifrar' Decrypt: 'Descifrar'
# agente
ErrAgentAccountBound: 'Cuenta vinculada a agente' ErrAgentAccountBound: 'Cuenta vinculada a agente'
ErrTerminalAIAccountInUse: 'Esta cuenta de modelo esta siendo usada por Terminal AI. Cambia la cuenta en la configuracion de Terminal AI o desactiva Terminal AI y vuelve a intentarlo.' ErrTerminalAIAccountInUse: 'Esta cuenta de modelo esta siendo usada por Terminal AI. Cambia la cuenta en la configuracion de Terminal AI o desactiva Terminal AI y vuelve a intentarlo.'
ErrAgentAccountUnavailable: 'Conexión de cuenta no disponible: {{ .err }}' ErrAgentAccountUnavailable: 'Conexión de cuenta no disponible: {{ .err }}'
@@ -65,14 +85,8 @@ ErrAgentWebsiteInUse: 'Este sitio web ya está vinculado a otro agente'
ErrAgentWebsiteUnbindUnsupported: 'Los sitios web de despliegue no se pueden desvincular manualmente' ErrAgentWebsiteUnbindUnsupported: 'Los sitios web de despliegue no se pueden desvincular manualmente'
ErrHermesPairingCodeUnavailable: 'El código de emparejamiento no está disponible temporalmente en Hermes, posiblemente por un problema de red. Inténtalo de nuevo más tarde.' ErrHermesPairingCodeUnavailable: 'El código de emparejamiento no está disponible temporalmente en Hermes, posiblemente por un problema de red. Inténtalo de nuevo más tarde.'
ErrHermesFeishuGroupAllowlistRequiresAllowlist: 'Cuando la política de grupo de Feishu es Lista permitida, la política de MD no puede ser Código de emparejamiento.' ErrHermesFeishuGroupAllowlistRequiresAllowlist: 'Cuando la política de grupo de Feishu es Lista permitida, la política de MD no puede ser Código de emparejamiento.'
ErrAIProxyServiceNotInstalled: 'El servicio {{ .name }} no está instalado'
ErrAIProxyModelAccountNotFound: 'Cuenta de modelo {{ .id }} no encontrada' # copia de seguridad y configuración de alertas
ErrAIProxyModelMapRequired: 'Este campo es obligatorio.'
ErrAIProxyModelMapInvalid: 'El mapeo de modelos debe ser un objeto JSON válido: {{ .err }}'
ErrAIProxyModelMapEmpty: 'El mapeo de modelos no puede estar vacío'
ErrAIProxyModelMapEmptyExternalModel: 'El mapeo de modelos contiene un modelo solicitado vacío'
ErrAIProxyModelMapEmptyUpstreamModel: 'El modelo upstream de {{ .model }} no puede estar vacío'
AIProxyUserFallback: 'Usuario {{ .id }}'
Localhost: 'Máquina local' Localhost: 'Máquina local'
ErrBackupInUsed: 'Cuenta de respaldo en uso por tarea programada' ErrBackupInUsed: 'Cuenta de respaldo en uso por tarea programada'
ErrBackupCheck: 'Conexión de respaldo falló: {{ .err }}' ErrBackupCheck: 'Conexión de respaldo falló: {{ .err }}'
@@ -80,6 +94,8 @@ ErrBackupLocalDelete: 'No se puede eliminar cuentas de respaldo locales'
ErrBackupLocalCreate: 'No se pueden crear cuentas de respaldo locales' ErrBackupLocalCreate: 'No se pueden crear cuentas de respaldo locales'
ErrAlertConfigInUse: 'La configuración de alertas está en uso y no se puede eliminar' ErrAlertConfigInUse: 'La configuración de alertas está en uso y no se puede eliminar'
ErrAlertConfigPhoneExist: 'El numero de telefono ya existe' ErrAlertConfigPhoneExist: 'El numero de telefono ya existe'
# aplicación
ErrPortInUsed: 'El puerto {{ .detail }} ya está ocupado' ErrPortInUsed: 'El puerto {{ .detail }} ya está ocupado'
ErrAppLimit: 'El número de aplicaciones instaladas ha superado el límite' ErrAppLimit: 'El número de aplicaciones instaladas ha superado el límite'
ErrNotInstall: 'Aplicación no instalada' ErrNotInstall: 'Aplicación no instalada'
@@ -97,16 +113,12 @@ ErrFileParseApp: 'El archivo {{ .name }} falló al analizarse {{ .err }}'
ErrAppDirNull: 'La carpeta de la versión no existe' ErrAppDirNull: 'La carpeta de la versión no existe'
LocalAppErr: 'La sincronización de la aplicación {{ .name }} falló {{ .err }}' LocalAppErr: 'La sincronización de la aplicación {{ .name }} falló {{ .err }}'
ErrContainerName: 'El nombre del contenedor ya existe' ErrContainerName: 'El nombre del contenedor ya existe'
ErrCreateHttpClient: 'Fallo al crear la solicitud {{ .err }}'
ErrHttpReqTimeOut: 'La solicitud superó el tiempo de espera {{ .err }}'
ErrHttpReqFailed: 'La solicitud falló {{ .err }}'
ErrNoSuchHost: 'No se pudo encontrar el servidor solicitado {{ .err }}'
ErrHttpReqNotFound: 'No se pudo encontrar el recurso solicitado {{ .err }}'
ErrContainerNotFound: 'El contenedor {{ .name }} no existe' ErrContainerNotFound: 'El contenedor {{ .name }} no existe'
ErrContainerMsg: 'El contenedor {{ .name }} presenta anomalías. Revise el log en la página de contenedores para más detalles' ErrContainerMsg: 'El contenedor {{ .name }} presenta anomalías. Revise el log en la página de contenedores para más detalles'
ErrAppBackup: 'Falló el respaldo de la aplicación {{ .name }} {{ .err }}' ErrAppBackup: 'Falló el respaldo de la aplicación {{ .name }} {{ .err }}'
ErrVersionTooLow: 'La versión actual de 1Panel es demasiado baja para actualizar la tienda de aplicaciones. Actualice primero.' ErrVersionTooLow: 'La versión actual de 1Panel es demasiado baja para actualizar la tienda de aplicaciones. Actualice primero.'
ErrAppNameExist: 'El nombre de la aplicación ya existe' ErrAppNameExist: 'El nombre de la aplicación ya existe'
ErrAppInstallNameExist: 'El nombre de instalación de la aplicación {{ .name }} ya existe'
AppStoreIsSyncing: 'La tienda de aplicaciones está sincronizando, inténtelo más tarde' AppStoreIsSyncing: 'La tienda de aplicaciones está sincronizando, inténtelo más tarde'
ErrGetCompose: 'Fallo al obtener el archivo docker-compose.yml {{ .detail }}' ErrGetCompose: 'Fallo al obtener el archivo docker-compose.yml {{ .detail }}'
ErrAppWarn: 'Estado anómalo, revise el log' ErrAppWarn: 'Estado anómalo, revise el log'
@@ -131,6 +143,8 @@ ErrDockerFailed: 'El estado de Docker es anómalo, revise el servicio'
ErrDockerComposeCmdNotFound: 'El comando Docker Compose no existe instálelo primero en el host' ErrDockerComposeCmdNotFound: 'El comando Docker Compose no existe instálelo primero en el host'
UseExistImage: 'La imagen ya existe, usando imagen existente' UseExistImage: 'La imagen ya existe, usando imagen existente'
ErrDatabaseNotFound: 'La base de datos {{ .name }} no existe' ErrDatabaseNotFound: 'La base de datos {{ .name }} no existe'
# SSH
ExportIP: 'IP de inicio de sesión' ExportIP: 'IP de inicio de sesión'
ExportArea: 'Ubicación' ExportArea: 'Ubicación'
ExportPort: 'Puerto' ExportPort: 'Puerto'
@@ -138,6 +152,8 @@ ExportAuthMode: 'Método de inicio de sesión'
ExportUser: 'Usuario' ExportUser: 'Usuario'
ExportStatus: 'Estado de inicio de sesión' ExportStatus: 'Estado de inicio de sesión'
ExportDate: 'Fecha y hora' ExportDate: 'Fecha y hora'
# archivo
ErrFileCanNotRead: 'Este archivo no soporta vista previa' ErrFileCanNotRead: 'Este archivo no soporta vista previa'
ErrSensitiveFileRead: 'No se permite leer archivos sensibles' ErrSensitiveFileRead: 'No se permite leer archivos sensibles'
ErrFileToLarge: 'El archivo es mayor a 10M y no puede abrirse' ErrFileToLarge: 'El archivo es mayor a 10M y no puede abrirse'
@@ -164,6 +180,8 @@ FileDropFailed: 'Error al limpiar el archivo {{ .name }}: {{ .err }}'
FileDropSuccess: 'Archivo {{ .name }} limpiado correctamente, {{ .count }} archivos eliminados, {{ .size }} de espacio liberado' FileDropSuccess: 'Archivo {{ .name }} limpiado correctamente, {{ .count }} archivos eliminados, {{ .size }} de espacio liberado'
FileDropSum: 'Limpieza de archivos completada, total {{ .count }} archivos eliminados, {{ .size }} de espacio liberado' FileDropSum: 'Limpieza de archivos completada, total {{ .count }} archivos eliminados, {{ .size }} de espacio liberado'
ErrBadDecrypt: 'Error de contraseña de descifrado del paquete comprimido, descompresión fallida, compruebe e inténtelo de nuevo' ErrBadDecrypt: 'Error de contraseña de descifrado del paquete comprimido, descompresión fallida, compruebe e inténtelo de nuevo'
# sitio web
ErrAliasIsExist: 'El alias ya existe' ErrAliasIsExist: 'El alias ya existe'
ErrBackupMatch: 'El archivo de respaldo no coincide con parte de los datos actuales del sitio web {{ .detail }}' ErrBackupMatch: 'El archivo de respaldo no coincide con parte de los datos actuales del sitio web {{ .detail }}'
ErrBackupExist: 'Parte de los datos fuente del respaldo no existe {{ .detail }}' ErrBackupExist: 'Parte de los datos fuente del respaldo no existe {{ .detail }}'
@@ -193,6 +211,8 @@ delete: 'Eliminar'
ErrDefaultWebsite: 'El sitio web predeterminado ya está configurado, cancélelo antes de configurar' ErrDefaultWebsite: 'El sitio web predeterminado ya está configurado, cancélelo antes de configurar'
SSL: 'Certificado' SSL: 'Certificado'
Set: 'Configuración' Set: 'Configuración'
# certificado SSL
ErrSSLCannotDelete: 'El certificado {{ .name }} está siendo utilizado por un sitio web y no puede eliminarse' ErrSSLCannotDelete: 'El certificado {{ .name }} está siendo utilizado por un sitio web y no puede eliminarse'
ErrAccountCannotDelete: 'La cuenta está asociada a un certificado y no puede eliminarse' ErrAccountCannotDelete: 'La cuenta está asociada a un certificado y no puede eliminarse'
ErrSSLApply: 'Renovación del certificado exitosa, recarga de openresty fallida, revise la configuración' ErrSSLApply: 'Renovación del certificado exitosa, recarga de openresty fallida, revise la configuración'
@@ -227,6 +247,8 @@ ErrApplySSLCanNotDelete: 'El certificado {{ .name }} en proceso de solicitud no
StartPushSSLToNode: 'Iniciando envío de certificado al nodo' StartPushSSLToNode: 'Iniciando envío de certificado al nodo'
PushSSLToNodeFailed: 'Error al enviar el certificado al nodo: {{ .err }}' PushSSLToNodeFailed: 'Error al enviar el certificado al nodo: {{ .err }}'
PushSSLToNodeSuccess: 'Certificado enviado correctamente al nodo' PushSSLToNodeSuccess: 'Certificado enviado correctamente al nodo'
# MySQL
ErrUserIsExist: 'El usuario actual ya existe, intente con otro' ErrUserIsExist: 'El usuario actual ya existe, intente con otro'
ErrDatabaseIsExist: 'La base de datos actual ya existe, intente con otro nombre' ErrDatabaseIsExist: 'La base de datos actual ya existe, intente con otro nombre'
ErrExecTimeOut: 'Tiempo de espera en la ejecución SQL, revise la base de datos' ErrExecTimeOut: 'Tiempo de espera en la ejecución SQL, revise la base de datos'
@@ -235,7 +257,11 @@ ErrLocalExist: 'El nombre ya existe en la base de datos local, modifíquelo e in
RemoteBackup: 'Para hacer una copia de seguridad de la base de datos remota, primero debe iniciarse el servicio de base de datos del contenedor local utilizando la imagen {{ .name }}, espere...' RemoteBackup: 'Para hacer una copia de seguridad de la base de datos remota, primero debe iniciarse el servicio de base de datos del contenedor local utilizando la imagen {{ .name }}, espere...'
RemoteRecover: 'Para restaurar la base de datos remota, primero debe iniciarse el servicio de base de datos del contenedor local utilizando la imagen {{ .name }}, espere...' RemoteRecover: 'Para restaurar la base de datos remota, primero debe iniciarse el servicio de base de datos del contenedor local utilizando la imagen {{ .name }}, espere...'
Arg: 'Argumento' Arg: 'Argumento'
# Redis
ErrTypeOfRedis: 'El tipo de archivo de recuperación no coincide con el método de persistencia actual, modifíquelo e intente' ErrTypeOfRedis: 'El tipo de archivo de recuperación no coincide con el método de persistencia actual, modifíquelo e intente'
# contenedor
ErrInUsed: '{{ .detail }} está en uso y no se puede eliminar' ErrInUsed: '{{ .detail }} está en uso y no se puede eliminar'
ErrObjectInUsed: 'Este objeto está en uso y no se puede eliminar' ErrObjectInUsed: 'Este objeto está en uso y no se puede eliminar'
ErrObjectBeDependent: 'Esta imagen es dependida por otras imágenes y no se puede eliminar' ErrObjectBeDependent: 'Esta imagen es dependida por otras imágenes y no se puede eliminar'
@@ -277,6 +303,8 @@ ComposeRecoverFiles: 'Restaurar archivos de compose'
ComposeRecoverContainers: 'Restaurar contenedores del compose' ComposeRecoverContainers: 'Restaurar contenedores del compose'
ComposeRecoverRecord: 'Guardar registro de compose' ComposeRecoverRecord: 'Guardar registro de compose'
ComposeRecoverCleanup: 'Limpiar espacio de restauracion de compose' ComposeRecoverCleanup: 'Limpiar espacio de restauracion de compose'
# entorno de ejecución
ErrFileNotExist: 'El archivo {{ .detail }} no existe, verifique la integridad' ErrFileNotExist: 'El archivo {{ .detail }} no existe, verifique la integridad'
ErrImageBuildErr: 'Fallo al construir la imagen' ErrImageBuildErr: 'Fallo al construir la imagen'
ErrImageExist: 'La imagen ya existe Modifique el nombre de la imagen.' ErrImageExist: 'La imagen ya existe Modifique el nombre de la imagen.'
@@ -289,12 +317,16 @@ ErrNodeModulesNotFound: 'La carpeta node_modules no existe, edite o espere a que
ErrContainerNameIsNull: 'El nombre del contenedor no existe' ErrContainerNameIsNull: 'El nombre del contenedor no existe'
ErrPHPPortIsDefault: 'El puerto 9000 es el predeterminado, modifique e intente de nuevo' ErrPHPPortIsDefault: 'El puerto 9000 es el predeterminado, modifique e intente de nuevo'
ErrPHPRuntimePortFailed: 'El puerto {{ .name }} ya está en uso por el entorno actual, modifique e intente' ErrPHPRuntimePortFailed: 'El puerto {{ .name }} ya está en uso por el entorno actual, modifique e intente'
# herramienta
ErrConfigNotFound: 'El archivo de configuración no existe' ErrConfigNotFound: 'El archivo de configuración no existe'
ErrConfigParse: 'El formato del archivo de configuración es incorrecto' ErrConfigParse: 'El formato del archivo de configuración es incorrecto'
ErrConfigIsNull: 'El archivo de configuración no puede estar vacío' ErrConfigIsNull: 'El archivo de configuración no puede estar vacío'
ErrConfigDirNotFound: 'El directorio de ejecución no existe' ErrConfigDirNotFound: 'El directorio de ejecución no existe'
ErrConfigAlreadyExist: 'Ya existe un archivo de configuración con ese nombre' ErrConfigAlreadyExist: 'Ya existe un archivo de configuración con ese nombre'
ErrUserFindErr: 'Búsqueda del usuario {{ .name }} fallida {{ .err }}' ErrUserFindErr: 'Búsqueda del usuario {{ .name }} fallida {{ .err }}'
# tarea programada
CutWebsiteLogSuccess: 'Log del sitio web {{ .name }} cortado con éxito, ruta de respaldo {{ .path }}' CutWebsiteLogSuccess: 'Log del sitio web {{ .name }} cortado con éxito, ruta de respaldo {{ .path }}'
HandleShell: 'Ejecutar script {{ .name }}' HandleShell: 'Ejecutar script {{ .name }}'
HandleCurl: 'URL {{ .name }} にアクセス' HandleCurl: 'URL {{ .name }} にアクセス'
@@ -313,6 +345,8 @@ NoSuchResource: 'No se encontraron contenidos de respaldo en la base de datos, o
CleanLog: 'Limpiar registro' CleanLog: 'Limpiar registro'
CleanLogByName: 'Limpiar registro de {{ .name }}' CleanLogByName: 'Limpiar registro de {{ .name }}'
WafIpGroupNotFound: 'Grupo de IP de WAF no encontrado., vaya a [Funciones Avanzadas - WAF - Lista Blanca/Negra - Grupo de IP] para agregar un grupo de IP mediante el método de descarga remota.' WafIpGroupNotFound: 'Grupo de IP de WAF no encontrado., vaya a [Funciones Avanzadas - WAF - Lista Blanca/Negra - Grupo de IP] para agregar un grupo de IP mediante el método de descarga remota.'
# caja de herramientas
ErrNotExistUser: 'El usuario actual no existe, modifíquelo e intente de nuevo' ErrNotExistUser: 'El usuario actual no existe, modifíquelo e intente de nuevo'
ErrBanAction: 'Fallo al configurar. El servicio {{ .name }} no está disponible, revise e intente de nuevo' ErrBanAction: 'Fallo al configurar. El servicio {{ .name }} no está disponible, revise e intente de nuevo'
ErrClamdscanNotFound: 'El comando clamdscan no fue detectado, siga la documentación para instalarlo' ErrClamdscanNotFound: 'El comando clamdscan no fue detectado, siga la documentación para instalarlo'
@@ -321,11 +355,15 @@ SetSwap: 'Configurar Swap {{ .path }} - {{ .size }}'
CreateSwap: 'Crear Archivo Swap' CreateSwap: 'Crear Archivo Swap'
FormatSwap: 'Formatear Archivo Swap' FormatSwap: 'Formatear Archivo Swap'
EnableSwap: 'Habilitar Swap' EnableSwap: 'Habilitar Swap'
# protección contra manipulación
CleanTamperSetting: 'Limpiar configuraciones de protección históricas' CleanTamperSetting: 'Limpiar configuraciones de protección históricas'
SetTamperWithRules: 'Iniciar protección de directorio según reglas' SetTamperWithRules: 'Iniciar protección de directorio según reglas'
ProtectDir: 'Proteger directorio {{ .name }}' ProtectDir: 'Proteger directorio {{ .name }}'
IgnoreFile: 'Proteger archivo {{ .name }}' IgnoreFile: 'Proteger archivo {{ .name }}'
TamperSetSuccessful: 'Configuración de protección completada, comenzando monitoreo de los siguientes directorios:' TamperSetSuccessful: 'Configuración de protección completada, comenzando monitoreo de los siguientes directorios:'
# WAF
ErrScope: 'No se admite la modificación de esta configuración' ErrScope: 'No se admite la modificación de esta configuración'
ErrStateChange: 'Fallo al cambiar de estado' ErrStateChange: 'Fallo al cambiar de estado'
ErrRuleExist: 'La regla ya existe' ErrRuleExist: 'La regla ya existe'
@@ -380,6 +418,8 @@ OpenrestyNotFound: 'OpenResty no está instalado'
remoteIpIsNull: 'La lista de IP está vacía' remoteIpIsNull: 'La lista de IP está vacía'
OpenrestyVersionErr: 'La versión de OpenResty es demasiado antigua. Actualízalo a 1.27.1.2-2-2-focal' OpenrestyVersionErr: 'La versión de OpenResty es demasiado antigua. Actualízalo a 1.27.1.2-2-2-focal'
ErrFileTooLarge: 'El archivo supera 1 MB y no se puede cargar' ErrFileTooLarge: 'El archivo supera 1 MB y no se puede cargar'
# tarea
TaskStart: 'La tarea {{ .name }} inicia [INICIO]' TaskStart: 'La tarea {{ .name }} inicia [INICIO]'
TaskEnd: 'La tarea {{ .name }} completada [COMPLETADA]' TaskEnd: 'La tarea {{ .name }} completada [COMPLETADA]'
TaskFailed: 'La tarea {{ .name }} falló' TaskFailed: 'La tarea {{ .name }} falló'
@@ -440,10 +480,17 @@ CustomAppstore: 'Almacén de aplicaciones personalizado'
TaskExec: 'Ejecutar' TaskExec: 'Ejecutar'
TaskBatch: 'Operación por Lotes' TaskBatch: 'Operación por Lotes'
FileConvert: 'Conversión de Formato de Archivo' FileConvert: 'Conversión de Formato de Archivo'
# tarea - ClamAV
Clamscan: 'Escanear {{ .name }}' Clamscan: 'Escanear {{ .name }}'
TaskScan: 'Escaneo' TaskScan: 'Escaneo'
# tarea - IA
OllamaModelPull: 'Descargar modelo Ollama {{ .name }}' OllamaModelPull: 'Descargar modelo Ollama {{ .name }}'
OllamaModelSize: 'Obtener tamaño del modelo Ollama {{ .name }}' OllamaModelSize: 'Obtener tamaño del modelo Ollama {{ .name }}'
AIBenchmarkRun: "Ejecutar prueba de referencia de IA"
# tarea - instantánea
Snapshot: 'Instantánea' Snapshot: 'Instantánea'
SnapDBInfo: 'Escribir información de base de datos de 1Panel' SnapDBInfo: 'Escribir información de base de datos de 1Panel'
SnapCopy: 'Copiar archivos y directorios {{ .name }}' SnapCopy: 'Copiar archivos y directorios {{ .name }}'
@@ -493,6 +540,8 @@ RecoverDaemonJson: 'Restaurar archivo daemon.json de configuración de contenedo
RecoverDBData: 'Restaurar datos de base de datos' RecoverDBData: 'Restaurar datos de base de datos'
RecoverBackups: 'Restaurar directorio local de respaldo' RecoverBackups: 'Restaurar directorio local de respaldo'
RecoverPanelData: 'Recuperar directorio de datos' RecoverPanelData: 'Recuperar directorio de datos'
# tarea - contenedor
ContainerImagePull: 'Descargar imagen de contenedor {{ .name }}' ContainerImagePull: 'Descargar imagen de contenedor {{ .name }}'
ContainerRemoveOld: 'Eliminar el contenedor original {{ .name }}' ContainerRemoveOld: 'Eliminar el contenedor original {{ .name }}'
ContainerImageCheck: 'Comprobar si la imagen se descargó correctamente' ContainerImageCheck: 'Comprobar si la imagen se descargó correctamente'
@@ -501,6 +550,8 @@ ContainerRecreate: 'Actualización del contenedor fallida, restaurando el conten
ContainerCreate: 'Crear nuevo contenedor {{ .name }}' ContainerCreate: 'Crear nuevo contenedor {{ .name }}'
ContainerCreateFailed: 'Falló la creación del contenedor, eliminando el contenedor fallido' ContainerCreateFailed: 'Falló la creación del contenedor, eliminando el contenedor fallido'
ContainerStartCheck: 'Verificar si el contenedor ha iniciado' ContainerStartCheck: 'Verificar si el contenedor ha iniciado'
# tarea - imagen
ImageBuild: 'Construcción de imagen' ImageBuild: 'Construcción de imagen'
ImagePull: 'Descargar imagen' ImagePull: 'Descargar imagen'
ImageRepoAuthFromDB: 'Obtener información de autenticación del repositorio desde la base de datos' ImageRepoAuthFromDB: 'Obtener información de autenticación del repositorio desde la base de datos'
@@ -508,6 +559,8 @@ ImagePush: 'Subir imagen'
ImageRenameTag: 'Modificar etiqueta de imagen' ImageRenameTag: 'Modificar etiqueta de imagen'
ImageNewTag: 'Nueva etiqueta de imagen {{ .name }}' ImageNewTag: 'Nueva etiqueta de imagen {{ .name }}'
ComposeCreate: 'Crear orquestación' ComposeCreate: 'Crear orquestación'
# tarea - sitio web
BackupNginxConfig: 'Respaldar archivo de configuración OpenResty' BackupNginxConfig: 'Respaldar archivo de configuración OpenResty'
CompressFileSuccess: 'Directorio comprimido con éxito, guardado en {{ .name }}' CompressFileSuccess: 'Directorio comprimido con éxito, guardado en {{ .name }}'
CompressDir: 'Directorio comprimido' CompressDir: 'Directorio comprimido'
@@ -518,8 +571,15 @@ websiteDir: 'Directorio del sitio web'
RecoverFailedStartRollBack: 'Restauración fallida, iniciando reversión' RecoverFailedStartRollBack: 'Restauración fallida, iniciando reversión'
AppBackupFileIncomplete: 'El archivo de respaldo está incompleto, falta app.json o app.tar.gz' AppBackupFileIncomplete: 'El archivo de respaldo está incompleto, falta app.json o app.tar.gz'
AppAttributesNotMatch: 'El tipo o nombre de la aplicación no coincide' AppAttributesNotMatch: 'El tipo o nombre de la aplicación no coincide'
# alerta
ErrAlertMethodNotSupported: 'Esta versión no admite este método de alerta'
ErrAlertSync: 'Error en la sincronización de la alerta, revise e intente de nuevo' ErrAlertSync: 'Error en la sincronización de la alerta, revise e intente de nuevo'
# tarea - entorno de ejecución
ErrInstallExtension: 'Ya hay una tarea de instalación en curso, espere a que termine' ErrInstallExtension: 'Ya hay una tarea de instalación en curso, espere a que termine'
# plantilla de correo de alerta
PanelAlertTitle: 'Notificación de alerta del panel' PanelAlertTitle: 'Notificación de alerta del panel'
TestAlertTitle: 'Correo de prueba - Verificar conectividad de correo' TestAlertTitle: 'Correo de prueba - Verificar conectividad de correo'
TestAlert: 'Este es un correo de prueba para verificar que la configuración de envío de correos es correcta.' TestAlert: 'Este es un correo de prueba para verificar que la configuración de envío de correos es correcta.'
@@ -536,6 +596,8 @@ CommonAlert: 'Su Panel {{ .node }}{{ .ip }}, {{ .msg }}. Inicie sesión en el pa
NodeExceptionAlert: 'Su Panel {{ .node }}{{ .ip }}, {{ .num }} nodos son anómalos. Inicie sesión en el panel para ver los detalles.' NodeExceptionAlert: 'Su Panel {{ .node }}{{ .ip }}, {{ .num }} nodos son anómalos. Inicie sesión en el panel para ver los detalles.'
LicenseExceptionAlert: 'Su Panel {{ .node }}{{ .ip }}, {{ .num }} licencias son anómalas. Inicie sesión en el panel para ver los detalles.' LicenseExceptionAlert: 'Su Panel {{ .node }}{{ .ip }}, {{ .num }} licencias son anómalas. Inicie sesión en el panel para ver los detalles.'
SSHAndPanelLoginAlert: 'Su Panel {{ .node }}{{ .ip }}, el inicio de sesión {{ .name }} desde {{ .loginIp }} es anómalo. Inicie sesión en el panel para ver los detalles.' SSHAndPanelLoginAlert: 'Su Panel {{ .node }}{{ .ip }}, el inicio de sesión {{ .name }} desde {{ .loginIp }} es anómalo. Inicie sesión en el panel para ver los detalles.'
# disco
DeviceNotFound: 'Dispositivo {{ .name }} no encontrado' DeviceNotFound: 'Dispositivo {{ .name }} no encontrado'
DeviceIsMounted: 'El dispositivo {{ .name }} está montado, desmóntelo primero' DeviceIsMounted: 'El dispositivo {{ .name }} está montado, desmóntelo primero'
PartitionDiskErr: 'Error al particionar, {{ .err }}' PartitionDiskErr: 'Error al particionar, {{ .err }}'
@@ -548,4 +610,13 @@ TerminalAIBlockedRiskyCommand: 'Comando de riesgo bloqueado: {{ .command }}'
TerminalAIThinking: 'La IA está pensando...' TerminalAIThinking: 'La IA está pensando...'
TerminalAIReadyToExecute: 'Pensamiento completado, pulsa Enter para ejecutar (duración: {{ .duration }}, token: {{ .tokens }})' TerminalAIReadyToExecute: 'Pensamiento completado, pulsa Enter para ejecutar (duración: {{ .duration }}, token: {{ .tokens }})'
TerminalAIRequestFailed: 'La solicitud de AI ha fallado: {{ .err }}' TerminalAIRequestFailed: 'La solicitud de AI ha fallado: {{ .err }}'
FileAISearchEmptyDir: 'No hay archivos ni carpetas bajo esta ruta (o todos fueron filtrados).'
# puerta de enlace de IA
ErrAIProxyServiceNotInstalled: 'El servicio {{ .name }} no está instalado'
ErrAIProxyModelAccountNotFound: 'Cuenta de modelo {{ .id }} no encontrada'
ErrAIProxyModelMapRequired: 'Este campo es obligatorio.'
ErrAIProxyModelMapInvalid: 'El mapeo de modelos debe ser un objeto JSON válido: {{ .err }}'
ErrAIProxyModelMapEmpty: 'El mapeo de modelos no puede estar vacío'
ErrAIProxyModelMapEmptyExternalModel: 'El mapeo de modelos contiene un modelo solicitado vacío'
ErrAIProxyModelMapEmptyUpstreamModel: 'El modelo upstream de {{ .model }} no puede estar vacío'
AIProxyUserFallback: 'Usuario eliminado (ID: {{ .id }})'
+622
View File
@@ -0,0 +1,622 @@
# خطاهای پایه
ErrInvalidParams: 'درخواست نامعتبر: {{ .detail }}'
ErrTokenParse: 'خطا در توکن: {{ .detail }}'
ErrInitialPassword: 'رمز عبور اصلی اشتباه است'
ErrInternalServer: 'خطای داخلی سرور: {{ .detail }}'
ErrRecordExist: 'رکورد از قبل وجود دارد'
ErrRecordNotFound: 'رکورد یافت نشد'
ErrStructTransform: 'تبدیل نوع ناموفق بود: {{ .err }}'
ErrNotSupportType: 'نوع پشتیبانی نمی‌شود: {{ .name }}'
# هوش مصنوعی فایل
ErrFileAINotEnabled: 'خلاصه‌سازی هوش مصنوعی مدیریت فایل نیاز به فعال بودن حساب هوش مصنوعی در مدیریت فایل دارد. جستجوی صرفاً محتوایی زمانی که هوش مصنوعی خاموش است همچنان کار می‌کند.'
ErrFileAISearchBadPattern: 'الگوی جستجوی فایل نامعتبر است (عبارت منظم یا کل کلمه): {{ .detail }}'
FileAISearchEmptyDir: 'هیچ فایل یا دایرکتوری در این مسیر یافت نشد (یا همه ورودی‌ها فیلتر شدند).'
# دانلود از راه دور
ErrWgetRemoteFailed: 'دانلود از راه دور ناموفق بود یا URL قابل دسترس نیست: {{ .detail }}'
ErrWgetInvalidContentType: 'URL از راه دور فایلی را برنگرداند (احتمالاً صفحه خطا)، {{ .detail }}'
ErrWgetProxyNotConfigured: 'ابتدا یک سرور پروکسی در تنظیمات پنل پیکربندی کنید'
ErrWgetProxyInvalid: 'آدرس سرور پروکسی نامعتبر است: {{ .detail }}'
# ورود و امنیت
ErrNotLogin: 'وارد نشده‌اید: {{ .detail }}'
ErrPasswordExpired: 'رمز عبور منقضی شده است: {{ .detail }}'
# درخواست و API
ErrProxy: 'درخواست ناموفق بود: {{ .detail }}'
ErrApiConfigStatusInvalid: 'دسترسی API غیرفعال است: {{ .detail }}'
ErrApiConfigKeyInvalid: 'کلید API نامعتبر است: {{ .detail }}'
ErrApiConfigIPInvalid: 'IP در لیست سفید API نیست: {{ .detail }}'
ErrApiConfigDisable: 'نقطه پایانی از طریق API مجاز نیست: {{ .detail }}'
ErrApiConfigKeyTimeInvalid: 'مهر زمانی API نامعتبر است: {{ .detail }}'
ErrCreateHttpClient: 'ایجاد درخواست HTTP ناموفق بود: {{ .err }}'
ErrHttpReqTimeOut: 'زمان درخواست HTTP به پایان رسید: {{ .err }}'
ErrHttpReqFailed: 'درخواست HTTP ناموفق بود: {{ .err }}'
ErrNoSuchHost: 'تفکیک میزبان ناموفق بود: {{ .err }}'
ErrHttpReqNotFound: 'منبع درخواستی یافت نشد: {{ .err }}'
# پرش سریع
ErrMinQuickJump: 'حداقل یک ورودی پرش سریع تنظیم کنید'
ErrMaxQuickJump: 'حداکثر ۴ ورودی پرش سریع'
# عمومی
ErrShutDown: 'دستور به صورت دستی متوقف شد'
ErrUsernameIsExist: 'نام کاربری از قبل وجود دارد'
ErrNameIsExist: 'نام از قبل وجود دارد'
ErrDemoEnvironment: 'در محیط آزمایشی غیرفعال است'
ErrCmdTimeout: 'زمان اجرای دستور به پایان رسید'
ErrCmdIllegal: 'دستور شامل کاراکترهای غیرمجاز است'
ErrPortExist: 'پورت {{ .port }} قبلاً توسط {{ .type }} [{{ .name }}] اشغال شده است'
TYPE_APP: 'برنامه'
TYPE_RUNTIME: 'محیط اجرا'
TYPE_DOMAIN: 'دامنه'
ErrTypePort: 'فرمت پورت نامعتبر است: {{ .name }}'
ErrTypePortRange: 'محدوده پورت باید ۱-۶۵۵۳۵ باشد'
Success: 'موفق'
Failed: 'ناموفق'
SystemRestart: 'وظیفه به دلیل راه‌اندازی مجدد سیستم قطع شد'
ErrGroupIsDefault: 'گروه پیش‌فرض، قابل حذف نیست'
ErrGroupIsInWebsiteUse: 'گروه توسط یک وب‌سایت در حال استفاده است'
Decrypt: "رمزگشایی"
# عامل
ErrAgentAccountBound: 'حساب به یک عامل متصل است و قابل حذف نیست'
ErrTerminalAIAccountInUse: 'این حساب مدل در حال حاضر توسط ترمینال هوش مصنوعی استفاده می‌شود. حساب را در تنظیمات ترمینال هوش مصنوعی تغییر دهید یا ترمینال هوش مصنوعی را غیرفعال کرده و دوباره تلاش کنید.'
ErrAgentAccountUnavailable: 'اتصال حساب در دسترس نیست: {{ .err }}'
ErrAgentProviderNotSupported: 'ارائه‌دهنده عامل پشتیبانی نمی‌شود'
ErrAgentAccountRequired: 'ابتدا یک حساب عامل انتخاب کنید'
ErrAgentAccountNotVerified: 'حساب عامل تأیید نشده است'
ErrAgentAccountModelsRequired: 'لطفاً حداقل یک مدل پیکربندی کنید'
ErrAgentAccountSingleInitialModel: 'فقط یک مدل اولیه می‌تواند در هنگام ایجاد حساب پیکربندی شود'
ErrAgentModelNotInAccount: 'مدل در حساب انتخاب شده پیکربندی نشده است'
ErrAgentFallbackModelDuplicate: 'مدل‌های جایگزین نمی‌توانند تکراری باشند'
ErrAgentFallbackModelPrimary: 'مدل جایگزین نمی‌تواند با مدل اصلی یکی باشد'
ErrAgentModelInUse: 'یک عامل متصل هنوز از این مدل استفاده می‌کند: {{ .name }}'
ErrAgentBaseURLRequired: 'آدرس پایه الزامی است'
ErrAgentApiKeyRequired: 'کلید API الزامی است'
ErrAgentComposeRequired: 'محتوای Compose الزامی است'
ErrAgentIDRequired: 'شناسه عامل الزامی است'
ErrAgentAccountIDRequired: 'شناسه حساب الزامی است'
ErrAgentLimitReached: 'نسخه انجمن تا {{ .max }} عامل هوش مصنوعی را پشتیبانی می‌کند. برای عامل‌های نامحدود به نسخه تجاری ارتقاء دهید'
ErrAgentWebsiteBound: 'این عامل قبلاً به یک وب‌سایت متصل است'
ErrAgentWebsiteTypeUnsupported: 'فقط وب‌سایت‌های پراکسی یا استاتیک قابل اتصال هستند'
ErrAgentWebsiteInUse: 'این وب‌سایت قبلاً به عامل دیگری متصل است'
ErrAgentWebsiteUnbindUnsupported: 'وب‌سایت‌های استقرار یافته را نمی‌توان به صورت دستی قطع اتصال کرد'
ErrHermesPairingCodeUnavailable: 'کد جفت‌سازی به طور موقت در هرمس در دسترس نیست، احتمالاً به دلیل مشکلات شبکه. لطفاً بعداً دوباره تلاش کنید.'
ErrHermesFeishuGroupAllowlistRequiresAllowlist: 'وقتی خط مشی گروه فیشو لیست سفید باشد، خط مشی DM نمی‌تواند کد جفت‌سازی باشد.'
# پشتیبان‌گیری و تنظیمات هشدار
Localhost: 'محلی'
ErrBackupInUsed: 'حساب پشتیبان توسط یک وظیفه زمان‌بندی در حال استفاده است'
ErrBackupCheck: 'تست اتصال حساب پشتیبان ناموفق بود: {{ .err }}'
ErrBackupLocalDelete: 'حساب‌های پشتیبان محلی قابل حذف نیستند'
ErrBackupLocalCreate: 'حساب‌های پشتیبان محلی قابل ایجاد نیستند'
ErrAlertConfigInUse: 'پیکربندی هشدار در حال استفاده است و قابل حذف نیست'
ErrAlertConfigPhoneExist: 'شماره تلفن از قبل وجود دارد'
# برنامه
ErrPortInUsed: 'پورت {{ .detail }} قبلاً اشغال شده است!'
ErrAppLimit: 'محدودیت نصب برنامه رسیده است'
ErrNotInstall: 'برنامه نصب نشده است'
ErrPortInOtherApp: 'پورت {{ .port }} قبلاً توسط برنامه {{ .apps }} اشغال شده است!'
ErrDbUserNotValid: 'نام کاربری/رمز عبور پایگاه داده مطابقت ندارد'
ErrUpdateBuWebsite: 'برنامه به‌روزرسانی شد، اما به‌روزرسانی پیکربندی وب‌سایت ناموفق بود'
Err1PanelNetworkFailed: 'ایجاد شبکه پیش‌فرض کانتینر ناموفق بود! {{ .detail }}'
ErrFileParse: 'تجزیه فایل docker-compose برنامه ناموفق بود'
ErrInstallDirNotFound: 'دایرکتوری نصب یافت نشد؛ از حذف اجباری استفاده کنید'
AppStoreIsUpToDate: 'فروشگاه برنامه از قبل آخرین نسخه است'
LocalAppVersionNull: 'برنامه {{ .name }} هیچ نسخه همگام‌سازی شده‌ای ندارد'
LocalAppVersionErr: 'همگام‌سازی نسخه {{ .version }} برنامه {{ .name }} ناموفق بود: {{ .err }}'
ErrFileNotFound: 'فایل {{ .name }} وجود ندارد'
ErrFileParseApp: 'تجزیه {{ .name }} ناموفق بود: {{ .err }}'
ErrAppDirNull: 'پوشه نسخه وجود ندارد'
LocalAppErr: 'همگام‌سازی برنامه {{ .name }} ناموفق بود: {{ .err }}'
ErrContainerName: 'نام کانتینر از قبل وجود دارد'
ErrContainerNotFound: 'کانتینر {{ .name }} وجود ندارد'
ErrContainerMsg: 'کانتینر {{ .name }} غیرعادی است؛ لاگ‌ها را بررسی کنید'
ErrAppBackup: 'پشتیبان‌گیری از برنامه ناموفق بود: {{ .name }} {{ .err }}'
ErrVersionTooLow: 'نسخه 1Panel برای به‌روزرسانی فروشگاه برنامه بسیار پایین است'
ErrAppNameExist: 'نام برنامه از قبل وجود دارد'
ErrAppInstallNameExist: 'نام نصب برنامه {{ .name }} از قبل وجود دارد'
AppStoreIsSyncing: 'فروشگاه برنامه در حال همگام‌سازی است؛ بعداً دوباره تلاش کنید'
ErrGetCompose: 'خواندن docker-compose.yml ناموفق بود: {{ .detail }}'
ErrAppWarn: 'وضعیت برنامه غیرعادی است؛ لاگ‌ها را بررسی کنید'
ErrAppParamKey: 'پارامتر برنامه نامعتبر است: {{ .name }}'
ErrAppUpgrade: 'ارتقاء برنامه ناموفق بود: {{ .name }} {{ .err }}'
AppRecover: 'بازگشت برنامه {{ .name }}'
PullImageStart: 'دریافت تصویر [{{ .name }}]'
PullImageSuccess: 'تصویر دریافت شد'
AppStoreSyncSuccess: 'فروشگاه برنامه همگام‌سازی شد'
SyncAppDetail: 'همگام‌سازی پیکربندی برنامه'
AppVersionNotMatch: 'رد شدن {{ .name }}: نیاز به 1Panel جدیدتر دارد'
MoveSiteDir: 'دایرکتوری وب‌سایت تغییر کرد؛ مهاجرت دایرکتوری OpenResty به {{ .name }}'
MoveSiteDirSuccess: 'دایرکتوری وب‌سایت مهاجرت کرد'
DeleteRuntimePHP: 'حذف محیط اجرا PHP'
CustomAppStoreFileValid: 'بسته فروشگاه برنامه باید .tar.gz باشد'
PullImageTimeout: 'زمان دریافت تصویر به پایان رسید؛ آینه دیگری را امتحان کنید'
ErrAppIsDown: 'برنامه {{ .name }} غیرعادی است'
ErrCustomApps: 'برنامه‌های نصب شده شناسایی شدند؛ ابتدا حذف نصب کنید'
ErrCustomRuntimes: 'محیط‌های اجرایی نصب شده شناسایی شدند؛ ابتدا حذف کنید'
ErrAppVersionDeprecated: "برنامه {{ .name }} با نسخه فعلی 1Panel سازگار نیست، رد شد"
ErrDockerFailed: 'Docker غیرعادی است؛ وضعیت سرویس را بررسی کنید'
ErrDockerComposeCmdNotFound: 'Docker Compose روی میزبان یافت نشد'
UseExistImage: 'تصویر وجود دارد؛ استفاده از تصویر موجود'
ErrDatabaseNotFound: 'پایگاه داده یافت نشد: {{ .name }}'
# SSH
ExportIP: "IP ورود"
ExportArea: "مکان"
ExportPort: "پورت"
ExportAuthMode: "روش ورود"
ExportUser: "کاربر"
ExportStatus: "وضعیت ورود"
ExportDate: "زمان"
# فایل
ErrFileCanNotRead: 'پیش‌نمایش فایل پشتیبانی نمی‌شود'
ErrSensitiveFileRead: 'خواندن فایل‌های حساس مجاز نیست'
ErrFileToLarge: 'فایل بزرگتر از ۱۰ مگابایت است'
ErrPathNotFound: 'دایرکتوری وجود ندارد'
ErrMovePathFailed: 'مسیر هدف نمی‌تواند شامل مسیر منبع باشد'
ErrLinkPathNotFound: 'مسیر هدف وجود ندارد!'
ErrFileIsExist: 'فایل یا پوشه از قبل وجود دارد!'
ErrFileUpload: 'بارگذاری ناموفق بود: {{ .name }} {{ .detail }}'
ErrFileDownloadDir: 'دانلود دایرکتوری پشتیبانی نمی‌شود'
ErrFileSharePath: 'مسیر فایل نامعتبر است یا هدف یک فایل نیست'
ErrFileShareInvalid: 'لینک اشتراک نامعتبر یا منقضی شده است'
ErrFileShareExpired: 'لینک اشتراک منقضی شده است'
ErrFileSharePassword: 'رمز عبور اشتراک اشتباه است'
ErrFileShareExhausted: 'محدودیت دانلود برای این اشتراک رسیده است'
ErrFileSharePasswordPolicy: 'رمز عبور باید حداقل ۴ کاراکتر باشد'
ErrFileShareRateLimit: 'تعداد درخواست‌ها زیاد است، لطفاً بعداً دوباره تلاش کنید'
ErrCmdNotFound: 'دستور یافت نشد: {{ .name }}'
ErrSourcePathNotFound: 'دایرکتوری منبع وجود ندارد'
ErrFavoriteExist: 'مسیر از قبل در نشان‌ها وجود دارد'
ErrInvalidChar: 'کاراکترهای غیرمجاز مجاز نیستند'
ErrPathNotDelete: 'دایرکتوری انتخاب شده قابل حذف نیست'
ErrLogFileToLarge: 'فایل لاگ بیش از ۵۰۰ مگابایت است'
FileDropFailed: 'پاک‌سازی فایل ناموفق بود: {{ .name }} {{ .err }}'
FileDropSuccess: 'پاک‌سازی {{ .name }}؛ فایل‌ها: {{ .count }}، آزاد شده: {{ .size }}'
FileDropSum: 'پاک‌سازی انجام شد؛ فایل‌ها: {{ .count }}، آزاد شده: {{ .size }}'
ErrBadDecrypt: 'رمز عبور آرشیو اشتباه است؛ استخراج ناموفق بود'
# وب‌سایت
ErrAliasIsExist: 'نام مستعار از قبل وجود دارد'
ErrBackupMatch: 'داده‌های پشتیبان مطابقت ندارند: {{ .detail }}'
ErrBackupExist: 'داده‌های منبع پشتیبان وجود ندارند: {{ .detail }}'
ErrPHPResource: 'تغییر محیط اجرای محلی پشتیبانی نمی‌شود'
ErrPathPermission: 'پوشه غیر ۱۰۰۰:۱۰۰۰ در دایرکتوری ایندکس ممکن است باعث خطای دسترسی شود'
ErrDomainIsUsed: 'نام دامنه قبلاً توسط وب‌سایت [{{ .name }}] استفاده می‌شود'
ErrDomainFormat: 'فرمت دامنه نامعتبر است: {{ .name }}'
ErrDefaultAlias: 'default رزرو شده است؛ از نام مستعار دیگری استفاده کنید'
ErrParentWebsite: 'ابتدا زیرسایت {{ .name }} را حذف کنید'
ErrBuildDirNotFound: 'دایرکتوری ساخت وجود ندارد'
ErrImageNotExist: 'تصویر محیط اجرا یافت نشد: {{ .name }}'
ErrProxyIsUsed: 'تعادل بار توسط پراکسی معکوس استفاده می‌شود'
ErrSSLValid: 'فایل گواهی نامعتبر است'
ErrWebsiteDir: 'یک زیردایرکتوری در زیر دایرکتوری وب‌سایت انتخاب کنید'
ErrComposerFileNotFound: "فایل composer.json وجود ندارد"
ErrRuntimeNoPort: 'پورت محیط اجرا تنظیم نشده است'
ErrRuntimeProjectDirContainsCodeDir: 'دایرکتوری محیط اجرا شامل دایرکتوری پروژه انتخاب شده است. لطفاً دایرکتوری پروژه دیگری را انتخاب کرده و دوباره ایجاد کنید.'
Status: 'وضعیت'
start: 'شروع'
stop: 'توقف'
restart: 'راه‌اندازی مجدد'
kill: 'توقف اجباری'
pause: 'مکث'
unpause: 'ادامه'
remove: 'حذف'
delete: 'حذف'
ErrDefaultWebsite: 'وب‌سایت پیش‌فرض از قبل تنظیم شده است؛ ابتدا آن را لغو تنظیم کنید'
SSL: 'گواهی'
Set: 'تنظیمات'
# گواهی SSL
ErrSSLCannotDelete: 'گواهی {{ .name }} توسط یک وب‌سایت در حال استفاده است'
ErrAccountCannotDelete: 'حساب به یک گواهی متصل است و قابل حذف نیست'
ErrSSLApply: 'گواهی تمدید شد؛ بارگذاری مجدد OpenResty ناموفق بود'
ErrEmailIsExist: 'ایمیل از قبل وجود دارد'
ErrSSLKeyNotFound: 'فایل کلید خصوصی وجود ندارد'
ErrSSLCertificateNotFound: 'فایل گواهی وجود ندارد'
ErrSSLKeyFormat: 'تأیید فایل کلید خصوصی ناموفق بود'
ErrSSLCertificateFormat: 'فرمت گواهی نامعتبر است؛ از PEM استفاده کنید'
ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid یا EabHmacKey نمی‌توانند خالی باشند'
ErrOpenrestyNotFound: 'حالت HTTP نیاز به OpenResty دارد'
ApplySSLStart: 'شروع درخواست گواهی. دامنه: [{{ .domain }}]، روش: [{{ .type }}]'
dnsAccount: 'خودکار DNS'
dnsManual: 'دستی DNS'
http: 'HTTP'
ApplySSLFailed: 'درخواست گواهی برای [{{ .domain }}] ناموفق بود: {{ .detail }}'
ApplySSLSuccess: 'گواهی برای [{{ .domain }}] صادر شد'
DNSAccountName: 'حساب DNS [{{ .name }}]، ارائه‌دهنده [{{ .type }}]'
PushDirLog: 'گواهی به دایرکتوری [{{ .path }}] ارسال شد {{ .status }}'
ErrDeleteCAWithSSL: 'CA گواهی‌هایی صادر کرده است؛ قابل حذف نیست'
ErrDeleteWithPanelSSL: 'گواهی در تنظیمات SSL پنل در حال استفاده است'
ErrDefaultCA: 'مرجع پیش‌فرض قابل حذف نیست'
ApplyWebSiteSSLLog: 'به‌روزرسانی گواهی وب‌سایت: {{ .name }}'
ErrUpdateWebsiteSSL: 'به‌روزرسانی گواهی وب‌سایت {{ .name }} ناموفق بود: {{ .err }}'
ApplyWebSiteSSLSuccess: 'گواهی وب‌سایت به‌روزرسانی شد'
ErrExecShell: 'اجرای اسکریپت ناموفق بود {{ .err }}'
ExecShellStart: 'اجرای اسکریپت'
ExecShellSuccess: 'اسکریپت با موفقیت اجرا شد'
StartUpdateSystemSSL: 'به‌روزرسانی گواهی سیستم'
UpdateSystemSSLSuccess: 'گواهی سیستم به‌روزرسانی شد'
ErrWildcardDomain: 'گواهی‌های عام در حالت HTTP پشتیبانی نمی‌شوند'
ErrApplySSLCanNotDelete: 'گواهی {{ .name }} در حال صدور است و هنوز قابل حذف نیست'
StartPushSSLToNode: 'ارسال گواهی به گره'
PushSSLToNodeFailed: "ارسال گواهی به گره ناموفق بود: {{ .err }}"
PushSSLToNodeSuccess: 'گواهی به گره ارسال شد'
# MySQL
ErrUserIsExist: 'کاربر از قبل وجود دارد'
ErrDatabaseIsExist: 'پایگاه داده از قبل وجود دارد'
ErrExecTimeOut: 'زمان اجرای SQL به پایان رسید'
ErrRemoteExist: 'نام پایگاه داده از راه دور از قبل وجود دارد'
ErrLocalExist: 'نام پایگاه داده محلی از قبل وجود دارد'
RemoteBackup: 'قبل از پشتیبان‌گیری از پایگاه داده از راه دور، کانتینر پایگاه داده محلی را با تصویر {{ .name }} راه‌اندازی کنید'
RemoteRecover: 'قبل از بازیابی پایگاه داده از راه دور، کانتینر پایگاه داده محلی را با تصویر {{ .name }} راه‌اندازی کنید'
Arg: "آرگومان"
# Redis
ErrTypeOfRedis: 'نوع فایل پشتیبان با حالت ماندگاری فعلی مطابقت ندارد'
# کانتینر
ErrInUsed: "{{ .detail }} در حال استفاده است و قابل حذف نیست!"
ErrObjectInUsed: "این شی در حال استفاده است و قابل حذف نیست!"
ErrObjectBeDependent: "این تصویر توسط تصاویر دیگر ارجاع داده شده است و قابل حذف نیست!"
ErrPortRules: 'تعداد پورت‌ها مطابقت ندارد'
ErrPgImagePull: 'زمان دریافت تصویر به پایان رسید؛ شتاب را پیکربندی کنید یا {{ .name }} را به صورت دستی دریافت کنید'
PruneHelper: "پاک‌سازی {{ .name }} فضای دیسک {{ .size }} را آزاد کرد"
ImageRemoveHelper: "تصویر {{ .name }} حذف شد، فضای دیسک {{ .size }} آزاد شد"
BuildCache: 'کش ساخت'
Volume: 'حجم'
Network: "شبکه"
PruneStart: 'پاک‌سازی در حال انجام است'
ContainerBackupPrepare: 'آماده‌سازی فضای کاری پشتیبان کانتینر'
ContainerBackupStop: 'توقف کانتینر قبل از پشتیبان‌گیری'
ContainerBackupInspect: 'بررسی و شبکه کانتینر پشتیبان'
ContainerBackupMounts: 'نصب‌های کانتینر پشتیبان'
ContainerBackupMeta: 'نوشتن فراداده پشتیبان کانتینر'
ContainerBackupStart: 'شروع کانتینر پس از پشتیبان‌گیری'
ContainerRecoverPrepare: 'آماده‌سازی فضای کاری بازیابی کانتینر'
ContainerRecoverExtract: 'استخراج آرشیو پشتیبان کانتینر'
ContainerRecoverParse: 'بارگذاری فراداده پشتیبان کانتینر'
ContainerRecoverCreate: 'بازآفرینی کانتینر'
ContainerRecoverMounts: 'بازیابی نصب‌های کانتینر'
ContainerRecoverStart: 'شروع کانتینر بازیابی شده'
ContainerRecoverCleanup: 'پاک‌سازی فضای کاری بازیابی کانتینر'
ComposeBackupPrepare: 'آماده‌سازی فضای کاری پشتیبان Compose'
ComposeBackupStop: 'توقف Compose قبل از پشتیبان‌گیری'
ComposeBackupFiles: 'پشتیبان‌گیری از فایل‌های Compose'
ComposeBackupContainers: 'پشتیبان‌گیری از کانتینرهای Compose'
ComposeBackupMeta: 'نوشتن فراداده پشتیبان Compose'
ComposeBackupStart: 'شروع Compose پس از پشتیبان‌گیری'
ComposeBackupCleanup: 'پاک‌سازی فضای کاری پشتیبان Compose'
ComposeRecoverPrepare: 'آماده‌سازی فضای کاری بازیابی Compose'
ComposeRecoverExtract: 'استخراج آرشیو پشتیبان Compose'
ComposeRecoverMeta: 'بارگذاری فراداده پشتیبان Compose'
ComposeRecoverMetaLogName: 'فراداده بازیابی Compose: name={{ .name }}'
ComposeRecoverMetaLogPath: 'فراداده بازیابی Compose: backupPath={{ .backupPath }} targetDir={{ .targetDir }}'
ComposeRecoverMetaLogCount: 'فراداده بازیابی Compose: files={{ .files }} containers={{ .containers }}'
ComposeRecoverFiles: 'بازیابی فایل‌های Compose'
ComposeRecoverContainers: 'بازیابی کانتینرهای Compose'
ComposeRecoverRecord: 'ذخیره رکورد Compose'
ComposeRecoverCleanup: 'پاک‌سازی فضای کاری بازیابی Compose'
# محیط اجرا
ErrFileNotExist: 'فایل منبع یافت نشد: {{ .detail }}'
ErrImageBuildErr: 'ساخت تصویر ناموفق بود'
ErrImageExist: "تصویر از قبل وجود دارد. از نام تصویر دیگری استفاده کنید."
ErrDelWithWebsite: 'محیط اجرا به یک وب‌سایت متصل است و قابل حذف نیست'
ErrRuntimeStart: 'شروع ناموفق بود'
ErrPackageJsonNotFound: 'فایل package.json وجود ندارد'
ErrScriptsNotFound: 'هیچ بخش scripts در package.json یافت نشد'
ErrContainerNameNotFound: 'نام کانتینر یافت نشد؛ .env را بررسی کنید'
ErrNodeModulesNotFound: 'node_modules یافت نشد؛ محیط اجرا را ویرایش کنید یا منتظر شروع باشید'
ErrContainerNameIsNull: 'نام کانتینر خالی است'
ErrPHPPortIsDefault: 'پورت ۹۰۰۰ به عنوان پیش‌فرض رزرو شده است؛ از پورت دیگری استفاده کنید'
ErrPHPRuntimePortFailed: 'پورت {{ .name }} قبلاً توسط این محیط اجرا استفاده می‌شود'
# ابزار
ErrConfigNotFound: 'فایل پیکربندی وجود ندارد'
ErrConfigParse: 'فرمت فایل پیکربندی نامعتبر است'
ErrConfigIsNull: 'فایل پیکربندی نمی‌تواند خالی باشد'
ErrConfigDirNotFound: 'دایرکتوری اجرا یافت نشد'
ErrConfigAlreadyExist: 'فایل پیکربندی با همین نام از قبل وجود دارد'
ErrUserFindErr: 'یافتن کاربر {{ .name }} ناموفق بود: {{ .err }}'
# وظیفه زمان‌بندی‌شده
CutWebsiteLogSuccess: 'لاگ وب‌سایت چرخش یافت: {{ .name }} (پشتیبان: {{ .path }})'
HandleShell: 'اجرای اسکریپت {{ .name }}'
HandleCurl: 'درخواست به URL {{ .name }}'
HandleNtpSync: 'همگام‌سازی زمان سیستم'
HandleSystemClean: 'پاک‌سازی کش سیستم'
SystemLog: 'لاگ سیستم'
CutWebsiteLog: 'چرخش لاگ وب‌سایت'
FileOrDir: 'دایرکتوری / فایل'
UploadFile: 'بارگذاری پشتیبان {{ .file }} به {{ .backup }}'
Upload: "بارگذاری"
IgnoreBackupErr: 'پشتیبان‌گیری ناموفق بود: {{ .detail }} (نادیده گرفته شد)'
IgnoreUploadErr: 'بارگذاری ناموفق بود: {{ .detail }} (نادیده گرفته شد)'
LoadBackupFailed: 'دریافت اطلاعات اتصال حساب پشتیبان ناموفق بود: {{ .detail }}'
InExecuting: 'وظیفه در حال اجراست'
NoSuchResource: 'هیچ رکورد پشتیبان یافت نشد؛ رد شد'
CleanLog: 'پاک‌سازی لاگ'
CleanLogByName: 'پاک‌سازی لاگ‌های {{ .name }}'
WafIpGroupNotFound: "گروه IP WAF یافت نشد. به [ویژگی‌های پیشرفته -> WAF -> لیست سیاه/سفید -> گروه IP] بروید و با استفاده از دانلود از راه دور یکی را اضافه کنید."
# جعبه‌ابزار
ErrNotExistUser: 'کاربر وجود ندارد'
ErrBanAction: 'پیکربندی ناموفق بود: سرویس {{ .name }} در دسترس نیست'
ErrClamdscanNotFound: 'دستور clamdscan یافت نشد'
TaskSwapSet: 'تنظیم swap'
SetSwap: "تنظیم Swap {{ .path }} - {{ .size }}"
CreateSwap: 'ایجاد فایل swap'
FormatSwap: 'فرمت فایل swap'
EnableSwap: 'فعال‌سازی swap'
# محافظت در برابر دستکاری
CleanTamperSetting: 'پاک‌سازی تنظیمات حفاظتی قدیمی'
SetTamperWithRules: 'فعال‌سازی محافظت دایرکتوری بر اساس قوانین'
ProtectDir: "محافظت از دایرکتوری {{ .name }}"
IgnoreFile: "محافظت از فایل {{ .name }}"
TamperSetSuccessful: 'محافظت تنظیم شد. نظارت بر این دایرکتوری‌ها:'
# WAF
ErrScope: 'این پیکربندی قابل تغییر نیست'
ErrStateChange: 'تغییر وضعیت ناموفق بود'
ErrRuleExist: 'قانون از قبل وجود دارد'
ErrRuleNotExist: 'قانون وجود ندارد'
ErrParseIP: 'فرمت IP نامعتبر است'
ErrDefaultIP: 'default رزرو شده است؛ از نام دیگری استفاده کنید'
ErrGroupInUse: 'گروه IP توسط قوانین لیست سیاه/سفید استفاده می‌شود'
ErrIPGroupAclUse: 'گروه IP توسط قوانین سفارشی وب‌سایت {{ .name }} استفاده می‌شود'
ErrGroupExist: 'نام گروه IP از قبل وجود دارد'
ErrIPRange: 'محدوده IP نامعتبر است'
ErrIPExist: 'IP از قبل وجود دارد'
urlDefense: 'قوانین URL'
urlHelper: 'URL مسدود شده'
dirFilter: 'فیلتر دایرکتوری'
xss: 'XSS'
phpExec: 'اجرای اسکریپت PHP'
oneWordTrojan: 'تروژان یک کلمه‌ای'
appFilter: 'فیلتر دایرکتوری خطرناک برنامه'
webShell: 'WebShell'
args: 'قوانین پارامتر'
protocolFilter: 'فیلتر پروتکل'
javaFilter: 'فیلتر فایل خطرناک جاوا'
scannerFilter: 'فیلتر اسکنر'
escapeFilter: 'فیلتر فرار'
customRule: 'قوانین سفارشی'
httpMethod: 'فیلتر روش HTTP'
fileExt: 'محدودیت‌های بارگذاری فایل'
defaultIpBlack: 'گروه IP مخرب'
cookie: 'قوانین کوکی'
urlBlack: 'لیست سیاه URL'
uaBlack: 'لیست سیاه User-Agent'
attackCount: 'محدودیت فرکانس حمله'
fileExtCheck: 'محدودیت‌های بارگذاری فایل'
geoRestrict: 'محدودیت‌های دسترسی منطقه‌ای'
unknownWebsite: 'دسترسی به دامنه غیرمجاز'
notFoundCount: 'محدودیت نرخ ۴۰۴'
headerDefense: 'قوانین هدر'
defaultUaBlack: 'قوانین User-Agent'
methodWhite: 'قوانین HTTP'
captcha: 'تأیید انسانی'
fiveSeconds: 'تأیید ۵ ثانیه‌ای'
vulnCheck: 'قوانین تکمیلی'
acl: 'قوانین سفارشی'
sql: 'تزریق SQL'
cc: 'محدودیت فرکانس دسترسی'
defaultUrlBlack: 'قوانین URL'
sqlInject: 'تزریق SQL'
ErrDBNotExist: 'پایگاه داده وجود ندارد'
allow: 'مجاز'
deny: 'ممنوع'
OpenrestyNotFound: 'OpenResty نصب نشده است'
remoteIpIsNull: "لیست IP خالی است"
OpenrestyVersionErr: 'نسخه OpenResty بسیار پایین است؛ به ۱.۲۷.۱.۲-۲-۲-focal ارتقاء دهید'
ErrFileTooLarge: 'فایل بزرگتر از ۱ مگابایت است و قابل بارگذاری نیست'
# وظیفه
TaskStart: '{{ .name }} [شروع]'
TaskEnd: '{{ .name }} [انجام شد]'
TaskFailed: 'وظیفه {{ .name }} ناموفق بود'
TaskTimeout: 'زمان وظیفه {{ .name }} به پایان رسید'
TaskSuccess: 'وظیفه {{ .name }} با موفقیت انجام شد'
TaskRetry: 'تلاش مجدد #{{ .name }}'
SubTaskSuccess: '{{ .name }} با موفقیت انجام شد'
SubTaskFailed: '{{ .name }} ناموفق بود: {{ .err }}'
TaskInstall: 'نصب'
TaskUninstall: 'حذف نصب'
TaskCreate: 'ایجاد'
TaskDelete: 'حذف'
TaskUpgrade: 'ارتقاء'
TaskUpdate: 'به‌روزرسانی'
TaskRestart: 'راه‌اندازی مجدد'
TaskProtect: "محافظت"
TaskBackup: 'پشتیبان‌گیری'
TaskRecover: 'بازیابی'
TaskRollback: 'بازگشت'
TaskPull: 'دریافت'
TaskCommit: 'ثبت'
TaskBuild: 'ساخت'
TaskPush: 'ارسال'
TaskClean: "پاک‌سازی"
TaskHandle: 'اجرا'
TaskImport: "واردات"
TaskExport: "خروجی"
Website: 'وب‌سایت'
App: 'برنامه'
Runtime: 'محیط اجرا'
Database: 'پایگاه داده'
ConfigFTP: 'ایجاد کاربر FTP {{ .name }}'
ConfigOpenresty: 'ایجاد فایل پیکربندی OpenResty'
InstallAppSuccess: 'برنامه {{ .name }} نصب شد'
ConfigRuntime: 'پیکربندی محیط اجرا'
ConfigApp: 'پیکربندی برنامه'
SuccessStatus: '{{ .name }} با موفقیت انجام شد'
FailedStatus: '{{ .name }} ناموفق بود: {{ .err }}'
HandleLink: 'پردازش لینک‌های برنامه'
HandleDatabaseApp: 'پردازش پارامترهای برنامه'
ExecShell: 'اجرای اسکریپت {{ .name }}'
PullImage: 'دریافت تصویر'
Start: 'شروع'
Run: 'شروع'
Stop: 'توقف'
Image: 'تصویر'
Compose: 'Compose'
Container: 'کانتینر'
AppLink: 'برنامه متصل'
EnableSSL: 'فعال‌سازی HTTPS'
AppStore: 'فروشگاه برنامه'
TaskSync: 'همگام‌سازی'
LocalApp: 'برنامه محلی'
SubTask: 'وظیفه فرعی'
RuntimeExtension: 'پسوند محیط اجرا'
TaskIsExecuting: 'وظیفه در حال اجراست'
CustomAppstore: 'مخزن برنامه سفارشی'
TaskExec: 'اجرا'
TaskBatch: "عملیات دسته‌ای"
FileConvert: 'تبدیل فایل'
# وظیفه - ClamAV
Clamscan: "اسکن {{ .name }}"
TaskScan: "اسکن"
# وظیفه - هوش مصنوعی
OllamaModelPull: 'دریافت مدل Ollama {{ .name }}'
OllamaModelSize: 'دریافت اندازه مدل Ollama: {{ .name }}'
AIBenchmarkRun: 'اجرای معیار سنجش هوش مصنوعی'
# وظیفه - اسنپ‌شات
Snapshot: 'تصویر لحظه‌ای'
SnapDBInfo: 'نوشتن اطلاعات پایگاه داده 1Panel'
SnapCopy: 'کپی فایل‌ها/دایرکتوری‌ها {{ .name }}'
SnapNewDB: 'راه‌اندازی اتصال پایگاه داده {{ .name }}'
SnapDeleteOperationLog: 'حذف لاگ‌های عملیات'
SnapDeleteLoginLog: 'حذف لاگ‌های دسترسی'
SnapDeleteMonitor: 'حذف داده‌های نظارت'
SnapRemoveSystemIP: 'حذف IP سیستم'
SnapBaseInfo: 'نوشتن اطلاعات پایه 1Panel'
SnapInstallAppImageEmpty: 'هیچ تصویر برنامه‌ای انتخاب نشد؛ رد شد'
SnapInstallApp: 'پشتیبان‌گیری از برنامه‌های نصب شده'
SnapDockerSave: 'فشرده‌سازی برنامه‌های نصب شده'
SnapLocalBackup: 'پشتیبان‌گیری از دایرکتوری پشتیبان محلی'
SnapCompressBackup: 'فشرده‌سازی دایرکتوری پشتیبان محلی'
SnapPanelData: 'پشتیبان‌گیری از دایرکتوری داده 1Panel'
SnapCompressPanel: 'فشرده‌سازی دایرکتوری داده'
SnapWebsite: 'پشتیبان‌گیری از دایرکتوری وب‌سایت'
SnapCloseDBConn: 'بستن اتصال پایگاه داده'
SnapCompress: 'ایجاد فایل تصویر لحظه‌ای'
SnapCompressFile: 'فشرده‌سازی فایل تصویر لحظه‌ای'
SnapCheckCompress: 'بررسی آرشیو تصویر لحظه‌ای'
SnapCompressSize: 'اندازه تصویر لحظه‌ای {{ .name }}'
SnapUpload: 'بارگذاری فایل تصویر لحظه‌ای'
SnapUploadTo: 'بارگذاری تصویر لحظه‌ای به {{ .name }}'
SnapUploadRes: 'بارگذاری تصویر لحظه‌ای به {{ .name }}'
SnapshotRecover: 'بازیابی تصویر لحظه‌ای'
RecoverDownload: 'دانلود فایل تصویر لحظه‌ای'
Download: 'دانلود'
RecoverDownloadAccount: 'دریافت حساب دانلود تصویر لحظه‌ای {{ .name }}'
RecoverDecompress: 'باز کردن فشرده آرشیو تصویر لحظه‌ای'
Decompress: 'باز کردن فشرده'
BackupBeforeRecover: 'پشتیبان‌گیری از داده‌های سیستم قبل از بازیابی'
ReadJson: 'خواندن فایل JSON تصویر لحظه‌ای'
ReadJsonPath: 'دریافت مسیر JSON تصویر لحظه‌ای'
ReadJsonContent: 'خواندن محتوای JSON'
ReadJsonMarshal: 'پردازش فرار JSON'
RecoverApp: 'بازیابی برنامه‌های نصب شده'
RecoverWebsite: 'بازیابی دایرکتوری وب‌سایت'
RecoverAppImage: 'بازیابی پشتیبان تصویر تصویر لحظه‌ای'
RecoverCompose: 'بازیابی سایر پروژه‌های Compose'
RecoverComposeList: 'دریافت همه پروژه‌های Compose برای بازیابی'
RecoverComposeItem: 'بازیابی Compose {{ .name }}'
RecoverAppEmpty: 'هیچ پشتیبان تصویر برنامه در تصویر لحظه‌ای یافت نشد'
RecoverBaseData: 'بازیابی داده‌های پایه و فایل‌ها'
RecoverDaemonJsonEmpty: 'daemon.json در تصویر لحظه‌ای یا میزبان فعلی یافت نشد'
RecoverDaemonJson: 'بازیابی daemon.json'
RecoverDBData: 'بازیابی داده‌های پایگاه داده'
RecoverBackups: 'بازیابی دایرکتوری پشتیبان محلی'
RecoverPanelData: 'بازیابی دایرکتوری داده'
# وظیفه - کانتینر
ContainerImagePull: 'دریافت تصویر کانتینر {{ .name }}'
ContainerRemoveOld: 'حذف کانتینر اصلی {{ .name }}'
ContainerImageCheck: 'بررسی نتیجه دریافت تصویر'
ContainerLoadInfo: 'بارگذاری اطلاعات کانتینر'
ContainerRecreate: 'به‌روزرسانی کانتینر ناموفق بود؛ بازگردانی کانتینر اصلی'
ContainerCreate: 'ایجاد کانتینر جدید {{ .name }}'
ContainerCreateFailed: 'ایجاد کانتینر ناموفق بود؛ حذف کانتینر ناموفق'
ContainerStartCheck: 'بررسی شروع کانتینر'
# وظیفه - تصویر
ImageBuild: 'ساخت تصویر'
ImagePull: 'دریافت تصویر'
ImageRepoAuthFromDB: 'بارگذاری احراز هویت مخزن از پایگاه داده'
ImagePush: 'ارسال تصویر'
ImageRenameTag: 'به‌روزرسانی برچسب تصویر'
ImageNewTag: 'برچسب تصویر جدید {{ .name }}'
ComposeCreate: 'ایجاد پروژه Compose'
# وظیفه - وب‌سایت
BackupNginxConfig: 'پشتیبان‌گیری از پیکربندی OpenResty وب‌سایت'
CompressFileSuccess: 'دایرکتوری به {{ .name }} فشرده شد'
CompressDir: 'فشرده‌سازی دایرکتوری'
DeCompressFile: 'باز کردن فشرده فایل {{ .name }}'
ErrCheckValid: 'تأیید فایل پشتیبان ناموفق بود: {{ .name }}'
Rollback: 'بازگشت'
websiteDir: 'دایرکتوری وب‌سایت'
RecoverFailedStartRollBack: 'بازیابی ناموفق بود؛ شروع بازگشت'
AppBackupFileIncomplete: 'پشتیبان ناقص است: app.json یا app.tar.gz وجود ندارد'
AppAttributesNotMatch: 'نوع یا نام برنامه مطابقت ندارد'
# هشدار
ErrAlertMethodNotSupported: 'این نسخه از این روش هشدار پشتیبانی نمی‌کند'
ErrAlertSync: 'همگام‌سازی پیام هشدار ناموفق بود'
# وظیفه - محیط اجرا
ErrInstallExtension: 'وظیفه نصب پسوند دیگری در حال اجراست'
# قالب ایمیل هشدار
PanelAlertTitle: "اعلان هشدار پنل"
TestAlertTitle: "ایمیل آزمایشی - تأیید اتصال ایمیل"
TestAlert: "این یک ایمیل آزمایشی برای تأیید صحت پیکربندی ارسال ایمیل شما است."
LicenseExpirationAlert: "پنل {{ .node }}{{ .ip }}: مجوز در {{ .day }} روز منقضی می‌شود. برای مشاهده جزئیات وارد شوید."
CronJobFailedAlert: "پنل {{ .node }}{{ .ip }}: وظیفه زمان‌بندی {{ .name }} ناموفق بود. برای مشاهده جزئیات وارد شوید."
ClamAlert: "پنل {{ .node }}{{ .ip }}: اسکن ویروس {{ .num }} فایل آلوده پیدا کرد. برای مشاهده جزئیات وارد شوید."
WebSiteAlert: "پنل {{ .node }}{{ .ip }}: {{ .num }} وب‌سایت در {{ .day }} روز منقضی می‌شوند. برای مشاهده جزئیات وارد شوید."
SSLAlert: "پنل {{ .node }}{{ .ip }}: {{ .num }} گواهی SSL در {{ .day }} روز منقضی می‌شوند. برای مشاهده جزئیات وارد شوید."
DiskUsedAlert: "پنل {{ .node }}{{ .ip }}: استفاده از دیسک {{ .name }} به {{ .used }} رسید. برای مشاهده جزئیات وارد شوید."
ResourceAlert: "پنل {{ .node }}{{ .ip }}: میانگین استفاده {{ .name }} در {{ .time }} دقیقه برابر با {{ .used }} است. برای مشاهده جزئیات وارد شوید."
PanelVersionAlert: "پنل {{ .node }}{{ .ip }}: نسخه جدید پنل موجود است. برای مشاهده جزئیات وارد شوید."
PanelPwdExpirationAlert: "پنل {{ .node }}{{ .ip }}: رمز عبور پنل در {{ .day }} روز منقضی می‌شود. برای مشاهده جزئیات وارد شوید."
CommonAlert: "پنل {{ .node }}{{ .ip }}: {{ .msg }}. برای مشاهده جزئیات وارد شوید."
NodeExceptionAlert: "پنل {{ .node }}{{ .ip }}: {{ .num }} گره غیرعادی هستند. برای مشاهده جزئیات وارد شوید."
LicenseExceptionAlert: "پنل {{ .node }}{{ .ip }}: {{ .num }} مجوز غیرعادی است. برای مشاهده جزئیات وارد شوید."
SSHAndPanelLoginAlert: "پنل {{ .node }}{{ .ip }}: ورود غیرعادی {{ .name }} از {{ .loginIp }}. برای مشاهده جزئیات وارد شوید."
# دیسک
DeviceNotFound: "دستگاه {{ .name }} یافت نشد"
DeviceIsMounted: 'دستگاه {{ .name }} متصل است؛ ابتدا قطع اتصال کنید'
PartitionDiskErr: 'پارتیشن‌بندی ناموفق بود: {{ .err }}'
FormatDiskErr: 'فرمت کردن ناموفق بود: {{ .err }}'
MountDiskErr: 'اتصال ناموفق بود: {{ .err }}'
XfsNotFound: 'xfs یافت نشد؛ ابتدا xfsprogs را نصب کنید'
# ترمینال
TerminalAIBlockedRiskyCommand: 'دستور پرخطر مسدود شد: {{ .command }}'
TerminalAIThinking: 'هوش مصنوعی در حال فکر کردن است...'
TerminalAIReadyToExecute: 'تفکر کامل شد، برای اجرا Enter را فشار دهید (مدت زمان: {{ .duration }}، توکن‌ها: {{ .tokens }})'
TerminalAIRequestFailed: 'درخواست هوش مصنوعی ناموفق بود: {{ .err }}'
# دروازه هوش مصنوعی
ErrAIProxyServiceNotInstalled: 'سرویس {{ .name }} نصب نشده است'
ErrAIProxyModelAccountNotFound: 'حساب مدل {{ .id }} یافت نشد'
ErrAIProxyModelMapRequired: 'این فیلد الزامی است.'
ErrAIProxyModelMapInvalid: 'نگاشت مدل باید یک شی JSON معتبر باشد: {{ .err }}'
ErrAIProxyModelMapEmpty: 'نگاشت مدل نمی‌تواند خالی باشد'
ErrAIProxyModelMapEmptyExternalModel: 'نگاشت مدل شامل یک مدل درخواست خالی است'
ErrAIProxyModelMapEmptyUpstreamModel: 'مدل بالادست برای {{ .model }} نمی‌تواند خالی باشد'
AIProxyUserFallback: 'کاربر حذف شده (شناسه: {{ .id }})'
+92 -21
View File
@@ -1,29 +1,47 @@
# 基本エラー
ErrInvalidParams: '不正なリクエスト: {{ .detail }}' ErrInvalidParams: '不正なリクエスト: {{ .detail }}'
ErrTokenParse: 'トークンエラー: {{ .detail }}' ErrTokenParse: 'トークンエラー: {{ .detail }}'
ErrInitialPassword: '元のパスワードが違います' ErrInitialPassword: '元のパスワードが違います'
ErrInternalServer: '内部エラー: {{ .detail }}' ErrInternalServer: '内部エラー: {{ .detail }}'
ErrRecordExist: 'レコードが既に存在します'
ErrRecordNotFound: 'レコードが見つかりません'
ErrStructTransform: '型変換エラー: {{ .err }}'
ErrNotSupportType: '未対応のタイプ: {{ .name }}'
# ファイルAI
ErrFileAINotEnabled: 'ファイル管理の「AI アカウント」でファイル AI 検索を有効にし、アカウントを選んでください。' ErrFileAINotEnabled: 'ファイル管理の「AI アカウント」でファイル AI 検索を有効にし、アカウントを選んでください。'
ErrFileAISearchBadPattern: '検索パターンが無効です(正規表現など): {{ .detail }}' ErrFileAISearchBadPattern: '検索パターンが無効です(正規表現など): {{ .detail }}'
FileAISearchEmptyDir: 'このパス以下に一覧できるファイルまたはフォルダーがありません(またはすべて除外されました)。'
# リモートダウンロード
ErrWgetRemoteFailed: 'リモートのダウンロード URL が無効か、到達できません:{{ .detail }}' ErrWgetRemoteFailed: 'リモートのダウンロード URL が無効か、到達できません:{{ .detail }}'
ErrWgetInvalidContentType: 'リモート URL がファイルではなくエラーページ等を返しました、{{ .detail }}' ErrWgetInvalidContentType: 'リモート URL がファイルではなくエラーページ等を返しました、{{ .detail }}'
ErrWgetProxyNotConfigured: '先にパネル設定でプロキシサーバーを設定してください' ErrWgetProxyNotConfigured: '先にパネル設定でプロキシサーバーを設定してください'
ErrWgetProxyInvalid: 'プロキシサーバーのアドレスが無効です:{{ .detail }}' ErrWgetProxyInvalid: 'プロキシサーバーのアドレスが無効です:{{ .detail }}'
ErrRecordExist: 'レコードが既に存在します'
ErrRecordNotFound: 'レコードが見つかりません' # ログインとセキュリティ
ErrStructTransform: '型変換エラー: {{ .err }}'
ErrNotLogin: 'ログインしていません: {{ .detail }}' ErrNotLogin: 'ログインしていません: {{ .detail }}'
ErrPasswordExpired: 'パスワード期限切れ: {{ .detail }}' ErrPasswordExpired: 'パスワード期限切れ: {{ .detail }}'
ErrNotSupportType: '未対応のタイプ: {{ .name }}'
ErrAlertMethodNotSupported: 'このバージョンではこの通知方法は利用できません' # リクエストとAPI
ErrProxy: 'リクエストに失敗しました: {{ .detail }}' ErrProxy: 'リクエストに失敗しました: {{ .detail }}'
ErrApiConfigStatusInvalid: 'API利用不可: {{ .detail }}' ErrApiConfigStatusInvalid: 'API利用不可: {{ .detail }}'
ErrApiConfigKeyInvalid: 'APIキーが無効です: {{ .detail }}' ErrApiConfigKeyInvalid: 'APIキーが無効です: {{ .detail }}'
ErrApiConfigIPInvalid: 'IPが許可されていません: {{ .detail }}' ErrApiConfigIPInvalid: 'IPが許可されていません: {{ .detail }}'
ErrApiConfigDisable: 'APIは無効です: {{ .detail }}' ErrApiConfigDisable: 'APIは無効です: {{ .detail }}'
ErrApiConfigKeyTimeInvalid: 'タイムスタンプが無効です: {{ .detail }}' ErrApiConfigKeyTimeInvalid: 'タイムスタンプが無効です: {{ .detail }}'
ErrShutDown: 'コマンドは手動で停止されました' ErrCreateHttpClient: 'リクエスト {{ .err }} の作成に失敗しました'
ErrHttpReqTimeOut: 'リクエストがタイムアウトしました {{ .err }}'
ErrHttpReqFailed: 'リクエストが失敗しました {{ .err }}'
ErrNoSuchHost: '要求されたサーバー {{ .err }} が見つかりません'
ErrHttpReqNotFound: '要求されたリソース {{ .err }} が見つかりませんでした'
# クイックジャンプ
ErrMinQuickJump: 'クイックアクセスを1件以上追加' ErrMinQuickJump: 'クイックアクセスを1件以上追加'
ErrMaxQuickJump: '最大4件のクイックアクセス' ErrMaxQuickJump: '最大4件のクイックアクセス'
# 共通
ErrShutDown: 'コマンドは手動で停止されました'
ErrUsernameIsExist: 'ユーザー名はすでに使われています' ErrUsernameIsExist: 'ユーザー名はすでに使われています'
ErrNameIsExist: '名称はすでに使われています' ErrNameIsExist: '名称はすでに使われています'
ErrDemoEnvironment: 'デモ環境では利用できません' ErrDemoEnvironment: 'デモ環境では利用できません'
@@ -41,6 +59,8 @@ SystemRestart: 'システムの再起動によりタスクが中断されまし
ErrGroupIsDefault: 'デフォルト グループ、削除できません' ErrGroupIsDefault: 'デフォルト グループ、削除できません'
ErrGroupIsInWebsiteUse: 'グループは別の Web サイトで使用されているため、削除できません。' ErrGroupIsInWebsiteUse: 'グループは別の Web サイトで使用されているため、削除できません。'
Decrypt: '復号化' Decrypt: '復号化'
# エージェント
ErrAgentAccountBound: 'アカウントはエージェントに紐づいています' ErrAgentAccountBound: 'アカウントはエージェントに紐づいています'
ErrTerminalAIAccountInUse: 'このモデルアカウントは Terminal AI で使用中です。Terminal AI の設定で別のアカウントへ切り替えるか、Terminal AI を無効にしてから再試行してください。' ErrTerminalAIAccountInUse: 'このモデルアカウントは Terminal AI で使用中です。Terminal AI の設定で別のアカウントへ切り替えるか、Terminal AI を無効にしてから再試行してください。'
ErrAgentAccountUnavailable: 'アカウント接続不可: {{ .err }}' ErrAgentAccountUnavailable: 'アカウント接続不可: {{ .err }}'
@@ -65,14 +85,8 @@ ErrAgentWebsiteInUse: 'このサイトはすでに別のエージェントに関
ErrAgentWebsiteUnbindUnsupported: 'ワンクリックデプロイのサイトは手動で関連解除できません' ErrAgentWebsiteUnbindUnsupported: 'ワンクリックデプロイのサイトは手動で関連解除できません'
ErrHermesPairingCodeUnavailable: 'Hermes でペアリングコードが一時的に見つかりません。ネットワーク要因の可能性があるため、しばらくしてから再試行してください。' ErrHermesPairingCodeUnavailable: 'Hermes でペアリングコードが一時的に見つかりません。ネットワーク要因の可能性があるため、しばらくしてから再試行してください。'
ErrHermesFeishuGroupAllowlistRequiresAllowlist: 'Feishu のグループポリシーが許可リストの場合、DM ポリシーをペアリングコードにはできません。' ErrHermesFeishuGroupAllowlistRequiresAllowlist: 'Feishu のグループポリシーが許可リストの場合、DM ポリシーをペアリングコードにはできません。'
ErrAIProxyServiceNotInstalled: '{{ .name }} サービスはインストールされていません'
ErrAIProxyModelAccountNotFound: 'モデルアカウント {{ .id }} が見つかりません' # バックアップとアラート設定
ErrAIProxyModelMapRequired: 'この項目は必須です。'
ErrAIProxyModelMapInvalid: 'モデルマッピングは有効な JSON オブジェクトである必要があります: {{ .err }}'
ErrAIProxyModelMapEmpty: 'モデルマッピングは空にできません'
ErrAIProxyModelMapEmptyExternalModel: 'モデルマッピングに空のリクエストモデルがあります'
ErrAIProxyModelMapEmptyUpstreamModel: '{{ .model }} の上流モデルは空にできません'
AIProxyUserFallback: 'ユーザー {{ .id }}'
Localhost: 'ローカルマシン' Localhost: 'ローカルマシン'
ErrBackupInUsed: 'バックアップアカウントがスケジュールで使用中' ErrBackupInUsed: 'バックアップアカウントがスケジュールで使用中'
ErrBackupCheck: '接続テストに失敗しました: {{ .err }}' ErrBackupCheck: '接続テストに失敗しました: {{ .err }}'
@@ -80,6 +94,8 @@ ErrBackupLocalDelete: 'ローカルバックアップは削除できません'
ErrBackupLocalCreate: 'ローカルバックアップは作成できません' ErrBackupLocalCreate: 'ローカルバックアップは作成できません'
ErrAlertConfigInUse: 'アラート設定は使用中のため削除できません' ErrAlertConfigInUse: 'アラート設定は使用中のため削除できません'
ErrAlertConfigPhoneExist: '電話番号はすでに存在します' ErrAlertConfigPhoneExist: '電話番号はすでに存在します'
# アプリ
ErrPortInUsed: '{{ .detail }} ポートはすでに使用されています' ErrPortInUsed: '{{ .detail }} ポートはすでに使用されています'
ErrAppLimit: 'インストールされているアプリケーションの数が制限を超えました' ErrAppLimit: 'インストールされているアプリケーションの数が制限を超えました'
ErrNotInstall: 'アプリケーションがインストールされていません' ErrNotInstall: 'アプリケーションがインストールされていません'
@@ -97,16 +113,12 @@ ErrFileParseApp: '{{ .name }} ファイルの解析に失敗しました {{ .err
ErrAppDirNull: 'バージョン フォルダーが存在しません' ErrAppDirNull: 'バージョン フォルダーが存在しません'
LocalAppErr: 'アプリケーション {{ .name }} の同期に失敗しました {{ .err }}' LocalAppErr: 'アプリケーション {{ .name }} の同期に失敗しました {{ .err }}'
ErrContainerName: 'コンテナ名が既に存在します' ErrContainerName: 'コンテナ名が既に存在します'
ErrCreateHttpClient: 'リクエスト {{ .err }} の作成に失敗しました'
ErrHttpReqTimeOut: 'リクエストがタイムアウトしました {{ .err }}'
ErrHttpReqFailed: 'リクエストが失敗しました {{ .err }}'
ErrNoSuchHost: '要求されたサーバー {{ .err }} が見つかりません'
ErrHttpReqNotFound: '要求されたリソース {{ .err }} が見つかりませんでした'
ErrContainerNotFound: '{{ .name }} コンテナが存在しません' ErrContainerNotFound: '{{ .name }} コンテナが存在しません'
ErrContainerMsg: '{{ .name }} コンテナが異常です。詳細についてはコンテナページのログを確認してください。' ErrContainerMsg: '{{ .name }} コンテナが異常です。詳細についてはコンテナページのログを確認してください。'
ErrAppBackup: '{{ .name }} アプリケーションのバックアップに失敗しました。エラー {{ .err }}' ErrAppBackup: '{{ .name }} アプリケーションのバックアップに失敗しました。エラー {{ .err }}'
ErrVersionTooLow: '現在の 1Panel のバージョンが低すぎるため、App Store を更新できません。操作する前にバージョンをアップグレードしてください。' ErrVersionTooLow: '現在の 1Panel のバージョンが低すぎるため、App Store を更新できません。操作する前にバージョンをアップグレードしてください。'
ErrAppNameExist: 'アプリケーション名がすでに存在します' ErrAppNameExist: 'アプリケーション名がすでに存在します'
ErrAppInstallNameExist: 'アプリケーションインストール名 {{ .name }} はすでに存在します'
AppStoreIsSyncing: 'App Store が同期中です。しばらくしてからもう一度お試しください' AppStoreIsSyncing: 'App Store が同期中です。しばらくしてからもう一度お試しください'
ErrGetCompose: 'docker-compose.yml ファイルの取得に失敗しました {{ .detail }}' ErrGetCompose: 'docker-compose.yml ファイルの取得に失敗しました {{ .detail }}'
ErrAppWarn: '異常な状態です。ログを確認してください' ErrAppWarn: '異常な状態です。ログを確認してください'
@@ -131,6 +143,8 @@ ErrDockerFailed: 'Docker の状態が異常です。サービス状態を確認
ErrDockerComposeCmdNotFound: 'Docker Compose コマンドは存在しません。ホストマシンにこのコマンドを先にインストールしてください' ErrDockerComposeCmdNotFound: 'Docker Compose コマンドは存在しません。ホストマシンにこのコマンドを先にインストールしてください'
UseExistImage: 'イメージは既に存在します。既存のイメージを使用します' UseExistImage: 'イメージは既に存在します。既存のイメージを使用します'
ErrDatabaseNotFound: 'データベース {{ .name }} は存在しません' ErrDatabaseNotFound: 'データベース {{ .name }} は存在しません'
# SSH
ExportIP: 'ログインIP' ExportIP: 'ログインIP'
ExportArea: '地域' ExportArea: '地域'
ExportPort: 'ポート' ExportPort: 'ポート'
@@ -138,6 +152,8 @@ ExportAuthMode: 'ログイン方式'
ExportUser: 'ユーザー' ExportUser: 'ユーザー'
ExportStatus: 'ログイン状態' ExportStatus: 'ログイン状態'
ExportDate: '時間' ExportDate: '時間'
# ファイル
ErrFileCanNotRead: 'このファイルはプレビューをサポートしていません' ErrFileCanNotRead: 'このファイルはプレビューをサポートしていません'
ErrSensitiveFileRead: '機密ファイルの読み取りは許可されていません' ErrSensitiveFileRead: '機密ファイルの読み取りは許可されていません'
ErrFileToLarge: 'ファイルは 10M より大きいため開けません' ErrFileToLarge: 'ファイルは 10M より大きいため開けません'
@@ -164,6 +180,8 @@ FileDropFailed: 'ファイル {{ .name }} のクリーンアップに失敗し
FileDropSuccess: 'ファイル {{ .name }} のクリーンアップに成功しました、{{ .count }} ファイルを削除、{{ .size }} のディスク領域を解放' FileDropSuccess: 'ファイル {{ .name }} のクリーンアップに成功しました、{{ .count }} ファイルを削除、{{ .size }} のディスク領域を解放'
FileDropSum: 'ファイルのクリーンアップが完了しました、合計 {{ .count }} ファイルを削除、合計 {{ .size }} のディスク領域を解放' FileDropSum: 'ファイルのクリーンアップが完了しました、合計 {{ .count }} ファイルを削除、合計 {{ .size }} のディスク領域を解放'
ErrBadDecrypt: '圧縮パッケージの解凍パスワードが間違っています。解凍に失敗しました。確認後再試行!' ErrBadDecrypt: '圧縮パッケージの解凍パスワードが間違っています。解凍に失敗しました。確認後再試行!'
# ウェブサイト
ErrAliasIsExist: 'エイリアスがすでに存在します' ErrAliasIsExist: 'エイリアスがすでに存在します'
ErrBackupMatch: 'バックアップ ファイルは、現在の Web サイト データ {{ .detail }} の一部と一致しません' ErrBackupMatch: 'バックアップ ファイルは、現在の Web サイト データ {{ .detail }} の一部と一致しません'
ErrBackupExist: 'バックアップ ファイル内のソース データの対応する部分が存在しません {{ .detail }}' ErrBackupExist: 'バックアップ ファイル内のソース データの対応する部分が存在しません {{ .detail }}'
@@ -193,6 +211,8 @@ delete: '削除'
ErrDefaultWebsite: 'デフォルト Web サイトが既に設定されています。設定する前にキャンセルしてください!' ErrDefaultWebsite: 'デフォルト Web サイトが既に設定されています。設定する前にキャンセルしてください!'
SSL: '証明書' SSL: '証明書'
Set: '設定' Set: '設定'
# SSL証明書
ErrSSLCannotDelete: '{{ .name }} 証明書は Web サイトで使用されているため、削除できません' ErrSSLCannotDelete: '{{ .name }} 証明書は Web サイトで使用されているため、削除できません'
ErrAccountCannotDelete: 'アカウントは証明書に関連付けられているため、削除できません' ErrAccountCannotDelete: 'アカウントは証明書に関連付けられているため、削除できません'
ErrSSLApply: '証明書の更新は成功しましたが、openresty の再ロードに失敗しました。設定を確認してください。' ErrSSLApply: '証明書の更新は成功しましたが、openresty の再ロードに失敗しました。設定を確認してください。'
@@ -227,6 +247,8 @@ ErrApplySSLCanNotDelete: '申請中の証明書 {{ .name }} は削除できま
StartPushSSLToNode: '証明書をノードにプッシュ開始' StartPushSSLToNode: '証明書をノードにプッシュ開始'
PushSSLToNodeFailed: 'ノードに証明書をプッシュ失敗: {{ .err }}' PushSSLToNodeFailed: 'ノードに証明書をプッシュ失敗: {{ .err }}'
PushSSLToNodeSuccess: 'ノードに証明書をプッシュ成功' PushSSLToNodeSuccess: 'ノードに証明書をプッシュ成功'
# MySQL
ErrUserIsExist: '現在のユーザーは既に存在します。再入力してください' ErrUserIsExist: '現在のユーザーは既に存在します。再入力してください'
ErrDatabaseIsExist: '現在のデータベースは既に存在します。再入力してください' ErrDatabaseIsExist: '現在のデータベースは既に存在します。再入力してください'
ErrExecTimeOut: 'SQL 実行がタイムアウトしました。データベースを確認してください' ErrExecTimeOut: 'SQL 実行がタイムアウトしました。データベースを確認してください'
@@ -235,7 +257,11 @@ ErrLocalExist: '名前はローカル データベースに既に存在します
RemoteBackup: 'リモートデータベースをバックアップするには、まずイメージ {{ .name }} を使用してローカルコンテナデータベースサービスを起動する必要があります。しばらくお待ちください...' RemoteBackup: 'リモートデータベースをバックアップするには、まずイメージ {{ .name }} を使用してローカルコンテナデータベースサービスを起動する必要があります。しばらくお待ちください...'
RemoteRecover: 'リモートデータベースを復元するには、まずイメージ {{ .name }} を使用してローカルコンテナデータベースサービスを起動する必要があります。しばらくお待ちください...' RemoteRecover: 'リモートデータベースを復元するには、まずイメージ {{ .name }} を使用してローカルコンテナデータベースサービスを起動する必要があります。しばらくお待ちください...'
Arg: '引数' Arg: '引数'
# Redis
ErrTypeOfRedis: 'リカバリ ファイルの種類が現在の永続化方法と一致しません。変更して再試行してください' ErrTypeOfRedis: 'リカバリ ファイルの種類が現在の永続化方法と一致しません。変更して再試行してください'
# コンテナ
ErrInUsed: '{{ .detail }} は使用中であり、削除できません!' ErrInUsed: '{{ .detail }} は使用中であり、削除できません!'
ErrObjectInUsed: 'このオブジェクトは使用中であり、削除できません!' ErrObjectInUsed: 'このオブジェクトは使用中であり、削除できません!'
ErrObjectBeDependent: 'このイメージは他のイメージに依存されているため、削除できません!' ErrObjectBeDependent: 'このイメージは他のイメージに依存されているため、削除できません!'
@@ -277,6 +303,8 @@ ComposeRecoverFiles: 'Compose ファイルを復元'
ComposeRecoverContainers: 'Compose コンテナを復元' ComposeRecoverContainers: 'Compose コンテナを復元'
ComposeRecoverRecord: 'Compose 記録を保存' ComposeRecoverRecord: 'Compose 記録を保存'
ComposeRecoverCleanup: 'Compose 復元作業領域をクリーンアップ' ComposeRecoverCleanup: 'Compose 復元作業領域をクリーンアップ'
# ランタイム
ErrFileNotExist: '{{ .detail }} ファイルが存在しません。ソース ファイルの整合性を確認してください。' ErrFileNotExist: '{{ .detail }} ファイルが存在しません。ソース ファイルの整合性を確認してください。'
ErrImageBuildErr: 'イメージのビルドに失敗しました' ErrImageBuildErr: 'イメージのビルドに失敗しました'
ErrImageExist: 'イメージはすでに存在します!イメージ名を変更してください。' ErrImageExist: 'イメージはすでに存在します!イメージ名を変更してください。'
@@ -289,12 +317,16 @@ ErrNodeModulesNotFound: 'node_modules フォルダが存在しません。ラン
ErrContainerNameIsNull: 'コンテナ名が存在しません' ErrContainerNameIsNull: 'コンテナ名が存在しません'
ErrPHPPortIsDefault: 'ポート9000はデフォルトポートです。修正してから再試行してください' ErrPHPPortIsDefault: 'ポート9000はデフォルトポートです。修正してから再試行してください'
ErrPHPRuntimePortFailed: 'ポート {{ .name }} は現在のランタイム環境で使用されています。修正してから再試行してください' ErrPHPRuntimePortFailed: 'ポート {{ .name }} は現在のランタイム環境で使用されています。修正してから再試行してください'
# ツール
ErrConfigNotFound: '構成ファイルが存在しません' ErrConfigNotFound: '構成ファイルが存在しません'
ErrConfigParse: '構成ファイルの形式が正しくありません' ErrConfigParse: '構成ファイルの形式が正しくありません'
ErrConfigIsNull: '構成ファイルは空にできません' ErrConfigIsNull: '構成ファイルは空にできません'
ErrConfigDirNotFound: '実行ディレクトリが存在しません' ErrConfigDirNotFound: '実行ディレクトリが存在しません'
ErrConfigAlreadyExist: '同じ名前の設定ファイルがすでに存在します' ErrConfigAlreadyExist: '同じ名前の設定ファイルがすでに存在します'
ErrUserFindErr: 'ユーザー {{ .name }} の検索に失敗しました {{ .err }}' ErrUserFindErr: 'ユーザー {{ .name }} の検索に失敗しました {{ .err }}'
# Cronジョブ
CutWebsiteLogSuccess: '{{ .name }} ウェブサイトのログが正常にカットされました。バックアップ パス {{ .path }}' CutWebsiteLogSuccess: '{{ .name }} ウェブサイトのログが正常にカットされました。バックアップ パス {{ .path }}'
HandleShell: 'スクリプト {{ .name }} を実行します' HandleShell: 'スクリプト {{ .name }} を実行します'
HandleCurl: 'URL {{ .name }} にアクセス' HandleCurl: 'URL {{ .name }} にアクセス'
@@ -313,6 +345,8 @@ NoSuchResource: 'データベースにバックアップ内容が見つかりま
CleanLog: 'ログをクリーン' CleanLog: 'ログをクリーン'
CleanLogByName: '{{ .name }} のログをクリーン' CleanLogByName: '{{ .name }} のログをクリーン'
WafIpGroupNotFound: 'WAF IPグループが見つかりません。[高度な機能 - WAF - ブラックリスト/ホワイトリスト - IPグループ]に移動し、リモートダウンロード方式でIPグループを追加してください。' WafIpGroupNotFound: 'WAF IPグループが見つかりません。[高度な機能 - WAF - ブラックリスト/ホワイトリスト - IPグループ]に移動し、リモートダウンロード方式でIPグループを追加してください。'
# ツールボックス
ErrNotExistUser: '現在のユーザーは存在しません。変更してもう一度お試しください。' ErrNotExistUser: '現在のユーザーは存在しません。変更してもう一度お試しください。'
ErrBanAction: '設定に失敗しました。現在の {{ .name }} サービスは利用できません。確認してもう一度お試しください。' ErrBanAction: '設定に失敗しました。現在の {{ .name }} サービスは利用できません。確認してもう一度お試しください。'
ErrClamdscanNotFound: 'clamdscan コマンドが検出されませんでした。インストールするにはドキュメントを参照してください。' ErrClamdscanNotFound: 'clamdscan コマンドが検出されませんでした。インストールするにはドキュメントを参照してください。'
@@ -321,11 +355,15 @@ SetSwap: 'Swap設定 {{ .path }} - {{ .size }}'
CreateSwap: 'Swapファイル作成' CreateSwap: 'Swapファイル作成'
FormatSwap: 'Swapファイルフォーマット' FormatSwap: 'Swapファイルフォーマット'
EnableSwap: 'Swapファイル有効化' EnableSwap: 'Swapファイル有効化'
# 改ざん防止
CleanTamperSetting: '履歴保護設定をクリーンアップ' CleanTamperSetting: '履歴保護設定をクリーンアップ'
SetTamperWithRules: 'ルールに従ってディレクトリ保護を開始' SetTamperWithRules: 'ルールに従ってディレクトリ保護を開始'
ProtectDir: 'ディレクトリを保護 {{ .name }}' ProtectDir: 'ディレクトリを保護 {{ .name }}'
IgnoreFile: 'ファイルを保護 {{ .name }}' IgnoreFile: 'ファイルを保護 {{ .name }}'
TamperSetSuccessful: '保護設定が完了し、以下のディレクトリの監視を開始します:' TamperSetSuccessful: '保護設定が完了し、以下のディレクトリの監視を開始します:'
# WAF
ErrScope: 'この構成の変更はサポートされていません' ErrScope: 'この構成の変更はサポートされていません'
ErrStateChange: '状態の変更に失敗しました' ErrStateChange: '状態の変更に失敗しました'
ErrRuleExist: 'ルールは既に存在します' ErrRuleExist: 'ルールは既に存在します'
@@ -380,6 +418,8 @@ OpenrestyNotFound: 'OpenResty がインストールされていません'
remoteIpIsNull: 'IPリストが空です' remoteIpIsNull: 'IPリストが空です'
OpenrestyVersionErr: 'OpenResty のバージョンが古すぎます。1.27.1.2-2-2-focal 以降にアップグレードしてください' OpenrestyVersionErr: 'OpenResty のバージョンが古すぎます。1.27.1.2-2-2-focal 以降にアップグレードしてください'
ErrFileTooLarge: 'ファイルが 1MB を超えているためアップロードできません' ErrFileTooLarge: 'ファイルが 1MB を超えているためアップロードできません'
# タスク
TaskStart: '{{ .name }} タスクが開始されました [START]' TaskStart: '{{ .name }} タスクが開始されました [START]'
TaskEnd: '{{ .name }} タスクが完了しました [COMPLETED]' TaskEnd: '{{ .name }} タスクが完了しました [COMPLETED]'
TaskFailed: '{{ .name }} タスクが失敗しました' TaskFailed: '{{ .name }} タスクが失敗しました'
@@ -440,10 +480,17 @@ CustomAppstore: 'カスタム アプリケーション ウェアハウス'
TaskExec: '実行' TaskExec: '実行'
TaskBatch: '一括操作' TaskBatch: '一括操作'
FileConvert: 'ファイル形式の変換' FileConvert: 'ファイル形式の変換'
# タスク - ClamAV
Clamscan: '{{ .name }} をスキャン' Clamscan: '{{ .name }} をスキャン'
TaskScan: 'スキャン' TaskScan: 'スキャン'
# タスク - AI
OllamaModelPull: 'Ollama モデル {{ .name }} をプルします' OllamaModelPull: 'Ollama モデル {{ .name }} をプルします'
OllamaModelSize: 'Ollama モデル {{ .name }} のサイズを取得します' OllamaModelSize: 'Ollama モデル {{ .name }} のサイズを取得します'
AIBenchmarkRun: "AIベンチマークを実行"
# タスク - スナップショット
Snapshot: 'スナップショット' Snapshot: 'スナップショット'
SnapDBInfo: '1Panel データベース情報を書き込む' SnapDBInfo: '1Panel データベース情報を書き込む'
SnapCopy: 'ファイルとディレクトリ {{ .name }} をコピーします' SnapCopy: 'ファイルとディレクトリ {{ .name }} をコピーします'
@@ -493,6 +540,8 @@ RecoverDaemonJson: 'コンテナ構成 daemon.json ファイルを復元する'
RecoverDBData: 'データベース データを回復する' RecoverDBData: 'データベース データを回復する'
RecoverBackups: 'ローカル バックアップ ディレクトリを復元する' RecoverBackups: 'ローカル バックアップ ディレクトリを復元する'
RecoverPanelData: 'リカバリデータディレクトリ' RecoverPanelData: 'リカバリデータディレクトリ'
# タスク - コンテナ
ContainerImagePull: 'コンテナ イメージ {{ .name }} をプルします' ContainerImagePull: 'コンテナ イメージ {{ .name }} をプルします'
ContainerRemoveOld: '元のコンテナ {{ .name }} を削除します' ContainerRemoveOld: '元のコンテナ {{ .name }} を削除します'
ContainerImageCheck: 'イメージが正常にプルされているかどうかを確認します' ContainerImageCheck: 'イメージが正常にプルされているかどうかを確認します'
@@ -501,6 +550,8 @@ ContainerRecreate: 'コンテナの更新に失敗しました。元のコンテ
ContainerCreate: '新しいコンテナ {{ .name }} を作成します' ContainerCreate: '新しいコンテナ {{ .name }} を作成します'
ContainerCreateFailed: 'コンテナの作成に失敗しました。失敗したコンテナを削除してください' ContainerCreateFailed: 'コンテナの作成に失敗しました。失敗したコンテナを削除してください'
ContainerStartCheck: 'コンテナが起動されているかどうかを確認します' ContainerStartCheck: 'コンテナが起動されているかどうかを確認します'
# タスク - イメージ
ImageBuild: 'イメージビルド' ImageBuild: 'イメージビルド'
ImagePull: '画像をプル' ImagePull: '画像をプル'
ImageRepoAuthFromDB: 'データベースからリポジトリ認証情報を取得する' ImageRepoAuthFromDB: 'データベースからリポジトリ認証情報を取得する'
@@ -508,6 +559,8 @@ ImagePush: '画像をプッシュ'
ImageRenameTag: '画像タグを変更する' ImageRenameTag: '画像タグを変更する'
ImageNewTag: '新しい画像タグ {{ .name }}' ImageNewTag: '新しい画像タグ {{ .name }}'
ComposeCreate: 'コンポジションを作成する' ComposeCreate: 'コンポジションを作成する'
# タスク - ウェブサイト
BackupNginxConfig: 'ウェブサイトの OpenResty 構成ファイルをバックアップする' BackupNginxConfig: 'ウェブサイトの OpenResty 構成ファイルをバックアップする'
CompressFileSuccess: 'ディレクトリを正常に圧縮しました。{{ .name }} に圧縮されました' CompressFileSuccess: 'ディレクトリを正常に圧縮しました。{{ .name }} に圧縮されました'
CompressDir: '圧縮ディレクトリ' CompressDir: '圧縮ディレクトリ'
@@ -518,8 +571,15 @@ websiteDir: 'ウェブサイトディレクトリ'
RecoverFailedStartRollBack: 'リカバリに失敗しました。ロールバックを開始します' RecoverFailedStartRollBack: 'リカバリに失敗しました。ロールバックを開始します'
AppBackupFileIncomplete: 'バックアップ ファイルが不完全で、app.json または app.tar.gz ファイルが不足しています' AppBackupFileIncomplete: 'バックアップ ファイルが不完全で、app.json または app.tar.gz ファイルが不足しています'
AppAttributesNotMatch: 'アプリケーションの種類または名前が一致しません' AppAttributesNotMatch: 'アプリケーションの種類または名前が一致しません'
# アラート
ErrAlertMethodNotSupported: 'このバージョンではこの通知方法は利用できません'
ErrAlertSync: 'アラーム情報の同期エラーです。確認してもう一度お試しください。' ErrAlertSync: 'アラーム情報の同期エラーです。確認してもう一度お試しください。'
# タスク - ランタイム
ErrInstallExtension: 'インストールタスクが進行中です、タスクが終了するのを待ってください' ErrInstallExtension: 'インストールタスクが進行中です、タスクが終了するのを待ってください'
# アラートメールテンプレート
PanelAlertTitle: 'パネルアラート通知' PanelAlertTitle: 'パネルアラート通知'
TestAlertTitle: 'テストメール - メール接続の確認' TestAlertTitle: 'テストメール - メール接続の確認'
TestAlert: 'これはテストメールです。メール送信設定が正しく構成されているかを確認します。' TestAlert: 'これはテストメールです。メール送信設定が正しく構成されているかを確認します。'
@@ -536,6 +596,8 @@ CommonAlert: 'あなたの {{ .node }}{{ .ip }} パネル、{{ .msg }}。詳細
NodeExceptionAlert: 'あなたの {{ .node }}{{ .ip }} パネル、{{ .num }} 個のノードに異常が発生しています。詳細はパネルにログインして' NodeExceptionAlert: 'あなたの {{ .node }}{{ .ip }} パネル、{{ .num }} 個のノードに異常が発生しています。詳細はパネルにログインして'
LicenseExceptionAlert: 'あなたの {{ .node }}{{ .ip }} パネル、{{ .num }} 個のライセンスに異常が発生しています。詳細はパネルにログインして' LicenseExceptionAlert: 'あなたの {{ .node }}{{ .ip }} パネル、{{ .num }} 個のライセンスに異常が発生しています。詳細はパネルにログインして'
SSHAndPanelLoginAlert: 'あなたの {{ .node }}{{ .ip }} パネル、{{ .loginIp }} からの {{ .name }} ログインに異常があります。詳細はパネルにログインして' SSHAndPanelLoginAlert: 'あなたの {{ .node }}{{ .ip }} パネル、{{ .loginIp }} からの {{ .name }} ログインに異常があります。詳細はパネルにログインして'
# ディスク
DeviceNotFound: 'デバイス {{ .name }} が見つかりません' DeviceNotFound: 'デバイス {{ .name }} が見つかりません'
DeviceIsMounted: 'デバイス {{ .name }} はマウントされています、まずアンマウントしてください' DeviceIsMounted: 'デバイス {{ .name }} はマウントされています、まずアンマウントしてください'
PartitionDiskErr: 'パーティションに失敗しました、{{ .err }}' PartitionDiskErr: 'パーティションに失敗しました、{{ .err }}'
@@ -543,9 +605,18 @@ FormatDiskErr: 'ディスクのフォーマットに失敗しました、{{ .err
MountDiskErr: 'ディスクのマウントに失敗しました、{{ .err }}' MountDiskErr: 'ディスクのマウントに失敗しました、{{ .err }}'
XfsNotFound: 'xfs ファイルシステムが検出されませんでした、最初に xfsprogs をインストールしてください' XfsNotFound: 'xfs ファイルシステムが検出されませんでした、最初に xfsprogs をインストールしてください'
# terminal # ターミナル
TerminalAIBlockedRiskyCommand: '危険なコマンドをブロックしました: {{ .command }}' TerminalAIBlockedRiskyCommand: '危険なコマンドをブロックしました: {{ .command }}'
TerminalAIThinking: 'AI が考えています...' TerminalAIThinking: 'AI が考えています...'
TerminalAIReadyToExecute: '思考が完了しました。Enter で実行してください(所要時間 {{ .duration }}、token: {{ .tokens }})' TerminalAIReadyToExecute: '思考が完了しました。Enter で実行してください(所要時間 {{ .duration }}、token: {{ .tokens }})'
TerminalAIRequestFailed: 'AI リクエストに失敗しました: {{ .err }}' TerminalAIRequestFailed: 'AI リクエストに失敗しました: {{ .err }}'
FileAISearchEmptyDir: 'このパス以下に一覧できるファイルまたはフォルダーがありません(またはすべて除外されました)。'
# AIゲートウェイ
ErrAIProxyServiceNotInstalled: '{{ .name }} サービスはインストールされていません'
ErrAIProxyModelAccountNotFound: 'モデルアカウント {{ .id }} が見つかりません'
ErrAIProxyModelMapRequired: 'この項目は必須です。'
ErrAIProxyModelMapInvalid: 'モデルマッピングは有効な JSON オブジェクトである必要があります: {{ .err }}'
ErrAIProxyModelMapEmpty: 'モデルマッピングは空にできません'
ErrAIProxyModelMapEmptyExternalModel: 'モデルマッピングに空のリクエストモデルがあります'
ErrAIProxyModelMapEmptyUpstreamModel: '{{ .model }} の上流モデルは空にできません'
AIProxyUserFallback: '削除済みユーザー (ID: {{ .id }})'
+92 -21
View File
@@ -1,29 +1,47 @@
# 기본 오류
ErrInvalidParams: '잘못된 요청: {{ .detail }}' ErrInvalidParams: '잘못된 요청: {{ .detail }}'
ErrTokenParse: '토큰 오류: {{ .detail }}' ErrTokenParse: '토큰 오류: {{ .detail }}'
ErrInitialPassword: '원래 비밀번호가 틀립니다' ErrInitialPassword: '원래 비밀번호가 틀립니다'
ErrInternalServer: '서버 오류: {{ .detail }}' ErrInternalServer: '서버 오류: {{ .detail }}'
ErrRecordExist: '레코드가 이미 있습니다'
ErrRecordNotFound: '레코드를 찾을 수 없습니다'
ErrStructTransform: '형 변환 실패: {{ .err }}'
ErrNotSupportType: '지원하지 않는 타입: {{ .name }}'
# 파일 AI
ErrFileAINotEnabled: '파일 관리에서 「AI 계정」으로 파일 AI 검색을 켜고 계정을 선택하세요.' ErrFileAINotEnabled: '파일 관리에서 「AI 계정」으로 파일 AI 검색을 켜고 계정을 선택하세요.'
ErrFileAISearchBadPattern: '검색 패턴이 잘못되었습니다(정규식 등): {{ .detail }}' ErrFileAISearchBadPattern: '검색 패턴이 잘못되었습니다(정규식 등): {{ .detail }}'
FileAISearchEmptyDir: '이 경로에 나열할 파일이나 디렉터리가 없습니다(또는 모두 필터링됨).'
# 원격 다운로드
ErrWgetRemoteFailed: '원격 다운로드 주소가 잘못되었거나 접근할 수 없습니다: {{ .detail }}' ErrWgetRemoteFailed: '원격 다운로드 주소가 잘못되었거나 접근할 수 없습니다: {{ .detail }}'
ErrWgetInvalidContentType: '원격 주소가 파일이 아닌 콘텐츠를 반환했습니다 (오류 페이지일 수 있음), {{ .detail }}' ErrWgetInvalidContentType: '원격 주소가 파일이 아닌 콘텐츠를 반환했습니다 (오류 페이지일 수 있음), {{ .detail }}'
ErrWgetProxyNotConfigured: '먼저 패널 설정에서 프록시 서버를 구성하세요' ErrWgetProxyNotConfigured: '먼저 패널 설정에서 프록시 서버를 구성하세요'
ErrWgetProxyInvalid: '프록시 서버 주소가 잘못되었습니다: {{ .detail }}' ErrWgetProxyInvalid: '프록시 서버 주소가 잘못되었습니다: {{ .detail }}'
ErrRecordExist: '레코드가 이미 있습니다'
ErrRecordNotFound: '레코드를 찾을 수 없습니다' # 로그인 및 보안
ErrStructTransform: '형 변환 실패: {{ .err }}'
ErrNotLogin: '로그인하지 않음: {{ .detail }}' ErrNotLogin: '로그인하지 않음: {{ .detail }}'
ErrPasswordExpired: '비밀번호 만료: {{ .detail }}' ErrPasswordExpired: '비밀번호 만료: {{ .detail }}'
ErrNotSupportType: '지원하지 않는 타입: {{ .name }}'
ErrAlertMethodNotSupported: '현재 버전에서는 이 알림 방식을 지원하지 않습니다' # 요청 및 API
ErrProxy: '요청 실패: {{ .detail }}' ErrProxy: '요청 실패: {{ .detail }}'
ErrApiConfigStatusInvalid: 'API 사용 중지: {{ .detail }}' ErrApiConfigStatusInvalid: 'API 사용 중지: {{ .detail }}'
ErrApiConfigKeyInvalid: 'API 키가 잘못됨: {{ .detail }}' ErrApiConfigKeyInvalid: 'API 키가 잘못됨: {{ .detail }}'
ErrApiConfigIPInvalid: 'IP 허용되지 않음: {{ .detail }}' ErrApiConfigIPInvalid: 'IP 허용되지 않음: {{ .detail }}'
ErrApiConfigDisable: 'API 접근 금지: {{ .detail }}' ErrApiConfigDisable: 'API 접근 금지: {{ .detail }}'
ErrApiConfigKeyTimeInvalid: '타임스탬프 오류: {{ .detail }}' ErrApiConfigKeyTimeInvalid: '타임스탬프 오류: {{ .detail }}'
ErrShutDown: '명령이 수동으로 중단되었습니다' ErrCreateHttpClient: '요청 {{ .err }}을(를) 생성하지 못했습니다.'
ErrHttpReqTimeOut: '요청 시간이 초과되었습니다 {{ .err }}'
ErrHttpReqFailed: '요청이 실패했습니다 {{ .err }}'
ErrNoSuchHost: '요청한 서버 {{ .err }}을 찾을 수 없습니다'
ErrHttpReqNotFound: '요청한 리소스 {{ .err }}을 찾을 수 없습니다.'
# 빠른 이동
ErrMinQuickJump: '퀵 액세스를 하나 이상 추가하세요' ErrMinQuickJump: '퀵 액세스를 하나 이상 추가하세요'
ErrMaxQuickJump: '퀵 액세스는 최대 4개' ErrMaxQuickJump: '퀵 액세스는 최대 4개'
# 공통
ErrShutDown: '명령이 수동으로 중단되었습니다'
ErrUsernameIsExist: '아이디가 이미 존재합니다' ErrUsernameIsExist: '아이디가 이미 존재합니다'
ErrNameIsExist: '이름이 이미 존재합니다' ErrNameIsExist: '이름이 이미 존재합니다'
ErrDemoEnvironment: '데모 환경에서는 불가' ErrDemoEnvironment: '데모 환경에서는 불가'
@@ -41,6 +59,8 @@ SystemRestart: '시스템 재시작으로 인해 작업이 중단되었습니다
ErrGroupIsDefault: '기본 그룹, 삭제할 수 없습니다' ErrGroupIsDefault: '기본 그룹, 삭제할 수 없습니다'
ErrGroupIsInWebsiteUse: '그룹이 다른 웹사이트에서 사용 중이므로 삭제할 수 없습니다.' ErrGroupIsInWebsiteUse: '그룹이 다른 웹사이트에서 사용 중이므로 삭제할 수 없습니다.'
Decrypt: '복호화' Decrypt: '복호화'
# 에이전트
ErrAgentAccountBound: '계정이 에이전트에 묶여 있습니다' ErrAgentAccountBound: '계정이 에이전트에 묶여 있습니다'
ErrTerminalAIAccountInUse: '이 모델 계정은 현재 터미널 AI에서 사용 중입니다. 터미널 AI 설정에서 다른 계정으로 변경하거나 터미널 AI를 비활성화한 뒤 다시 시도하세요.' ErrTerminalAIAccountInUse: '이 모델 계정은 현재 터미널 AI에서 사용 중입니다. 터미널 AI 설정에서 다른 계정으로 변경하거나 터미널 AI를 비활성화한 뒤 다시 시도하세요.'
ErrAgentAccountUnavailable: '계정 연결 불가: {{ .err }}' ErrAgentAccountUnavailable: '계정 연결 불가: {{ .err }}'
@@ -65,14 +85,8 @@ ErrAgentWebsiteInUse: '이 웹사이트는 이미 다른 에이전트에 연결
ErrAgentWebsiteUnbindUnsupported: '원클릭 배포 웹사이트는 수동으로 연결 해제할 수 없습니다' ErrAgentWebsiteUnbindUnsupported: '원클릭 배포 웹사이트는 수동으로 연결 해제할 수 없습니다'
ErrHermesPairingCodeUnavailable: 'Hermes에서 페어링 코드가 일시적으로 존재하지 않습니다. 네트워크 문제일 수 있으니 잠시 후 다시 시도해 주세요.' ErrHermesPairingCodeUnavailable: 'Hermes에서 페어링 코드가 일시적으로 존재하지 않습니다. 네트워크 문제일 수 있으니 잠시 후 다시 시도해 주세요.'
ErrHermesFeishuGroupAllowlistRequiresAllowlist: 'Feishu 그룹 정책이 허용 목록이면 DM 정책을 페어링 코드로 설정할 수 없습니다.' ErrHermesFeishuGroupAllowlistRequiresAllowlist: 'Feishu 그룹 정책이 허용 목록이면 DM 정책을 페어링 코드로 설정할 수 없습니다.'
ErrAIProxyServiceNotInstalled: '{{ .name }} 서비스가 설치되어 있지 않습니다'
ErrAIProxyModelAccountNotFound: '모델 계정 {{ .id }}을(를) 찾을 수 없습니다' # 백업 및 알림 설정
ErrAIProxyModelMapRequired: '이 필드는 필수입니다.'
ErrAIProxyModelMapInvalid: '모델 매핑은 유효한 JSON 객체여야 합니다: {{ .err }}'
ErrAIProxyModelMapEmpty: '모델 매핑은 비워 둘 수 없습니다'
ErrAIProxyModelMapEmptyExternalModel: '모델 매핑에 빈 요청 모델이 있습니다'
ErrAIProxyModelMapEmptyUpstreamModel: '{{ .model }}의 업스트림 모델은 비워 둘 수 없습니다'
AIProxyUserFallback: '사용자 {{ .id }}'
Localhost: '로컬 머신' Localhost: '로컬 머신'
ErrBackupInUsed: '백업 계정이 예약에 사용 중' ErrBackupInUsed: '백업 계정이 예약에 사용 중'
ErrBackupCheck: '연결 테스트 실패: {{ .err }}' ErrBackupCheck: '연결 테스트 실패: {{ .err }}'
@@ -80,6 +94,8 @@ ErrBackupLocalDelete: '로컬 백업은 삭제할 수 없습니다'
ErrBackupLocalCreate: '로컬 백업은 만들 수 없습니다' ErrBackupLocalCreate: '로컬 백업은 만들 수 없습니다'
ErrAlertConfigInUse: '경고 설정이 사용 중이므로 삭제할 수 없습니다' ErrAlertConfigInUse: '경고 설정이 사용 중이므로 삭제할 수 없습니다'
ErrAlertConfigPhoneExist: '전화번호가 이미 존재합니다' ErrAlertConfigPhoneExist: '전화번호가 이미 존재합니다'
# 앱
ErrPortInUsed: '{{ .detail }} 포트가 이미 사용 중입니다' ErrPortInUsed: '{{ .detail }} 포트가 이미 사용 중입니다'
ErrAppLimit: '설치된 애플리케이션 수가 한도를 초과했습니다' ErrAppLimit: '설치된 애플리케이션 수가 한도를 초과했습니다'
ErrNotInstall: '응용 프로그램이 설치되지 않았습니다' ErrNotInstall: '응용 프로그램이 설치되지 않았습니다'
@@ -97,16 +113,12 @@ ErrFileParseApp: '{{ .name }} 파일 구문 분석에 실패했습니다 {{ .err
ErrAppDirNull: '버전 폴더가 존재하지 않습니다' ErrAppDirNull: '버전 폴더가 존재하지 않습니다'
LocalAppErr: '애플리케이션 {{ .name }} 동기화에 실패했습니다 {{ .err }}' LocalAppErr: '애플리케이션 {{ .name }} 동기화에 실패했습니다 {{ .err }}'
ErrContainerName: '컨테이너 이름이 이미 존재합니다' ErrContainerName: '컨테이너 이름이 이미 존재합니다'
ErrCreateHttpClient: '요청 {{ .err }}을(를) 생성하지 못했습니다.'
ErrHttpReqTimeOut: '요청 시간이 초과되었습니다 {{ .err }}'
ErrHttpReqFailed: '요청이 실패했습니다 {{ .err }}'
ErrNoSuchHost: '요청한 서버 {{ .err }}을 찾을 수 없습니다'
ErrHttpReqNotFound: '요청한 리소스 {{ .err }}을 찾을 수 없습니다.'
ErrContainerNotFound: '{{ .name }} 컨테이너가 존재하지 않습니다' ErrContainerNotFound: '{{ .name }} 컨테이너가 존재하지 않습니다'
ErrContainerMsg: '{{ .name }} 컨테이너가 비정상입니다. 자세한 내용은 컨테이너 페이지의 로그를 확인하세요.' ErrContainerMsg: '{{ .name }} 컨테이너가 비정상입니다. 자세한 내용은 컨테이너 페이지의 로그를 확인하세요.'
ErrAppBackup: '{{ .name }} 애플리케이션 백업에 실패했습니다 {{ .err }}' ErrAppBackup: '{{ .name }} 애플리케이션 백업에 실패했습니다 {{ .err }}'
ErrVersionTooLow: '현재 1Panel 버전이 너무 낮아 App Store를 업데이트할 수 없습니다. 작동하시기 전에 버전을 업그레이드하세요.' ErrVersionTooLow: '현재 1Panel 버전이 너무 낮아 App Store를 업데이트할 수 없습니다. 작동하시기 전에 버전을 업그레이드하세요.'
ErrAppNameExist: '응용 프로그램 이름이 이미 존재합니다' ErrAppNameExist: '응용 프로그램 이름이 이미 존재합니다'
ErrAppInstallNameExist: '앱 설치 이름 {{ .name }} 이(가) 이미 존재합니다'
AppStoreIsSyncing: 'App Store가 동기화 중입니다. 나중에 다시 시도하세요.' AppStoreIsSyncing: 'App Store가 동기화 중입니다. 나중에 다시 시도하세요.'
ErrGetCompose: 'docker-compose.yml 파일을 가져오지 못했습니다 {{ .detail }}' ErrGetCompose: 'docker-compose.yml 파일을 가져오지 못했습니다 {{ .detail }}'
ErrAppWarn: '비정상적인 상태입니다. 로그를 확인해 주세요.' ErrAppWarn: '비정상적인 상태입니다. 로그를 확인해 주세요.'
@@ -131,6 +143,8 @@ ErrDockerFailed: 'Docker의 상태가 비정상입니다. 서비스 상태를
ErrDockerComposeCmdNotFound: 'Docker Compose 명령이 없습니다. 호스트 머신에 먼저 이 명령을 설치하세요' ErrDockerComposeCmdNotFound: 'Docker Compose 명령이 없습니다. 호스트 머신에 먼저 이 명령을 설치하세요'
UseExistImage: '이미지가 이미 존재하여 기존 이미지를 사용합니다' UseExistImage: '이미지가 이미 존재하여 기존 이미지를 사용합니다'
ErrDatabaseNotFound: '데이터베이스 {{ .name }} 이(가) 존재하지 않습니다' ErrDatabaseNotFound: '데이터베이스 {{ .name }} 이(가) 존재하지 않습니다'
# SSH
ExportIP: '로그인 IP' ExportIP: '로그인 IP'
ExportArea: '위치' ExportArea: '위치'
ExportPort: '포트' ExportPort: '포트'
@@ -138,6 +152,8 @@ ExportAuthMode: '로그인 방식'
ExportUser: '사용자' ExportUser: '사용자'
ExportStatus: '로그인 상태' ExportStatus: '로그인 상태'
ExportDate: '시간' ExportDate: '시간'
# 파일
ErrFileCanNotRead: '이 파일은 미리보기를 지원하지 않습니다' ErrFileCanNotRead: '이 파일은 미리보기를 지원하지 않습니다'
ErrSensitiveFileRead: '민감한 파일을 읽을 수 없습니다' ErrSensitiveFileRead: '민감한 파일을 읽을 수 없습니다'
ErrFileToLarge: '파일이 10M보다 커서 열 수 없습니다' ErrFileToLarge: '파일이 10M보다 커서 열 수 없습니다'
@@ -164,6 +180,8 @@ FileDropFailed: '파일 {{ .name }} 정리 실패: {{ .err }}'
FileDropSuccess: '파일 {{ .name }} 정리 성공, {{ .count }}개 파일 삭제, {{ .size }} 디스크 공간 확보' FileDropSuccess: '파일 {{ .name }} 정리 성공, {{ .count }}개 파일 삭제, {{ .size }} 디스크 공간 확보'
FileDropSum: '파일 정리 완료, 총 {{ .count }}개 파일 삭제, 총 {{ .size }} 디스크 공간 확보' FileDropSum: '파일 정리 완료, 총 {{ .count }}개 파일 삭제, 총 {{ .size }} 디스크 공간 확보'
ErrBadDecrypt: '압축 패키지 암호 해제 비밀번호 오류, 압축 해제 실패, 확인 후 다시 시도하세요' ErrBadDecrypt: '압축 패키지 암호 해제 비밀번호 오류, 압축 해제 실패, 확인 후 다시 시도하세요'
# 웹사이트
ErrAliasIsExist: '별칭이 이미 존재합니다' ErrAliasIsExist: '별칭이 이미 존재합니다'
ErrBackupMatch: '백업 파일이 현재 웹사이트 데이터 중 일부 {{ .detail }}와 일치하지 않습니다.' ErrBackupMatch: '백업 파일이 현재 웹사이트 데이터 중 일부 {{ .detail }}와 일치하지 않습니다.'
ErrBackupExist: '백업 파일에 있는 소스 데이터의 해당 부분이 존재하지 않습니다 {{ .detail }}' ErrBackupExist: '백업 파일에 있는 소스 데이터의 해당 부분이 존재하지 않습니다 {{ .detail }}'
@@ -193,6 +211,8 @@ delete: '삭제'
ErrDefaultWebsite: '기본 웹사이트가 이미 설정되었습니다. 설정하기 전에 취소하세요' ErrDefaultWebsite: '기본 웹사이트가 이미 설정되었습니다. 설정하기 전에 취소하세요'
SSL: '인증서' SSL: '인증서'
Set: '설정' Set: '설정'
# SSL 인증서
ErrSSLCannotDelete: '{{ .name }} 인증서는 웹사이트에서 사용 중이므로 삭제할 수 없습니다.' ErrSSLCannotDelete: '{{ .name }} 인증서는 웹사이트에서 사용 중이므로 삭제할 수 없습니다.'
ErrAccountCannotDelete: '계정이 인증서와 연결되어 있어 삭제할 수 없습니다.' ErrAccountCannotDelete: '계정이 인증서와 연결되어 있어 삭제할 수 없습니다.'
ErrSSLApply: '인증서 갱신이 성공했으나, openresty 재로드에 실패했습니다. 구성을 확인해 주세요' ErrSSLApply: '인증서 갱신이 성공했으나, openresty 재로드에 실패했습니다. 구성을 확인해 주세요'
@@ -227,6 +247,8 @@ ErrApplySSLCanNotDelete: '신청 중인 인증서 {{ .name }}는 삭제할 수
StartPushSSLToNode: '인증서를 노드로 푸시 시작' StartPushSSLToNode: '인증서를 노드로 푸시 시작'
PushSSLToNodeFailed: '노드로 인증서 푸시 실패: {{ .err }}' PushSSLToNodeFailed: '노드로 인증서 푸시 실패: {{ .err }}'
PushSSLToNodeSuccess: '노드로 인증서 푸시 성공' PushSSLToNodeSuccess: '노드로 인증서 푸시 성공'
# MySQL
ErrUserIsExist: '현재 사용자가 이미 존재합니다. 다시 입력하세요' ErrUserIsExist: '현재 사용자가 이미 존재합니다. 다시 입력하세요'
ErrDatabaseIsExist: '현재 데이터베이스가 이미 존재합니다. 다시 입력하세요' ErrDatabaseIsExist: '현재 데이터베이스가 이미 존재합니다. 다시 입력하세요'
ErrExecTimeOut: 'SQL 실행 시간이 초과되었습니다. 데이터베이스를 확인하십시오.' ErrExecTimeOut: 'SQL 실행 시간이 초과되었습니다. 데이터베이스를 확인하십시오.'
@@ -235,7 +257,11 @@ ErrLocalExist: '이름이 로컬 데이터베이스에 이미 존재합니다.
RemoteBackup: '원격 데이터베이스를 백업하려면 먼저 이미지 {{ .name }}을(를) 사용하여 로컬 컨테이너 데이터베이스 서비스를 시작해야 합니다. 잠시만 기다려 주세요...' RemoteBackup: '원격 데이터베이스를 백업하려면 먼저 이미지 {{ .name }}을(를) 사용하여 로컬 컨테이너 데이터베이스 서비스를 시작해야 합니다. 잠시만 기다려 주세요...'
RemoteRecover: '원격 데이터베이스를 복원하려면 먼저 이미지 {{ .name }}을(를) 사용하여 로컬 컨테이너 데이터베이스 서비스를 시작해야 합니다. 잠시만 기다려 주세요...' RemoteRecover: '원격 데이터베이스를 복원하려면 먼저 이미지 {{ .name }}을(를) 사용하여 로컬 컨테이너 데이터베이스 서비스를 시작해야 합니다. 잠시만 기다려 주세요...'
Arg: '인수' Arg: '인수'
# Redis
ErrTypeOfRedis: '복구 파일 유형이 현재 지속성 방법과 일치하지 않습니다. 수정하고 다시 시도하세요' ErrTypeOfRedis: '복구 파일 유형이 현재 지속성 방법과 일치하지 않습니다. 수정하고 다시 시도하세요'
# 컨테이너
ErrInUsed: '{{ .detail }}(이)가 사용 중이어서 삭제할 수 없습니다' ErrInUsed: '{{ .detail }}(이)가 사용 중이어서 삭제할 수 없습니다'
ErrObjectInUsed: '이 객체는 사용 중이어서 삭제할 수 없습니다' ErrObjectInUsed: '이 객체는 사용 중이어서 삭제할 수 없습니다'
ErrObjectBeDependent: '이 이미지는 다른 이미지에 의존되어 있어 삭제할 수 없습니다' ErrObjectBeDependent: '이 이미지는 다른 이미지에 의존되어 있어 삭제할 수 없습니다'
@@ -277,6 +303,8 @@ ComposeRecoverFiles: 'Compose 파일 복원'
ComposeRecoverContainers: 'Compose 컨테이너 복원' ComposeRecoverContainers: 'Compose 컨테이너 복원'
ComposeRecoverRecord: 'Compose 기록 저장' ComposeRecoverRecord: 'Compose 기록 저장'
ComposeRecoverCleanup: 'Compose 복원 작업 공간 정리' ComposeRecoverCleanup: 'Compose 복원 작업 공간 정리'
# 런타임
ErrFileNotExist: '{{ .detail }} 파일이 존재하지 않습니다 소스 파일의 무결성을 확인하세요' ErrFileNotExist: '{{ .detail }} 파일이 존재하지 않습니다 소스 파일의 무결성을 확인하세요'
ErrImageBuildErr: '이미지 빌드 실패' ErrImageBuildErr: '이미지 빌드 실패'
ErrImageExist: '이미지가 이미 존재합니다 이미지 이름을 수정하세요.' ErrImageExist: '이미지가 이미 존재합니다 이미지 이름을 수정하세요.'
@@ -289,12 +317,16 @@ ErrNodeModulesNotFound: 'node_modules 폴더가 없습니다 런타임 환경을
ErrContainerNameIsNull: '컨테이너 이름이 존재하지 않습니다' ErrContainerNameIsNull: '컨테이너 이름이 존재하지 않습니다'
ErrPHPPortIsDefault: '9000 포트는 기본 포트입니다. 수정 후 다시 시도하세요' ErrPHPPortIsDefault: '9000 포트는 기본 포트입니다. 수정 후 다시 시도하세요'
ErrPHPRuntimePortFailed: '포트 {{ .name }} 는 현재 런타임 환경에서 이미 사용 중입니다. 수정 후 다시 시도하세요' ErrPHPRuntimePortFailed: '포트 {{ .name }} 는 현재 런타임 환경에서 이미 사용 중입니다. 수정 후 다시 시도하세요'
# 도구
ErrConfigNotFound: '구성 파일이 존재하지 않습니다' ErrConfigNotFound: '구성 파일이 존재하지 않습니다'
ErrConfigParse: '구성 파일 형식이 올바르지 않습니다' ErrConfigParse: '구성 파일 형식이 올바르지 않습니다'
ErrConfigIsNull: '구성 파일은 비어 있을 수 없습니다' ErrConfigIsNull: '구성 파일은 비어 있을 수 없습니다'
ErrConfigDirNotFound: '실행 디렉토리가 존재하지 않습니다' ErrConfigDirNotFound: '실행 디렉토리가 존재하지 않습니다'
ErrConfigAlreadyExist: '같은 이름의 구성 파일이 이미 존재합니다' ErrConfigAlreadyExist: '같은 이름의 구성 파일이 이미 존재합니다'
ErrUserFindErr: '사용자 {{ .name }} 검색에 실패했습니다 {{ .err }}' ErrUserFindErr: '사용자 {{ .name }} 검색에 실패했습니다 {{ .err }}'
# 예약 작업
CutWebsiteLogSuccess: '{{ .name }} 웹사이트 로그가 성공적으로 잘렸습니다. 백업 경로 {{ .path }}' CutWebsiteLogSuccess: '{{ .name }} 웹사이트 로그가 성공적으로 잘렸습니다. 백업 경로 {{ .path }}'
HandleShell: '스크립트 {{ .name }} 실행' HandleShell: '스크립트 {{ .name }} 실행'
HandleCurl: 'URL {{ .name }} 접근' HandleCurl: 'URL {{ .name }} 접근'
@@ -313,6 +345,8 @@ NoSuchResource: '데이터베이스에서 백업 내용을 찾을 수 없어 건
CleanLog: '로그 정리' CleanLog: '로그 정리'
CleanLogByName: '{{ .name }} 로그 정리' CleanLogByName: '{{ .name }} 로그 정리'
WafIpGroupNotFound: 'WAF IP 그룹을 찾을 수 없습니다. [고급 기능 - WAF - 블랙/화이트 목록 - IP 그룹]으로 이동하여 원격 다운로드 방식으로 IP 그룹을 추가하십시오.' WafIpGroupNotFound: 'WAF IP 그룹을 찾을 수 없습니다. [고급 기능 - WAF - 블랙/화이트 목록 - IP 그룹]으로 이동하여 원격 다운로드 방식으로 IP 그룹을 추가하십시오.'
# 도구 상자
ErrNotExistUser: '현재 사용자가 존재하지 않습니다. 수정한 후 다시 시도하세요' ErrNotExistUser: '현재 사용자가 존재하지 않습니다. 수정한 후 다시 시도하세요'
ErrBanAction: '설정에 실패했습니다. 현재 {{ .name }} 서비스를 사용할 수 없습니다. 확인하고 다시 시도하세요' ErrBanAction: '설정에 실패했습니다. 현재 {{ .name }} 서비스를 사용할 수 없습니다. 확인하고 다시 시도하세요'
ErrClamdscanNotFound: 'clamdscan 명령이 감지되지 않았습니다. 설명서를 참조하여 설치하세요' ErrClamdscanNotFound: 'clamdscan 명령이 감지되지 않았습니다. 설명서를 참조하여 설치하세요'
@@ -321,11 +355,15 @@ SetSwap: 'Swap 설정 {{ .path }} - {{ .size }}'
CreateSwap: 'Swap 파일 생성' CreateSwap: 'Swap 파일 생성'
FormatSwap: 'Swap 파일 포맷' FormatSwap: 'Swap 파일 포맷'
EnableSwap: 'Swap 활성화' EnableSwap: 'Swap 활성화'
# 변조 방지
CleanTamperSetting: '히스토리 보호 설정 정리' CleanTamperSetting: '히스토리 보호 설정 정리'
SetTamperWithRules: '규칙에 따라 디렉토리 보호 시작' SetTamperWithRules: '규칙에 따라 디렉토리 보호 시작'
ProtectDir: '디렉토리 보호 {{ .name }}' ProtectDir: '디렉토리 보호 {{ .name }}'
IgnoreFile: '파일 보호 {{ .name }}' IgnoreFile: '파일 보호 {{ .name }}'
TamperSetSuccessful: '보호 설정 완료, 다음 디렉토리 모니터링 시작:' TamperSetSuccessful: '보호 설정 완료, 다음 디렉토리 모니터링 시작:'
# WAF
ErrScope: '이 구성을 수정하는 것은 지원되지 않습니다' ErrScope: '이 구성을 수정하는 것은 지원되지 않습니다'
ErrStateChange: '상태 변경에 실패했습니다' ErrStateChange: '상태 변경에 실패했습니다'
ErrRuleExist: '규칙이 이미 존재합니다' ErrRuleExist: '규칙이 이미 존재합니다'
@@ -380,6 +418,8 @@ OpenrestyNotFound: 'OpenResty가 설치되어 있지 않습니다'
remoteIpIsNull: 'IP 목록이 비어 있습니다' remoteIpIsNull: 'IP 목록이 비어 있습니다'
OpenrestyVersionErr: 'OpenResty 버전이 너무 낮습니다. 1.27.1.2-2-2-focal 이상으로 업그레이드하세요' OpenrestyVersionErr: 'OpenResty 버전이 너무 낮습니다. 1.27.1.2-2-2-focal 이상으로 업그레이드하세요'
ErrFileTooLarge: '파일이 1MB를 초과하여 업로드할 수 없습니다' ErrFileTooLarge: '파일이 1MB를 초과하여 업로드할 수 없습니다'
# 작업
TaskStart: '[START] {{ .name }} 작업이 시작됩니다.' TaskStart: '[START] {{ .name }} 작업이 시작됩니다.'
TaskEnd: '{{ .name }} 작업이 완료되었습니다 [완료]' TaskEnd: '{{ .name }} 작업이 완료되었습니다 [완료]'
TaskFailed: '{{ .name }} 작업이 실패했습니다' TaskFailed: '{{ .name }} 작업이 실패했습니다'
@@ -440,10 +480,17 @@ CustomAppstore: '사용자 정의 애플리케이션 웨어하우스'
TaskExec: '실행' TaskExec: '실행'
TaskBatch: '일괄 작업' TaskBatch: '일괄 작업'
FileConvert: '파일 형식 변환' FileConvert: '파일 형식 변환'
# 작업 - ClamAV
Clamscan: '{{ .name }} 스캔' Clamscan: '{{ .name }} 스캔'
TaskScan: '스캔' TaskScan: '스캔'
# 작업 - AI
OllamaModelPull: 'Ollama 모델 {{ .name }}을(를) 끌어오세요' OllamaModelPull: 'Ollama 모델 {{ .name }}을(를) 끌어오세요'
OllamaModelSize: 'Ollama 모델 {{ .name }}의 크기를 가져옵니다' OllamaModelSize: 'Ollama 모델 {{ .name }}의 크기를 가져옵니다'
AIBenchmarkRun: "AI 벤치마크 실행"
# 작업 - 스냅샷
Snapshot: '스냅샷' Snapshot: '스냅샷'
SnapDBInfo: '1Panel 데이터베이스 정보 쓰기' SnapDBInfo: '1Panel 데이터베이스 정보 쓰기'
SnapCopy: '파일 및 디렉토리 {{ .name }} 복사' SnapCopy: '파일 및 디렉토리 {{ .name }} 복사'
@@ -493,6 +540,8 @@ RecoverDaemonJson: '컨테이너 구성 daemon.json 파일 복원'
RecoverDBData: '데이터베이스 데이터 복구' RecoverDBData: '데이터베이스 데이터 복구'
RecoverBackups: '로컬 백업 디렉토리 복원' RecoverBackups: '로컬 백업 디렉토리 복원'
RecoverPanelData: '복구 데이터 디렉토리' RecoverPanelData: '복구 데이터 디렉토리'
# 작업 - 컨테이너
ContainerImagePull: '컨테이너 이미지 {{ .name }} 가져오기' ContainerImagePull: '컨테이너 이미지 {{ .name }} 가져오기'
ContainerRemoveOld: '원래 컨테이너 {{ .name }} 제거' ContainerRemoveOld: '원래 컨테이너 {{ .name }} 제거'
ContainerImageCheck: '이미지가 정상적으로 당겨졌는지 확인' ContainerImageCheck: '이미지가 정상적으로 당겨졌는지 확인'
@@ -501,6 +550,8 @@ ContainerRecreate: '컨테이너 업데이트에 실패했습니다. 이제 원
ContainerCreate: '새로운 컨테이너 {{ .name }}를 만듭니다' ContainerCreate: '새로운 컨테이너 {{ .name }}를 만듭니다'
ContainerCreateFailed: '컨테이너 생성에 실패했습니다. 실패한 컨테이너를 삭제하세요' ContainerCreateFailed: '컨테이너 생성에 실패했습니다. 실패한 컨테이너를 삭제하세요'
ContainerStartCheck: '컨테이너가 시작되었는지 확인' ContainerStartCheck: '컨테이너가 시작되었는지 확인'
# 작업 - 이미지
ImageBuild: '이미지 빌드' ImageBuild: '이미지 빌드'
ImagePull: '이미지 가져오기' ImagePull: '이미지 가져오기'
ImageRepoAuthFromDB: '데이터베이스에서 저장소 인증 정보 가져오기' ImageRepoAuthFromDB: '데이터베이스에서 저장소 인증 정보 가져오기'
@@ -508,6 +559,8 @@ ImagePush: '이미지 푸시'
ImageRenameTag: '이미지 태그 수정' ImageRenameTag: '이미지 태그 수정'
ImageNewTag: '새로운 이미지 태그 {{ .name }}' ImageNewTag: '새로운 이미지 태그 {{ .name }}'
ComposeCreate: '작곡 만들기' ComposeCreate: '작곡 만들기'
# 작업 - 웹사이트
BackupNginxConfig: '웹사이트 OpenResty 구성 파일 백업' BackupNginxConfig: '웹사이트 OpenResty 구성 파일 백업'
CompressFileSuccess: '디렉토리 압축이 성공했습니다. {{ .name }}으로 압축되었습니다.' CompressFileSuccess: '디렉토리 압축이 성공했습니다. {{ .name }}으로 압축되었습니다.'
CompressDir: '압축 디렉토리' CompressDir: '압축 디렉토리'
@@ -518,8 +571,15 @@ websiteDir: '웹사이트 디렉토리'
RecoverFailedStartRollBack: '복구 실패, 롤백 시작' RecoverFailedStartRollBack: '복구 실패, 롤백 시작'
AppBackupFileIncomplete: '백업 파일이 불완전하며 app.json 또는 app.tar.gz 파일이 없습니다.' AppBackupFileIncomplete: '백업 파일이 불완전하며 app.json 또는 app.tar.gz 파일이 없습니다.'
AppAttributesNotMatch: '애플리케이션 유형 또는 이름이 일치하지 않습니다' AppAttributesNotMatch: '애플리케이션 유형 또는 이름이 일치하지 않습니다'
# 알림
ErrAlertMethodNotSupported: '현재 버전에서는 이 알림 방식을 지원하지 않습니다'
ErrAlertSync: '알람 정보 동기화 오류입니다. 확인하고 다시 시도하세요' ErrAlertSync: '알람 정보 동기화 오류입니다. 확인하고 다시 시도하세요'
# 작업 - 런타임
ErrInstallExtension: '이미 설치 작업이 진행 중입니다. 작업이 완료될 때까지 기다려 주세요.' ErrInstallExtension: '이미 설치 작업이 진행 중입니다. 작업이 완료될 때까지 기다려 주세요.'
# 알림 메일 템플릿
PanelAlertTitle: '패널 알림 통지' PanelAlertTitle: '패널 알림 통지'
TestAlertTitle: '테스트 이메일 - 이메일 연결 확인' TestAlertTitle: '테스트 이메일 - 이메일 연결 확인'
TestAlert: '이것은 테스트 이메일이며 이메일 발송 설정이 올바른지 확인합니다.' TestAlert: '이것은 테스트 이메일이며 이메일 발송 설정이 올바른지 확인합니다.'
@@ -536,6 +596,8 @@ CommonAlert: '귀하의 {{ .node }}{{ .ip }} 패널, {{ .msg }}。자세한 내
NodeExceptionAlert: '귀하의 {{ .node }}{{ .ip }} 패널, {{ .num }}개의 노드에 이상이 있습니다. 자세한 내용은 패널에 로그인하십시오.' NodeExceptionAlert: '귀하의 {{ .node }}{{ .ip }} 패널, {{ .num }}개의 노드에 이상이 있습니다. 자세한 내용은 패널에 로그인하십시오.'
LicenseExceptionAlert: '귀하의 {{ .node }}{{ .ip }} 패널, {{ .num }}개의 라이센스에 이상이 있습니다. 자세한 내용은 패널에 로그인하십시오.' LicenseExceptionAlert: '귀하의 {{ .node }}{{ .ip }} 패널, {{ .num }}개의 라이센스에 이상이 있습니다. 자세한 내용은 패널에 로그인하십시오.'
SSHAndPanelLoginAlert: '귀하의 {{ .node }}{{ .ip }} 패널, {{ .loginIp }}에서의 {{ .name }} 로그인에 이상이 있습니다. 자세한 내용은 패널에 로그인하십시오.' SSHAndPanelLoginAlert: '귀하의 {{ .node }}{{ .ip }} 패널, {{ .loginIp }}에서의 {{ .name }} 로그인에 이상이 있습니다. 자세한 내용은 패널에 로그인하십시오.'
# 디스크
DeviceNotFound: '장치 {{ .name }} 을(를) 찾을 수 없습니다' DeviceNotFound: '장치 {{ .name }} 을(를) 찾을 수 없습니다'
DeviceIsMounted: '장치 {{ .name }} 이(가) 마운트되었습니다, 먼저 마운트 해제하세요' DeviceIsMounted: '장치 {{ .name }} 이(가) 마운트되었습니다, 먼저 마운트 해제하세요'
PartitionDiskErr: '파티션 분할에 실패했습니다, {{ .err }}' PartitionDiskErr: '파티션 분할에 실패했습니다, {{ .err }}'
@@ -543,9 +605,18 @@ FormatDiskErr: '디스크 포맷에 실패했습니다, {{ .err }}'
MountDiskErr: '디스크 마운트에 실패했습니다, {{ .err }}' MountDiskErr: '디스크 마운트에 실패했습니다, {{ .err }}'
XfsNotFound: 'xfs 파일 시스템이 감지되지 않았습니다, 먼저 xfsprogs 를 설치하세요' XfsNotFound: 'xfs 파일 시스템이 감지되지 않았습니다, 먼저 xfsprogs 를 설치하세요'
# terminal # 터미널
TerminalAIBlockedRiskyCommand: '위험한 명령이 차단되었습니다: {{ .command }}' TerminalAIBlockedRiskyCommand: '위험한 명령이 차단되었습니다: {{ .command }}'
TerminalAIThinking: 'AI가 생각 중입니다...' TerminalAIThinking: 'AI가 생각 중입니다...'
TerminalAIReadyToExecute: '생각이 완료되었습니다. Enter를 눌러 실행하세요 (소요 시간 {{ .duration }}, token: {{ .tokens }})' TerminalAIReadyToExecute: '생각이 완료되었습니다. Enter를 눌러 실행하세요 (소요 시간 {{ .duration }}, token: {{ .tokens }})'
TerminalAIRequestFailed: 'AI 요청 실패: {{ .err }}' TerminalAIRequestFailed: 'AI 요청 실패: {{ .err }}'
FileAISearchEmptyDir: '이 경로에 나열할 파일이나 디렉터리가 없습니다(또는 모두 필터링됨).'
# AI 게이트웨이
ErrAIProxyServiceNotInstalled: '{{ .name }} 서비스가 설치되어 있지 않습니다'
ErrAIProxyModelAccountNotFound: '모델 계정 {{ .id }}을(를) 찾을 수 없습니다'
ErrAIProxyModelMapRequired: '이 필드는 필수입니다.'
ErrAIProxyModelMapInvalid: '모델 매핑은 유효한 JSON 객체여야 합니다: {{ .err }}'
ErrAIProxyModelMapEmpty: '모델 매핑은 비워 둘 수 없습니다'
ErrAIProxyModelMapEmptyExternalModel: '모델 매핑에 빈 요청 모델이 있습니다'
ErrAIProxyModelMapEmptyUpstreamModel: '{{ .model }}의 업스트림 모델은 비워 둘 수 없습니다'
AIProxyUserFallback: '삭제된 사용자 (ID: {{ .id }})'
+91 -20
View File
@@ -1,29 +1,47 @@
# ralat asas
ErrInvalidParams: 'Permintaan tidak sah: {{ .detail }}' ErrInvalidParams: 'Permintaan tidak sah: {{ .detail }}'
ErrTokenParse: 'Token tidak sah: {{ .detail }}' ErrTokenParse: 'Token tidak sah: {{ .detail }}'
ErrInitialPassword: 'Kata laluan asal salah' ErrInitialPassword: 'Kata laluan asal salah'
ErrInternalServer: 'Ralat pelayan: {{ .detail }}' ErrInternalServer: 'Ralat pelayan: {{ .detail }}'
ErrRecordExist: 'Rekod sudah wujud'
ErrRecordNotFound: 'Rekod tidak ditemui'
ErrStructTransform: 'Ralat penukaran: {{ .err }}'
ErrNotSupportType: 'Jenis tidak disokong: {{ .name }}'
# AI fail
ErrFileAINotEnabled: 'Carian AI fail dimatikan atau tiada akaun. Dalam Pengurusan Fail, gunakan Akaun AI, aktifkan dan pilih akaun.' ErrFileAINotEnabled: 'Carian AI fail dimatikan atau tiada akaun. Dalam Pengurusan Fail, gunakan Akaun AI, aktifkan dan pilih akaun.'
ErrFileAISearchBadPattern: 'Corak carian tidak sah (regex dsb.): {{ .detail }}' ErrFileAISearchBadPattern: 'Corak carian tidak sah (regex dsb.): {{ .detail }}'
FileAISearchEmptyDir: 'Tiada fail atau direktori di bawah laluan ini (atau semua ditapis).'
# muat turun jauh
ErrWgetRemoteFailed: 'Muat turun jauh gagal atau URL tidak boleh diakses: {{ .detail }}' ErrWgetRemoteFailed: 'Muat turun jauh gagal atau URL tidak boleh diakses: {{ .detail }}'
ErrWgetInvalidContentType: 'URL jauh tidak mengembalikan fail (mungkin halaman ralat), {{ .detail }}' ErrWgetInvalidContentType: 'URL jauh tidak mengembalikan fail (mungkin halaman ralat), {{ .detail }}'
ErrWgetProxyNotConfigured: 'Sila konfigurasikan pelayan proksi dalam tetapan panel dahulu' ErrWgetProxyNotConfigured: 'Sila konfigurasikan pelayan proksi dalam tetapan panel dahulu'
ErrWgetProxyInvalid: 'Alamat pelayan proksi tidak sah: {{ .detail }}' ErrWgetProxyInvalid: 'Alamat pelayan proksi tidak sah: {{ .detail }}'
ErrRecordExist: 'Rekod sudah wujud'
ErrRecordNotFound: 'Rekod tidak ditemui' # log masuk dan keselamatan
ErrStructTransform: 'Ralat penukaran: {{ .err }}'
ErrNotLogin: 'Belum log masuk: {{ .detail }}' ErrNotLogin: 'Belum log masuk: {{ .detail }}'
ErrPasswordExpired: 'Kata laluan tamat: {{ .detail }}' ErrPasswordExpired: 'Kata laluan tamat: {{ .detail }}'
ErrNotSupportType: 'Jenis tidak disokong: {{ .name }}'
ErrAlertMethodNotSupported: 'Versi ini tidak menyokong kaedah amaran ini' # permintaan dan API
ErrProxy: 'Permintaan gagal: {{ .detail }}' ErrProxy: 'Permintaan gagal: {{ .detail }}'
ErrApiConfigStatusInvalid: 'API dilumpuhkan: {{ .detail }}' ErrApiConfigStatusInvalid: 'API dilumpuhkan: {{ .detail }}'
ErrApiConfigKeyInvalid: 'Kunci API tidak sah: {{ .detail }}' ErrApiConfigKeyInvalid: 'Kunci API tidak sah: {{ .detail }}'
ErrApiConfigIPInvalid: 'IP tidak dibenarkan: {{ .detail }}' ErrApiConfigIPInvalid: 'IP tidak dibenarkan: {{ .detail }}'
ErrApiConfigDisable: 'API tidak dibenarkan: {{ .detail }}' ErrApiConfigDisable: 'API tidak dibenarkan: {{ .detail }}'
ErrApiConfigKeyTimeInvalid: 'Cap masa tidak sah: {{ .detail }}' ErrApiConfigKeyTimeInvalid: 'Cap masa tidak sah: {{ .detail }}'
ErrShutDown: 'Arahan diberhentikan manual' ErrCreateHttpClient: 'Gagal membuat permintaan {{ .err }}'
ErrHttpReqTimeOut: 'Permintaan tamat masa {{ .err }}'
ErrHttpReqFailed: 'Permintaan gagal {{ .err }}'
ErrNoSuchHost: 'Tidak dapat mencari pelayan yang diminta {{ .err }}'
ErrHttpReqNotFound: 'Sumber yang diminta {{ .err }} tidak dapat ditemui'
# lompat pantas
ErrMinQuickJump: 'Tambah sekurang-kurangnya satu pintasan pantas' ErrMinQuickJump: 'Tambah sekurang-kurangnya satu pintasan pantas'
ErrMaxQuickJump: 'Maksimum 4 pintasan pantas' ErrMaxQuickJump: 'Maksimum 4 pintasan pantas'
# umum
ErrShutDown: 'Arahan diberhentikan manual'
ErrUsernameIsExist: 'Nama pengguna sudah wujud' ErrUsernameIsExist: 'Nama pengguna sudah wujud'
ErrNameIsExist: 'Nama sudah wujud' ErrNameIsExist: 'Nama sudah wujud'
ErrDemoEnvironment: 'Tidak tersedia dalam demo' ErrDemoEnvironment: 'Tidak tersedia dalam demo'
@@ -41,6 +59,8 @@ SystemRestart: 'Tugas terganggu kerana sistem mula semula'
ErrGroupIsDefault: 'Kumpulan lalai, tidak boleh dipadamkan' ErrGroupIsDefault: 'Kumpulan lalai, tidak boleh dipadamkan'
ErrGroupIsInWebsiteUse: 'Kumpulan sedang digunakan oleh tapak web lain dan tidak boleh dipadamkan.' ErrGroupIsInWebsiteUse: 'Kumpulan sedang digunakan oleh tapak web lain dan tidak boleh dipadamkan.'
Decrypt: 'Dekripsi' Decrypt: 'Dekripsi'
# ejen
ErrAgentAccountBound: 'Akaun terikat kepada ejen' ErrAgentAccountBound: 'Akaun terikat kepada ejen'
ErrTerminalAIAccountInUse: 'Akaun model ini sedang digunakan oleh Terminal AI. Tukar akaun dalam tetapan Terminal AI atau nyahaktifkan Terminal AI, kemudian cuba lagi.' ErrTerminalAIAccountInUse: 'Akaun model ini sedang digunakan oleh Terminal AI. Tukar akaun dalam tetapan Terminal AI atau nyahaktifkan Terminal AI, kemudian cuba lagi.'
ErrAgentAccountUnavailable: 'Sambungan akaun tidak tersedia: {{ .err }}' ErrAgentAccountUnavailable: 'Sambungan akaun tidak tersedia: {{ .err }}'
@@ -65,14 +85,8 @@ ErrAgentWebsiteInUse: 'Laman web ini sudah dipautkan ke ejen lain'
ErrAgentWebsiteUnbindUnsupported: 'Laman web one-click deployment tidak menyokong nyahikat manual' ErrAgentWebsiteUnbindUnsupported: 'Laman web one-click deployment tidak menyokong nyahikat manual'
ErrHermesPairingCodeUnavailable: 'Kod pasangan buat sementara waktu tidak wujud dalam Hermes, mungkin disebabkan masalah rangkaian. Sila cuba lagi sebentar nanti.' ErrHermesPairingCodeUnavailable: 'Kod pasangan buat sementara waktu tidak wujud dalam Hermes, mungkin disebabkan masalah rangkaian. Sila cuba lagi sebentar nanti.'
ErrHermesFeishuGroupAllowlistRequiresAllowlist: 'Apabila dasar kumpulan Feishu ialah senarai benarkan, dasar DM tidak boleh menggunakan kod pasangan.' ErrHermesFeishuGroupAllowlistRequiresAllowlist: 'Apabila dasar kumpulan Feishu ialah senarai benarkan, dasar DM tidak boleh menggunakan kod pasangan.'
ErrAIProxyServiceNotInstalled: 'Perkhidmatan {{ .name }} belum dipasang'
ErrAIProxyModelAccountNotFound: 'Akaun model {{ .id }} tidak ditemui' # sandaran dan tetapan amaran
ErrAIProxyModelMapRequired: 'Medan ini wajib diisi.'
ErrAIProxyModelMapInvalid: 'Pemetaan model mestilah objek JSON yang sah: {{ .err }}'
ErrAIProxyModelMapEmpty: 'Pemetaan model tidak boleh kosong'
ErrAIProxyModelMapEmptyExternalModel: 'Pemetaan model mengandungi model permintaan kosong'
ErrAIProxyModelMapEmptyUpstreamModel: 'Model upstream untuk {{ .model }} tidak boleh kosong'
AIProxyUserFallback: 'Pengguna {{ .id }}'
Localhost: 'Mesin Tempatan' Localhost: 'Mesin Tempatan'
ErrBackupInUsed: 'Akaun sandaran sedang digunakan oleh tugas' ErrBackupInUsed: 'Akaun sandaran sedang digunakan oleh tugas'
ErrBackupCheck: 'Ujian sambungan gagal: {{ .err }}' ErrBackupCheck: 'Ujian sambungan gagal: {{ .err }}'
@@ -80,6 +94,8 @@ ErrBackupLocalDelete: 'Tidak boleh padam sandaran tempatan'
ErrBackupLocalCreate: 'Tidak boleh buat sandaran tempatan' ErrBackupLocalCreate: 'Tidak boleh buat sandaran tempatan'
ErrAlertConfigInUse: 'Konfigurasi amaran sedang digunakan dan tidak boleh dipadamkan' ErrAlertConfigInUse: 'Konfigurasi amaran sedang digunakan dan tidak boleh dipadamkan'
ErrAlertConfigPhoneExist: 'Nombor telefon sudah wujud' ErrAlertConfigPhoneExist: 'Nombor telefon sudah wujud'
# aplikasi
ErrPortInUsed: 'Port {{ .detail }} sudah diduduki' ErrPortInUsed: 'Port {{ .detail }} sudah diduduki'
ErrAppLimit: 'Bilangan aplikasi yang dipasang telah melebihi had' ErrAppLimit: 'Bilangan aplikasi yang dipasang telah melebihi had'
ErrNotInstall: 'Aplikasi tidak dipasang' ErrNotInstall: 'Aplikasi tidak dipasang'
@@ -97,16 +113,12 @@ ErrFileParseApp: '{{ .name }} penghuraian fail gagal {{ .err }}'
ErrAppDirNull: 'Folder versi tidak wujud' ErrAppDirNull: 'Folder versi tidak wujud'
LocalAppErr: 'Penyegerakan {{ .name }} aplikasi gagal {{ .err }}' LocalAppErr: 'Penyegerakan {{ .name }} aplikasi gagal {{ .err }}'
ErrContainerName: 'Nama kontena sudah wujud' ErrContainerName: 'Nama kontena sudah wujud'
ErrCreateHttpClient: 'Gagal membuat permintaan {{ .err }}'
ErrHttpReqTimeOut: 'Permintaan tamat masa {{ .err }}'
ErrHttpReqFailed: 'Permintaan gagal {{ .err }}'
ErrNoSuchHost: 'Tidak dapat mencari pelayan yang diminta {{ .err }}'
ErrHttpReqNotFound: 'Sumber yang diminta {{ .err }} tidak dapat ditemui'
ErrContainerNotFound: 'Bekas {{ .name }} tidak wujud' ErrContainerNotFound: 'Bekas {{ .name }} tidak wujud'
ErrContainerMsg: 'Bekas ''{{ .name }} adalah tidak normal. Sila semak log pada halaman kontena untuk butiran''' ErrContainerMsg: 'Bekas ''{{ .name }} adalah tidak normal. Sila semak log pada halaman kontena untuk butiran'''
ErrAppBackup: '{{ .name }} sandaran aplikasi gagal {{ .err }}' ErrAppBackup: '{{ .name }} sandaran aplikasi gagal {{ .err }}'
ErrVersionTooLow: 'Versi 1Panel semasa terlalu rendah untuk mengemas kini App Store. Sila tingkatkan versi sebelum beroperasi.' ErrVersionTooLow: 'Versi 1Panel semasa terlalu rendah untuk mengemas kini App Store. Sila tingkatkan versi sebelum beroperasi.'
ErrAppNameExist: 'Nama aplikasi sudah wujud' ErrAppNameExist: 'Nama aplikasi sudah wujud'
ErrAppInstallNameExist: 'Nama pemasangan aplikasi {{ .name }} sudah wujud'
AppStoreIsSyncing: 'App Store sedang menyegerak, sila cuba sebentar lagi' AppStoreIsSyncing: 'App Store sedang menyegerak, sila cuba sebentar lagi'
ErrGetCompose: 'Gagal mendapatkan fail docker-compose.yml {{ .detail }}' ErrGetCompose: 'Gagal mendapatkan fail docker-compose.yml {{ .detail }}'
ErrAppWarn: 'Status tidak normal, sila semak log' ErrAppWarn: 'Status tidak normal, sila semak log'
@@ -131,6 +143,8 @@ ErrDockerFailed: 'Keadaan Docker tidak normal, sila periksa status perkhidmatan'
ErrDockerComposeCmdNotFound: 'Perintah Docker Compose tidak wujud, sila pasang perintah ini di mesin tuan terlebih dahulu' ErrDockerComposeCmdNotFound: 'Perintah Docker Compose tidak wujud, sila pasang perintah ini di mesin tuan terlebih dahulu'
UseExistImage: 'Imej sudah wujud, menggunakan imej sedia ada' UseExistImage: 'Imej sudah wujud, menggunakan imej sedia ada'
ErrDatabaseNotFound: 'Pangkalan data {{ .name }} tidak wujud' ErrDatabaseNotFound: 'Pangkalan data {{ .name }} tidak wujud'
# SSH
ExportIP: 'IP Log Masuk' ExportIP: 'IP Log Masuk'
ExportArea: 'Lokasi' ExportArea: 'Lokasi'
ExportPort: 'Port' ExportPort: 'Port'
@@ -138,6 +152,8 @@ ExportAuthMode: 'Kaedah Log Masuk'
ExportUser: 'Pengguna' ExportUser: 'Pengguna'
ExportStatus: 'Status Log Masuk' ExportStatus: 'Status Log Masuk'
ExportDate: 'Masa' ExportDate: 'Masa'
# fail
ErrFileCanNotRead: 'Fail ini tidak menyokong pratonton' ErrFileCanNotRead: 'Fail ini tidak menyokong pratonton'
ErrSensitiveFileRead: 'Membaca fail sensitif tidak dibenarkan' ErrSensitiveFileRead: 'Membaca fail sensitif tidak dibenarkan'
ErrFileToLarge: 'Fail lebih besar daripada 10M dan tidak boleh dibuka' ErrFileToLarge: 'Fail lebih besar daripada 10M dan tidak boleh dibuka'
@@ -164,6 +180,8 @@ FileDropFailed: 'Gagal membersihkan fail {{ .name }}: {{ .err }}'
FileDropSuccess: 'Berjaya membersihkan fail {{ .name }}, {{ .count }} fail dibersihkan, {{ .size }} ruang cakera dibebaskan' FileDropSuccess: 'Berjaya membersihkan fail {{ .name }}, {{ .count }} fail dibersihkan, {{ .size }} ruang cakera dibebaskan'
FileDropSum: 'Pembersihan fail selesai, sejumlah {{ .count }} fail dibersihkan, sejumlah {{ .size }} ruang cakera dibebaskan' FileDropSum: 'Pembersihan fail selesai, sejumlah {{ .count }} fail dibersihkan, sejumlah {{ .size }} ruang cakera dibebaskan'
ErrBadDecrypt: 'Kata laluan penyahsulitan pakej termampat salah, penyahmampatan gagal, sila periksa dan cuba lagi' ErrBadDecrypt: 'Kata laluan penyahsulitan pakej termampat salah, penyahmampatan gagal, sila periksa dan cuba lagi'
# laman web
ErrAliasIsExist: 'Alias sudah wujud' ErrAliasIsExist: 'Alias sudah wujud'
ErrBackupMatch: 'Fail sandaran tidak sepadan dengan beberapa data tapak web semasa {{ .detail }}' ErrBackupMatch: 'Fail sandaran tidak sepadan dengan beberapa data tapak web semasa {{ .detail }}'
ErrBackupExist: 'Bahagian sepadan data sumber dalam fail sandaran tidak wujud {{ .detail }}' ErrBackupExist: 'Bahagian sepadan data sumber dalam fail sandaran tidak wujud {{ .detail }}'
@@ -193,6 +211,8 @@ delete: 'Padam'
ErrDefaultWebsite: 'Laman web lalai telah ditetapkan, sila batalkan sebelum menetapkan' ErrDefaultWebsite: 'Laman web lalai telah ditetapkan, sila batalkan sebelum menetapkan'
SSL: 'Sijil' SSL: 'Sijil'
Set: 'Tetapan' Set: 'Tetapan'
# sijil SSL
ErrSSLCannotDelete: 'Sijil {{ .name }} sedang digunakan oleh tapak web dan tidak boleh dipadamkan' ErrSSLCannotDelete: 'Sijil {{ .name }} sedang digunakan oleh tapak web dan tidak boleh dipadamkan'
ErrAccountCannotDelete: 'Akaun dikaitkan dengan sijil dan tidak boleh dipadamkan' ErrAccountCannotDelete: 'Akaun dikaitkan dengan sijil dan tidak boleh dipadamkan'
ErrSSLApply: 'Pembaharuan sijil berjaya, muat semula openresty gagal, sila semak konfigurasi' ErrSSLApply: 'Pembaharuan sijil berjaya, muat semula openresty gagal, sila semak konfigurasi'
@@ -227,6 +247,8 @@ ErrApplySSLCanNotDelete: 'Sertifikat {{ .name }} yang sedang diajukan tidak dapa
StartPushSSLToNode: 'Mula menolak sijil ke nod' StartPushSSLToNode: 'Mula menolak sijil ke nod'
PushSSLToNodeFailed: 'Gagal menolak sijil ke nod: {{ .err }}' PushSSLToNodeFailed: 'Gagal menolak sijil ke nod: {{ .err }}'
PushSSLToNodeSuccess: 'Berjaya menolak sijil ke nod' PushSSLToNodeSuccess: 'Berjaya menolak sijil ke nod'
# MySQL
ErrUserIsExist: 'Pengguna semasa sudah wujud, sila masukkan semula' ErrUserIsExist: 'Pengguna semasa sudah wujud, sila masukkan semula'
ErrDatabaseIsExist: 'Pangkalan data semasa sudah wujud, sila masukkan semula' ErrDatabaseIsExist: 'Pangkalan data semasa sudah wujud, sila masukkan semula'
ErrExecTimeOut: 'Pelaksanaan SQL tamat masa, sila semak pangkalan data' ErrExecTimeOut: 'Pelaksanaan SQL tamat masa, sila semak pangkalan data'
@@ -235,7 +257,11 @@ ErrLocalExist: 'Nama sudah wujud dalam pangkalan data tempatan, sila ubah suai d
RemoteBackup: 'Untuk menyandarkan pangkalan data jauh, perkhidmatan pangkalan data bekas tempatan perlu dimulakan terlebih dahulu menggunakan imej {{ .name }}, sila tunggu...' RemoteBackup: 'Untuk menyandarkan pangkalan data jauh, perkhidmatan pangkalan data bekas tempatan perlu dimulakan terlebih dahulu menggunakan imej {{ .name }}, sila tunggu...'
RemoteRecover: 'Untuk memulihkan pangkalan data jauh, perkhidmatan pangkalan data bekas tempatan perlu dimulakan terlebih dahulu menggunakan imej {{ .name }}, sila tunggu...' RemoteRecover: 'Untuk memulihkan pangkalan data jauh, perkhidmatan pangkalan data bekas tempatan perlu dimulakan terlebih dahulu menggunakan imej {{ .name }}, sila tunggu...'
Arg: 'Hujah' Arg: 'Hujah'
# Redis
ErrTypeOfRedis: 'Jenis fail pemulihan tidak sepadan dengan kaedah kegigihan semasa, sila ubah suai dan cuba lagi' ErrTypeOfRedis: 'Jenis fail pemulihan tidak sepadan dengan kaedah kegigihan semasa, sila ubah suai dan cuba lagi'
# bekas
ErrInUsed: '{{ .detail }} sedang digunakan dan tidak boleh dipadam' ErrInUsed: '{{ .detail }} sedang digunakan dan tidak boleh dipadam'
ErrObjectInUsed: 'Objek ini sedang digunakan dan tidak boleh dipadam' ErrObjectInUsed: 'Objek ini sedang digunakan dan tidak boleh dipadam'
ErrObjectBeDependent: 'Imej ini digantungkan oleh imej lain dan tidak boleh dipadam' ErrObjectBeDependent: 'Imej ini digantungkan oleh imej lain dan tidak boleh dipadam'
@@ -277,6 +303,8 @@ ComposeRecoverFiles: 'Pulihkan fail compose'
ComposeRecoverContainers: 'Pulihkan kontena compose' ComposeRecoverContainers: 'Pulihkan kontena compose'
ComposeRecoverRecord: 'Simpan rekod compose' ComposeRecoverRecord: 'Simpan rekod compose'
ComposeRecoverCleanup: 'Bersihkan ruang kerja pemulihan compose' ComposeRecoverCleanup: 'Bersihkan ruang kerja pemulihan compose'
# runtime
ErrFileNotExist: 'Fail {{ .detail }} tidak wujud Sila semak integriti fail sumber' ErrFileNotExist: 'Fail {{ .detail }} tidak wujud Sila semak integriti fail sumber'
ErrImageBuildErr: 'Pembinaan imej gagal' ErrImageBuildErr: 'Pembinaan imej gagal'
ErrImageExist: 'Imej sudah wujud Sila ubah nama imej.' ErrImageExist: 'Imej sudah wujud Sila ubah nama imej.'
@@ -289,12 +317,16 @@ ErrNodeModulesNotFound: 'Folder node_modules tidak wujud Sila edit persekitaran
ErrContainerNameIsNull: 'Nama kontena tidak wujud' ErrContainerNameIsNull: 'Nama kontena tidak wujud'
ErrPHPPortIsDefault: 'Port 9000 ialah port lalai. Sila tukar dan cuba lagi' ErrPHPPortIsDefault: 'Port 9000 ialah port lalai. Sila tukar dan cuba lagi'
ErrPHPRuntimePortFailed: 'Port {{ .name }} sudah digunakan oleh runtime semasa. Sila tukar dan cuba lagi' ErrPHPRuntimePortFailed: 'Port {{ .name }} sudah digunakan oleh runtime semasa. Sila tukar dan cuba lagi'
# alat
ErrConfigNotFound: 'Fail konfigurasi tidak wujud' ErrConfigNotFound: 'Fail konfigurasi tidak wujud'
ErrConfigParse: 'Format fail konfigurasi tidak betul' ErrConfigParse: 'Format fail konfigurasi tidak betul'
ErrConfigIsNull: 'Fail konfigurasi tidak boleh kosong' ErrConfigIsNull: 'Fail konfigurasi tidak boleh kosong'
ErrConfigDirNotFound: 'Direktori berjalan tidak wujud' ErrConfigDirNotFound: 'Direktori berjalan tidak wujud'
ErrConfigAlreadyExist: 'Fail konfigurasi dengan nama yang sama sudah wujud' ErrConfigAlreadyExist: 'Fail konfigurasi dengan nama yang sama sudah wujud'
ErrUserFindErr: 'Pengguna {{ .name }} carian gagal {{ .err }}' ErrUserFindErr: 'Pengguna {{ .name }} carian gagal {{ .err }}'
# tugas cron
CutWebsiteLogSuccess: '{{ .name }} log tapak web berjaya dipotong, laluan sandaran {{ .path }}' CutWebsiteLogSuccess: '{{ .name }} log tapak web berjaya dipotong, laluan sandaran {{ .path }}'
HandleShell: 'Laksanakan skrip {{ .name }}' HandleShell: 'Laksanakan skrip {{ .name }}'
HandleCurl: 'Akses URL {{ .name }}' HandleCurl: 'Akses URL {{ .name }}'
@@ -313,6 +345,8 @@ NoSuchResource: 'Tiada kandungan sandaran ditemui dalam pangkalan data, dilangka
CleanLog: 'Bersihkan log' CleanLog: 'Bersihkan log'
CleanLogByName: 'Bersihkan log {{ .name }}' CleanLogByName: 'Bersihkan log {{ .name }}'
WafIpGroupNotFound: 'Kumpulan IP WAF tidak ditemui. Sila pergi ke [Ciri Lanjutan - WAF - Senarai Hitam/Putih - Kumpulan IP] untuk menambah kumpulan IP melalui kaedah muat turun jauh.' WafIpGroupNotFound: 'Kumpulan IP WAF tidak ditemui. Sila pergi ke [Ciri Lanjutan - WAF - Senarai Hitam/Putih - Kumpulan IP] untuk menambah kumpulan IP melalui kaedah muat turun jauh.'
# kotak alat
ErrNotExistUser: 'Pengguna semasa tidak wujud, sila ubah suai dan cuba lagi' ErrNotExistUser: 'Pengguna semasa tidak wujud, sila ubah suai dan cuba lagi'
ErrBanAction: 'Tetapan gagal. Perkhidmatan {{ .name }} semasa tidak tersedia. Sila semak dan cuba lagi' ErrBanAction: 'Tetapan gagal. Perkhidmatan {{ .name }} semasa tidak tersedia. Sila semak dan cuba lagi'
ErrClamdscanNotFound: 'Arahan clamdscan tidak dikesan, sila rujuk dokumentasi untuk memasangnya' ErrClamdscanNotFound: 'Arahan clamdscan tidak dikesan, sila rujuk dokumentasi untuk memasangnya'
@@ -321,11 +355,15 @@ SetSwap: 'Tetapkan Swap {{ .path }} - {{ .size }}'
CreateSwap: 'Buat Fail Swap' CreateSwap: 'Buat Fail Swap'
FormatSwap: 'Format Fail Swap' FormatSwap: 'Format Fail Swap'
EnableSwap: 'Dayakan Swap' EnableSwap: 'Dayakan Swap'
# perlindungan ubah suai
CleanTamperSetting: 'Bersihkan tetapan perlindungan sejarah' CleanTamperSetting: 'Bersihkan tetapan perlindungan sejarah'
SetTamperWithRules: 'Mulakan perlindungan direktori mengikut peraturan' SetTamperWithRules: 'Mulakan perlindungan direktori mengikut peraturan'
ProtectDir: 'Lindungi direktori {{ .name }}' ProtectDir: 'Lindungi direktori {{ .name }}'
IgnoreFile: 'Lindungi fail {{ .name }}' IgnoreFile: 'Lindungi fail {{ .name }}'
TamperSetSuccessful: 'Tetapan perlindungan selesai, mula memantau direktori berikut:' TamperSetSuccessful: 'Tetapan perlindungan selesai, mula memantau direktori berikut:'
# WAF
ErrScope: 'Mengubah suai konfigurasi ini tidak disokong' ErrScope: 'Mengubah suai konfigurasi ini tidak disokong'
ErrStateChange: 'Perubahan keadaan gagal' ErrStateChange: 'Perubahan keadaan gagal'
ErrRuleExist: 'Peraturan sudah wujud' ErrRuleExist: 'Peraturan sudah wujud'
@@ -380,6 +418,8 @@ OpenrestyNotFound: 'OpenResty tidak dipasang'
remoteIpIsNull: 'Senarai IP kosong' remoteIpIsNull: 'Senarai IP kosong'
OpenrestyVersionErr: 'Versi OpenResty terlalu lama. Naik taraf ke 1.27.1.2-2-2-focal' OpenrestyVersionErr: 'Versi OpenResty terlalu lama. Naik taraf ke 1.27.1.2-2-2-focal'
ErrFileTooLarge: 'Fail melebihi 1 MB dan tidak boleh dimuat naik' ErrFileTooLarge: 'Fail melebihi 1 MB dan tidak boleh dimuat naik'
# tugas
TaskStart: '{{ .name }} Task mula [MULA]' TaskStart: '{{ .name }} Task mula [MULA]'
TaskEnd: '{{ .name }} Task selesai [SELESAI]' TaskEnd: '{{ .name }} Task selesai [SELESAI]'
TaskFailed: 'tugas {{ .name }} gagal' TaskFailed: 'tugas {{ .name }} gagal'
@@ -440,10 +480,17 @@ CustomAppstore: 'Gudang aplikasi tersuai'
TaskExec: 'Laksanakan' TaskExec: 'Laksanakan'
TaskBatch: 'Operasi Batch' TaskBatch: 'Operasi Batch'
FileConvert: 'Penukaran Format Fail' FileConvert: 'Penukaran Format Fail'
# tugas - ClamAV
Clamscan: 'Imbas {{ .name }}' Clamscan: 'Imbas {{ .name }}'
TaskScan: 'Imbas' TaskScan: 'Imbas'
# tugas - AI
OllamaModelPull: 'Tarik model Ollama {{ .name }}' OllamaModelPull: 'Tarik model Ollama {{ .name }}'
OllamaModelSize: 'Dapatkan saiz model Ollama {{ .name }}' OllamaModelSize: 'Dapatkan saiz model Ollama {{ .name }}'
AIBenchmarkRun: "Jalankan penanda aras AI"
# tugas - syot kilat
Snapshot: 'Snapshot' Snapshot: 'Snapshot'
SnapDBInfo: 'Tulis maklumat pangkalan data 1Panel' SnapDBInfo: 'Tulis maklumat pangkalan data 1Panel'
SnapCopy: 'Salin fail & direktori {{ .name }}' SnapCopy: 'Salin fail & direktori {{ .name }}'
@@ -493,6 +540,8 @@ RecoverDaemonJson: 'Pulihkan fail daemon.json konfigurasi bekas'
RecoverDBData: 'Pulihkan data pangkalan data' RecoverDBData: 'Pulihkan data pangkalan data'
RecoverBackups: 'Pulihkan direktori sandaran tempatan' RecoverBackups: 'Pulihkan direktori sandaran tempatan'
RecoverPanelData: 'Direktori data pemulihan' RecoverPanelData: 'Direktori data pemulihan'
# tugas - bekas
ContainerImagePull: 'Tarik imej bekas {{ .name }}' ContainerImagePull: 'Tarik imej bekas {{ .name }}'
ContainerRemoveOld: 'Alih keluar bekas asal {{ .name }}' ContainerRemoveOld: 'Alih keluar bekas asal {{ .name }}'
ContainerImageCheck: 'Periksa sama ada imej ditarik seperti biasa' ContainerImageCheck: 'Periksa sama ada imej ditarik seperti biasa'
@@ -501,6 +550,8 @@ ContainerRecreate: 'Kemas kini kontena gagal, kini mula memulihkan bekas asal'
ContainerCreate: 'Buat bekas baharu {{ .name }}' ContainerCreate: 'Buat bekas baharu {{ .name }}'
ContainerCreateFailed: 'Penciptaan bekas gagal, padamkan bekas yang gagal' ContainerCreateFailed: 'Penciptaan bekas gagal, padamkan bekas yang gagal'
ContainerStartCheck: 'Periksa sama ada bekas telah dimulakan' ContainerStartCheck: 'Periksa sama ada bekas telah dimulakan'
# tugas - imej
ImageBuild: 'Membina Imej' ImageBuild: 'Membina Imej'
ImagePull: 'Tarik imej' ImagePull: 'Tarik imej'
ImageRepoAuthFromDB: 'Dapatkan maklumat pengesahan repositori daripada pangkalan data' ImageRepoAuthFromDB: 'Dapatkan maklumat pengesahan repositori daripada pangkalan data'
@@ -508,6 +559,8 @@ ImagePush: 'Tolak imej'
ImageRenameTag: 'Ubah suai teg imej' ImageRenameTag: 'Ubah suai teg imej'
ImageNewTag: 'Teg imej baharu {{ .name }}' ImageNewTag: 'Teg imej baharu {{ .name }}'
ComposeCreate: 'Buat gubahan' ComposeCreate: 'Buat gubahan'
# tugas - laman web
BackupNginxConfig: 'Fail konfigurasi OpenResty tapak web sandaran' BackupNginxConfig: 'Fail konfigurasi OpenResty tapak web sandaran'
CompressFileSuccess: 'Mampatkan direktori berjaya, dimampatkan ke {{ .name }}' CompressFileSuccess: 'Mampatkan direktori berjaya, dimampatkan ke {{ .name }}'
CompressDir: 'Direktori mampatan' CompressDir: 'Direktori mampatan'
@@ -518,8 +571,15 @@ websiteDir: 'Direktori Laman Web'
RecoverFailedStartRollBack: 'Pemulihan gagal, mulakan rollback' RecoverFailedStartRollBack: 'Pemulihan gagal, mulakan rollback'
AppBackupFileIncomplete: 'Fail sandaran tidak lengkap dan tidak mempunyai fail app.json atau app.tar.gz' AppBackupFileIncomplete: 'Fail sandaran tidak lengkap dan tidak mempunyai fail app.json atau app.tar.gz'
AppAttributesNotMatch: 'Jenis atau nama aplikasi tidak sepadan' AppAttributesNotMatch: 'Jenis atau nama aplikasi tidak sepadan'
# amaran
ErrAlertMethodNotSupported: 'Versi ini tidak menyokong kaedah amaran ini'
ErrAlertSync: 'Ralat penyegerakan maklumat penggera, sila semak dan cuba lagi' ErrAlertSync: 'Ralat penyegerakan maklumat penggera, sila semak dan cuba lagi'
# tugas - runtime
ErrInstallExtension: 'Tugas pemasangan sudah sedang berjalan, silakan tunggu tugas selesai' ErrInstallExtension: 'Tugas pemasangan sudah sedang berjalan, silakan tunggu tugas selesai'
# templat mel amaran
PanelAlertTitle: 'Notifikasi Amaran Panel' PanelAlertTitle: 'Notifikasi Amaran Panel'
TestAlertTitle: 'E-mel Ujian - Sahkan Sambungan E-mel' TestAlertTitle: 'E-mel Ujian - Sahkan Sambungan E-mel'
TestAlert: 'Ini adalah e-mel ujian untuk mengesahkan konfigurasi penghantaran e-mel anda betul.' TestAlert: 'Ini adalah e-mel ujian untuk mengesahkan konfigurasi penghantaran e-mel anda betul.'
@@ -536,6 +596,8 @@ CommonAlert: 'Panel {{ .node }}{{ .ip }} Anda, {{ .msg }}. Sila log masuk ke pan
NodeExceptionAlert: 'Panel {{ .node }}{{ .ip }} Anda, {{ .num }} nod tidak normal. Sila log masuk ke panel untuk butiran lanjut.' NodeExceptionAlert: 'Panel {{ .node }}{{ .ip }} Anda, {{ .num }} nod tidak normal. Sila log masuk ke panel untuk butiran lanjut.'
LicenseExceptionAlert: 'Panel {{ .node }}{{ .ip }} Anda, {{ .num }} lesen tidak normal. Sila log masuk ke panel untuk butiran lanjut.' LicenseExceptionAlert: 'Panel {{ .node }}{{ .ip }} Anda, {{ .num }} lesen tidak normal. Sila log masuk ke panel untuk butiran lanjut.'
SSHAndPanelLoginAlert: 'Panel {{ .node }}{{ .ip }} Anda, log masuk {{ .name }} dari {{ .loginIp }} tidak normal. Sila log masuk ke panel untuk butiran lanjut.' SSHAndPanelLoginAlert: 'Panel {{ .node }}{{ .ip }} Anda, log masuk {{ .name }} dari {{ .loginIp }} tidak normal. Sila log masuk ke panel untuk butiran lanjut.'
# cakera
DeviceNotFound: 'Peranti {{ .name }} tidak ditemui' DeviceNotFound: 'Peranti {{ .name }} tidak ditemui'
DeviceIsMounted: 'Peranti {{ .name }} telah dikaitkan, sila nyahkaitkan terlebih dahulu' DeviceIsMounted: 'Peranti {{ .name }} telah dikaitkan, sila nyahkaitkan terlebih dahulu'
PartitionDiskErr: 'Gagal membahagikan, {{ .err }}' PartitionDiskErr: 'Gagal membahagikan, {{ .err }}'
@@ -548,4 +610,13 @@ TerminalAIBlockedRiskyCommand: 'Perintah berisiko telah disekat: {{ .command }}'
TerminalAIThinking: 'AI sedang berfikir...' TerminalAIThinking: 'AI sedang berfikir...'
TerminalAIReadyToExecute: 'Pemikiran selesai, tekan Enter untuk jalankan (tempoh: {{ .duration }}, token: {{ .tokens }})' TerminalAIReadyToExecute: 'Pemikiran selesai, tekan Enter untuk jalankan (tempoh: {{ .duration }}, token: {{ .tokens }})'
TerminalAIRequestFailed: 'Permintaan AI gagal: {{ .err }}' TerminalAIRequestFailed: 'Permintaan AI gagal: {{ .err }}'
FileAISearchEmptyDir: 'Tiada fail atau direktori di bawah laluan ini (atau semua ditapis).'
# gerbang AI
ErrAIProxyServiceNotInstalled: 'Perkhidmatan {{ .name }} belum dipasang'
ErrAIProxyModelAccountNotFound: 'Akaun model {{ .id }} tidak ditemui'
ErrAIProxyModelMapRequired: 'Medan ini wajib diisi.'
ErrAIProxyModelMapInvalid: 'Pemetaan model mestilah objek JSON yang sah: {{ .err }}'
ErrAIProxyModelMapEmpty: 'Pemetaan model tidak boleh kosong'
ErrAIProxyModelMapEmptyExternalModel: 'Pemetaan model mengandungi model permintaan kosong'
ErrAIProxyModelMapEmptyUpstreamModel: 'Model upstream untuk {{ .model }} tidak boleh kosong'
AIProxyUserFallback: 'Pengguna dipadam (ID: {{ .id }})'
+91 -20
View File
@@ -1,29 +1,47 @@
# erros básicos
ErrInvalidParams: 'Requisição inválida: {{ .detail }}' ErrInvalidParams: 'Requisição inválida: {{ .detail }}'
ErrTokenParse: 'Erro de token: {{ .detail }}' ErrTokenParse: 'Erro de token: {{ .detail }}'
ErrInitialPassword: 'Senha original incorreta' ErrInitialPassword: 'Senha original incorreta'
ErrInternalServer: 'Erro interno: {{ .detail }}' ErrInternalServer: 'Erro interno: {{ .detail }}'
ErrRecordExist: 'Registro já existe'
ErrRecordNotFound: 'Registro não encontrado'
ErrStructTransform: 'Erro de conversão: {{ .err }}'
ErrNotSupportType: 'Tipo não suportado: {{ .name }}'
# IA de arquivos
ErrFileAINotEnabled: 'A pesquisa com IA de arquivos está desativada ou sem conta. Em Gerenciamento de arquivos, use Conta de IA, ative e escolha uma conta.' ErrFileAINotEnabled: 'A pesquisa com IA de arquivos está desativada ou sem conta. Em Gerenciamento de arquivos, use Conta de IA, ative e escolha uma conta.'
ErrFileAISearchBadPattern: 'Padrão de busca inválido (regex ou opção): {{ .detail }}' ErrFileAISearchBadPattern: 'Padrão de busca inválido (regex ou opção): {{ .detail }}'
FileAISearchEmptyDir: 'Nenhum arquivo ou pasta encontrado neste caminho (ou todos foram filtrados).'
# download remoto
ErrWgetRemoteFailed: 'Falha no download remoto ou URL inacessível: {{ .detail }}' ErrWgetRemoteFailed: 'Falha no download remoto ou URL inacessível: {{ .detail }}'
ErrWgetInvalidContentType: 'A URL remota não retornou um arquivo (possivelmente uma página de erro), {{ .detail }}' ErrWgetInvalidContentType: 'A URL remota não retornou um arquivo (possivelmente uma página de erro), {{ .detail }}'
ErrWgetProxyNotConfigured: 'Configure primeiro um servidor proxy nas configurações do painel' ErrWgetProxyNotConfigured: 'Configure primeiro um servidor proxy nas configurações do painel'
ErrWgetProxyInvalid: 'Endereço do servidor proxy inválido: {{ .detail }}' ErrWgetProxyInvalid: 'Endereço do servidor proxy inválido: {{ .detail }}'
ErrRecordExist: 'Registro já existe'
ErrRecordNotFound: 'Registro não encontrado' # login e segurança
ErrStructTransform: 'Erro de conversão: {{ .err }}'
ErrNotLogin: 'Sem sessão: {{ .detail }}' ErrNotLogin: 'Sem sessão: {{ .detail }}'
ErrPasswordExpired: 'Senha expirada: {{ .detail }}' ErrPasswordExpired: 'Senha expirada: {{ .detail }}'
ErrNotSupportType: 'Tipo não suportado: {{ .name }}'
ErrAlertMethodNotSupported: 'Esta versão não oferece suporte a este método de alerta' # requisição e API
ErrProxy: 'Requisição falhou: {{ .detail }}' ErrProxy: 'Requisição falhou: {{ .detail }}'
ErrApiConfigStatusInvalid: 'API desativada: {{ .detail }}' ErrApiConfigStatusInvalid: 'API desativada: {{ .detail }}'
ErrApiConfigKeyInvalid: 'Chave API inválida: {{ .detail }}' ErrApiConfigKeyInvalid: 'Chave API inválida: {{ .detail }}'
ErrApiConfigIPInvalid: 'IP sem permissão: {{ .detail }}' ErrApiConfigIPInvalid: 'IP sem permissão: {{ .detail }}'
ErrApiConfigDisable: 'API bloqueada: {{ .detail }}' ErrApiConfigDisable: 'API bloqueada: {{ .detail }}'
ErrApiConfigKeyTimeInvalid: 'Timestamp inválido: {{ .detail }}' ErrApiConfigKeyTimeInvalid: 'Timestamp inválido: {{ .detail }}'
ErrShutDown: 'Comando parado manualmente' ErrCreateHttpClient: 'Falha ao criar solicitação {{ .err }}'
ErrHttpReqTimeOut: 'Tempo limite da solicitação esgotado {{ .err }}'
ErrHttpReqFailed: 'Falha na solicitação {{ .err }}'
ErrNoSuchHost: 'Não foi possível encontrar o servidor solicitado {{ .err }}'
ErrHttpReqNotFound: 'O recurso solicitado {{ .err }} não pôde ser encontrado'
# atalho rápido
ErrMinQuickJump: 'Adicione pelo menos um atalho rápido' ErrMinQuickJump: 'Adicione pelo menos um atalho rápido'
ErrMaxQuickJump: 'Máximo 4 atalhos rápidos' ErrMaxQuickJump: 'Máximo 4 atalhos rápidos'
# comum
ErrShutDown: 'Comando parado manualmente'
ErrUsernameIsExist: 'Usuário já existe' ErrUsernameIsExist: 'Usuário já existe'
ErrNameIsExist: 'Nome já existe' ErrNameIsExist: 'Nome já existe'
ErrDemoEnvironment: 'Indisponível em demo' ErrDemoEnvironment: 'Indisponível em demo'
@@ -41,6 +59,8 @@ SystemRestart: 'Tarefa interrompida devido à reinicialização do sistema'
ErrGroupIsDefault: 'Grupo padrão, não pode ser excluído' ErrGroupIsDefault: 'Grupo padrão, não pode ser excluído'
ErrGroupIsInWebsiteUse: 'O grupo está sendo usado por outro site e não pode ser excluído.' ErrGroupIsInWebsiteUse: 'O grupo está sendo usado por outro site e não pode ser excluído.'
Decrypt: 'Descriptografar' Decrypt: 'Descriptografar'
# agente
ErrAgentAccountBound: 'Conta vinculada a agente' ErrAgentAccountBound: 'Conta vinculada a agente'
ErrTerminalAIAccountInUse: 'Esta conta de modelo esta sendo usada pelo Terminal AI. Troque a conta nas configuracoes do Terminal AI ou desative o Terminal AI e tente novamente.' ErrTerminalAIAccountInUse: 'Esta conta de modelo esta sendo usada pelo Terminal AI. Troque a conta nas configuracoes do Terminal AI ou desative o Terminal AI e tente novamente.'
ErrAgentAccountUnavailable: 'Conexão da conta indisponível: {{ .err }}' ErrAgentAccountUnavailable: 'Conexão da conta indisponível: {{ .err }}'
@@ -65,14 +85,8 @@ ErrAgentWebsiteInUse: 'Este site já está vinculado a outro agente'
ErrAgentWebsiteUnbindUnsupported: 'Sites implantados em um clique não podem ser desvinculados manualmente' ErrAgentWebsiteUnbindUnsupported: 'Sites implantados em um clique não podem ser desvinculados manualmente'
ErrHermesPairingCodeUnavailable: 'O código de pareamento está temporariamente indisponível no Hermes, possivelmente por causa de rede. Tente novamente mais tarde.' ErrHermesPairingCodeUnavailable: 'O código de pareamento está temporariamente indisponível no Hermes, possivelmente por causa de rede. Tente novamente mais tarde.'
ErrHermesFeishuGroupAllowlistRequiresAllowlist: 'Quando a política de grupo do Feishu é Lista de permissões, a política de DM não pode ser Código de pareamento.' ErrHermesFeishuGroupAllowlistRequiresAllowlist: 'Quando a política de grupo do Feishu é Lista de permissões, a política de DM não pode ser Código de pareamento.'
ErrAIProxyServiceNotInstalled: 'O serviço {{ .name }} não está instalado'
ErrAIProxyModelAccountNotFound: 'Conta de modelo {{ .id }} não encontrada' # backup e configurações de alerta
ErrAIProxyModelMapRequired: 'Este campo é obrigatório.'
ErrAIProxyModelMapInvalid: 'O mapeamento de modelos deve ser um objeto JSON válido: {{ .err }}'
ErrAIProxyModelMapEmpty: 'O mapeamento de modelos não pode estar vazio'
ErrAIProxyModelMapEmptyExternalModel: 'O mapeamento de modelos contém um modelo solicitado vazio'
ErrAIProxyModelMapEmptyUpstreamModel: 'O modelo upstream de {{ .model }} não pode estar vazio'
AIProxyUserFallback: 'Usuário {{ .id }}'
Localhost: 'Máquina Local' Localhost: 'Máquina Local'
ErrBackupInUsed: 'Conta de backup em uso por tarefa' ErrBackupInUsed: 'Conta de backup em uso por tarefa'
ErrBackupCheck: 'Teste de conexão falhou: {{ .err }}' ErrBackupCheck: 'Teste de conexão falhou: {{ .err }}'
@@ -80,6 +94,8 @@ ErrBackupLocalDelete: 'Não é permitido excluir contas locais'
ErrBackupLocalCreate: 'Não é permitido criar contas locais' ErrBackupLocalCreate: 'Não é permitido criar contas locais'
ErrAlertConfigInUse: 'A configuração de alerta está em uso e não pode ser excluída' ErrAlertConfigInUse: 'A configuração de alerta está em uso e não pode ser excluída'
ErrAlertConfigPhoneExist: 'O numero de telefone ja existe' ErrAlertConfigPhoneExist: 'O numero de telefone ja existe'
# aplicativo
ErrPortInUsed: 'A porta {{ .detail }} já está ocupada' ErrPortInUsed: 'A porta {{ .detail }} já está ocupada'
ErrAppLimit: 'O número de aplicativos instalados excedeu o limite' ErrAppLimit: 'O número de aplicativos instalados excedeu o limite'
ErrNotInstall: 'Aplicativo não instalado' ErrNotInstall: 'Aplicativo não instalado'
@@ -97,16 +113,12 @@ ErrFileParseApp: 'Falha na análise do arquivo {{ .name }} {{ .err }}'
ErrAppDirNull: 'A pasta da versão não existe' ErrAppDirNull: 'A pasta da versão não existe'
LocalAppErr: 'Falha na sincronização do aplicativo {{ .name }} {{ .err }}' LocalAppErr: 'Falha na sincronização do aplicativo {{ .name }} {{ .err }}'
ErrContainerName: 'O nome do contêiner já existe' ErrContainerName: 'O nome do contêiner já existe'
ErrCreateHttpClient: 'Falha ao criar solicitação {{ .err }}'
ErrHttpReqTimeOut: 'Tempo limite da solicitação esgotado {{ .err }}'
ErrHttpReqFailed: 'Falha na solicitação {{ .err }}'
ErrNoSuchHost: 'Não foi possível encontrar o servidor solicitado {{ .err }}'
ErrHttpReqNotFound: 'O recurso solicitado {{ .err }} não pôde ser encontrado'
ErrContainerNotFound: '{{ .name }} container não existe' ErrContainerNotFound: '{{ .name }} container não existe'
ErrContainerMsg: 'O contêiner {{ .name }} está anormal., verifique o log na página do contêiner para obter detalhes.' ErrContainerMsg: 'O contêiner {{ .name }} está anormal., verifique o log na página do contêiner para obter detalhes.'
ErrAppBackup: '{{ .name }} falha no backup do aplicativo {{ .err }}' ErrAppBackup: '{{ .name }} falha no backup do aplicativo {{ .err }}'
ErrVersionTooLow: 'A versão atual do 1Panel é muito antiga para atualizar a App Store., atualize a versão antes de operar.' ErrVersionTooLow: 'A versão atual do 1Panel é muito antiga para atualizar a App Store., atualize a versão antes de operar.'
ErrAppNameExist: 'O nome do aplicativo já existe' ErrAppNameExist: 'O nome do aplicativo já existe'
ErrAppInstallNameExist: 'O nome de instalação do aplicativo {{ .name }} já existe'
AppStoreIsSyncing: 'A App Store está sincronizando mais tarde' AppStoreIsSyncing: 'A App Store está sincronizando mais tarde'
ErrGetCompose: 'Falha ao obter o arquivo docker-compose.yml {{ .detail }}' ErrGetCompose: 'Falha ao obter o arquivo docker-compose.yml {{ .detail }}'
ErrAppWarn: 'Status anormal, verifique o log' ErrAppWarn: 'Status anormal, verifique o log'
@@ -131,6 +143,8 @@ ErrDockerFailed: 'O estado do Docker está anormal, verifique o status do servi
ErrDockerComposeCmdNotFound: 'O comando Docker Compose não existe, instale este comando na máquina host primeiro' ErrDockerComposeCmdNotFound: 'O comando Docker Compose não existe, instale este comando na máquina host primeiro'
UseExistImage: 'A imagem já existe, usando imagem existente' UseExistImage: 'A imagem já existe, usando imagem existente'
ErrDatabaseNotFound: 'O banco de dados {{ .name }} não existe' ErrDatabaseNotFound: 'O banco de dados {{ .name }} não existe'
# SSH
ExportIP: 'IP de Login' ExportIP: 'IP de Login'
ExportArea: 'Localização' ExportArea: 'Localização'
ExportPort: 'Porta' ExportPort: 'Porta'
@@ -138,6 +152,8 @@ ExportAuthMode: 'Método de Login'
ExportUser: 'Usuário' ExportUser: 'Usuário'
ExportStatus: 'Status de Login' ExportStatus: 'Status de Login'
ExportDate: 'Hora' ExportDate: 'Hora'
# arquivo
ErrFileCanNotRead: 'Este arquivo não suporta visualização' ErrFileCanNotRead: 'Este arquivo não suporta visualização'
ErrSensitiveFileRead: 'A leitura de arquivos sensíveis não é permitida' ErrSensitiveFileRead: 'A leitura de arquivos sensíveis não é permitida'
ErrFileToLarge: 'O arquivo é maior que 10M e não pode ser aberto' ErrFileToLarge: 'O arquivo é maior que 10M e não pode ser aberto'
@@ -164,6 +180,8 @@ FileDropFailed: 'Falha ao limpar arquivo {{ .name }}: {{ .err }}'
FileDropSuccess: 'Arquivo {{ .name }} limpo com sucesso, {{ .count }} arquivos removidos, {{ .size }} de espaço em disco liberado' FileDropSuccess: 'Arquivo {{ .name }} limpo com sucesso, {{ .count }} arquivos removidos, {{ .size }} de espaço em disco liberado'
FileDropSum: 'Limpeza de arquivos concluída com sucesso, total de {{ .count }} arquivos removidos, total de {{ .size }} de espaço em disco liberado' FileDropSum: 'Limpeza de arquivos concluída com sucesso, total de {{ .count }} arquivos removidos, total de {{ .size }} de espaço em disco liberado'
ErrBadDecrypt: 'Erro de senha de descriptografia do pacote compactado, descompactação falhou, verifique e' ErrBadDecrypt: 'Erro de senha de descriptografia do pacote compactado, descompactação falhou, verifique e'
# site
ErrAliasIsExist: 'Alias já existe' ErrAliasIsExist: 'Alias já existe'
ErrBackupMatch: 'O arquivo de backup não corresponde a alguns dados atuais do site {{ .detail }}' ErrBackupMatch: 'O arquivo de backup não corresponde a alguns dados atuais do site {{ .detail }}'
ErrBackupExist: 'A parte correspondente dos dados de origem no arquivo de backup não existe {{ .detail }}' ErrBackupExist: 'A parte correspondente dos dados de origem no arquivo de backup não existe {{ .detail }}'
@@ -193,6 +211,8 @@ delete: 'Excluir'
ErrDefaultWebsite: 'O site padrão já foi definido, cancele-o antes de definir' ErrDefaultWebsite: 'O site padrão já foi definido, cancele-o antes de definir'
SSL: 'Certificado' SSL: 'Certificado'
Set: 'Configurações' Set: 'Configurações'
# certificado SSL
ErrSSLCannotDelete: 'O certificado {{ .name }} está sendo usado por um site e não pode ser excluído' ErrSSLCannotDelete: 'O certificado {{ .name }} está sendo usado por um site e não pode ser excluído'
ErrAccountCannotDelete: 'A conta está associada a um certificado e não pode ser excluída' ErrAccountCannotDelete: 'A conta está associada a um certificado e não pode ser excluída'
ErrSSLApply: 'Renovação do certificado concluída, mas a recarga do OpenResty falhou. Verifique a configuração' ErrSSLApply: 'Renovação do certificado concluída, mas a recarga do OpenResty falhou. Verifique a configuração'
@@ -227,6 +247,8 @@ ErrApplySSLCanNotDelete: 'O certificado {{ .name }} que está sendo solicitado n
StartPushSSLToNode: 'Iniciando o envio do certificado para o nó' StartPushSSLToNode: 'Iniciando o envio do certificado para o nó'
PushSSLToNodeFailed: 'Falha ao enviar o certificado para o nó: {{ .err }}' PushSSLToNodeFailed: 'Falha ao enviar o certificado para o nó: {{ .err }}'
PushSSLToNodeSuccess: 'Certificado enviado com sucesso para o nó' PushSSLToNodeSuccess: 'Certificado enviado com sucesso para o nó'
# MySQL
ErrUserIsExist: 'O usuário atual já existe, digite novamente' ErrUserIsExist: 'O usuário atual já existe, digite novamente'
ErrDatabaseIsExist: 'O banco de dados atual já existe, digite novamente' ErrDatabaseIsExist: 'O banco de dados atual já existe, digite novamente'
ErrExecTimeOut: 'Tempo limite de execução do SQL expirou, verifique o banco de dados' ErrExecTimeOut: 'Tempo limite de execução do SQL expirou, verifique o banco de dados'
@@ -235,7 +257,11 @@ ErrLocalExist: 'O nome já existe no banco de dados local, modifique-o e'
RemoteBackup: 'Para fazer backup do banco de dados remoto, o serviço de banco de dados do contêiner local precisa ser iniciado primeiro usando a imagem {{ .name }} aguarde...' RemoteBackup: 'Para fazer backup do banco de dados remoto, o serviço de banco de dados do contêiner local precisa ser iniciado primeiro usando a imagem {{ .name }} aguarde...'
RemoteRecover: 'Para restaurar o banco de dados remoto, o serviço de banco de dados do contêiner local precisa ser iniciado primeiro usando a imagem {{ .name }} aguarde...' RemoteRecover: 'Para restaurar o banco de dados remoto, o serviço de banco de dados do contêiner local precisa ser iniciado primeiro usando a imagem {{ .name }} aguarde...'
Arg: 'Argumento' Arg: 'Argumento'
# Redis
ErrTypeOfRedis: 'O tipo de arquivo de recuperação não corresponde ao método de persistência atual, modifique-o e' ErrTypeOfRedis: 'O tipo de arquivo de recuperação não corresponde ao método de persistência atual, modifique-o e'
# contêiner
ErrInUsed: '{{ .detail }} está em uso e não pode ser excluído' ErrInUsed: '{{ .detail }} está em uso e não pode ser excluído'
ErrObjectInUsed: 'Este objeto está em uso e não pode ser excluído' ErrObjectInUsed: 'Este objeto está em uso e não pode ser excluído'
ErrObjectBeDependent: 'Esta imagem é dependida por outras imagens e não pode ser excluída' ErrObjectBeDependent: 'Esta imagem é dependida por outras imagens e não pode ser excluída'
@@ -277,6 +303,8 @@ ComposeRecoverFiles: 'Restaurar arquivos do compose'
ComposeRecoverContainers: 'Restaurar contêineres do compose' ComposeRecoverContainers: 'Restaurar contêineres do compose'
ComposeRecoverRecord: 'Salvar registro do compose' ComposeRecoverRecord: 'Salvar registro do compose'
ComposeRecoverCleanup: 'Limpar área de restauração do compose' ComposeRecoverCleanup: 'Limpar área de restauração do compose'
# runtime
ErrFileNotExist: 'O arquivo {{ .detail }} não existe Verifique a integridade do arquivo de origem' ErrFileNotExist: 'O arquivo {{ .detail }} não existe Verifique a integridade do arquivo de origem'
ErrImageBuildErr: 'Falha na criação da imagem' ErrImageBuildErr: 'Falha na criação da imagem'
ErrImageExist: 'A imagem já existe, modifique o nome da imagem.' ErrImageExist: 'A imagem já existe, modifique o nome da imagem.'
@@ -289,12 +317,16 @@ ErrNodeModulesNotFound: 'A pasta node_modules não existe Edite o ambiente de ex
ErrContainerNameIsNull: 'O nome do contêiner não existe' ErrContainerNameIsNull: 'O nome do contêiner não existe'
ErrPHPPortIsDefault: 'A porta 9000 é a porta padrão. Altere-a e tente novamente' ErrPHPPortIsDefault: 'A porta 9000 é a porta padrão. Altere-a e tente novamente'
ErrPHPRuntimePortFailed: 'A porta {{ .name }} já está em uso neste runtime. Altere-a e tente novamente' ErrPHPRuntimePortFailed: 'A porta {{ .name }} já está em uso neste runtime. Altere-a e tente novamente'
# ferramenta
ErrConfigNotFound: 'O arquivo de configuração não existe' ErrConfigNotFound: 'O arquivo de configuração não existe'
ErrConfigParse: 'O formato do arquivo de configuração está incorreto' ErrConfigParse: 'O formato do arquivo de configuração está incorreto'
ErrConfigIsNull: 'O arquivo de configuração não pode estar vazio' ErrConfigIsNull: 'O arquivo de configuração não pode estar vazio'
ErrConfigDirNotFound: 'O diretório de execução não existe' ErrConfigDirNotFound: 'O diretório de execução não existe'
ErrConfigAlreadyExist: 'Um arquivo de configuração com o mesmo nome já existe' ErrConfigAlreadyExist: 'Um arquivo de configuração com o mesmo nome já existe'
ErrUserFindErr: 'Falha na pesquisa do usuário {{ .name }} {{ .err }}' ErrUserFindErr: 'Falha na pesquisa do usuário {{ .name }} {{ .err }}'
# tarefa cron
CutWebsiteLogSuccess: '{{ .name }} registro do site cortado com sucesso, caminho de backup {{ .path }}' CutWebsiteLogSuccess: '{{ .name }} registro do site cortado com sucesso, caminho de backup {{ .path }}'
HandleShell: 'Executar script {{ .name }}' HandleShell: 'Executar script {{ .name }}'
HandleCurl: 'Acessar URL {{ .name }}' HandleCurl: 'Acessar URL {{ .name }}'
@@ -313,6 +345,8 @@ NoSuchResource: 'Nenhum conteúdo de backup encontrado no banco de dados, ignora
CleanLog: 'Limpar log' CleanLog: 'Limpar log'
CleanLogByName: 'Limpar log de {{ .name }}' CleanLogByName: 'Limpar log de {{ .name }}'
WafIpGroupNotFound: 'Grupo de IP do WAF não encontrado., vá para [Recursos Avançados - WAF - Lista Branca/Preta - Grupo de IP] para adicionar um grupo de IP via método de download remoto.' WafIpGroupNotFound: 'Grupo de IP do WAF não encontrado., vá para [Recursos Avançados - WAF - Lista Branca/Preta - Grupo de IP] para adicionar um grupo de IP via método de download remoto.'
# caixa de ferramentas
ErrNotExistUser: 'O usuário atual não existe, modifique e' ErrNotExistUser: 'O usuário atual não existe, modifique e'
ErrBanAction: 'Falha na configuração. O serviço atual {{ .name }} não está disponível. Verifique e' ErrBanAction: 'Falha na configuração. O serviço atual {{ .name }} não está disponível. Verifique e'
ErrClamdscanNotFound: 'O comando clamdscan não foi detectado, consulte a documentação para instalá-lo' ErrClamdscanNotFound: 'O comando clamdscan não foi detectado, consulte a documentação para instalá-lo'
@@ -321,11 +355,15 @@ SetSwap: 'Configurar Swap {{ .path }} - {{ .size }}'
CreateSwap: 'Criar Arquivo Swap' CreateSwap: 'Criar Arquivo Swap'
FormatSwap: 'Formatar Arquivo Swap' FormatSwap: 'Formatar Arquivo Swap'
EnableSwap: 'Ativar Swap' EnableSwap: 'Ativar Swap'
# proteção contra adulteração
CleanTamperSetting: 'Limpar configurações de proteção históricas' CleanTamperSetting: 'Limpar configurações de proteção históricas'
SetTamperWithRules: 'Iniciar proteção de diretório de acordo com as regras' SetTamperWithRules: 'Iniciar proteção de diretório de acordo com as regras'
ProtectDir: 'Proteger diretório {{ .name }}' ProtectDir: 'Proteger diretório {{ .name }}'
IgnoreFile: 'Proteger arquivo {{ .name }}' IgnoreFile: 'Proteger arquivo {{ .name }}'
TamperSetSuccessful: 'Configurações de proteção concluídas, iniciando monitoramento dos seguintes diretórios:' TamperSetSuccessful: 'Configurações de proteção concluídas, iniciando monitoramento dos seguintes diretórios:'
# WAF
ErrScope: 'A modificação desta configuração não é suportada' ErrScope: 'A modificação desta configuração não é suportada'
ErrStateChange: 'Falha na alteração de estado' ErrStateChange: 'Falha na alteração de estado'
ErrRuleExist: 'A regra já existe' ErrRuleExist: 'A regra já existe'
@@ -380,6 +418,8 @@ OpenrestyNotFound: 'OpenResty não está instalado'
remoteIpIsNull: 'A lista de IP está vazia' remoteIpIsNull: 'A lista de IP está vazia'
OpenrestyVersionErr: 'A versão do OpenResty é muito antiga. Atualize para 1.27.1.2-2-2-focal' OpenrestyVersionErr: 'A versão do OpenResty é muito antiga. Atualize para 1.27.1.2-2-2-focal'
ErrFileTooLarge: 'O arquivo excede 1 MB e não pode ser enviado' ErrFileTooLarge: 'O arquivo excede 1 MB e não pode ser enviado'
# tarefa
TaskStart: '{{ .name }} A tarefa inicia [START]' TaskStart: '{{ .name }} A tarefa inicia [START]'
TaskEnd: '{{ .name }} Tarefa concluída [CONCLUÍDA]' TaskEnd: '{{ .name }} Tarefa concluída [CONCLUÍDA]'
TaskFailed: '{{ .name }} tarefa falhou' TaskFailed: '{{ .name }} tarefa falhou'
@@ -440,10 +480,17 @@ CustomAppstore: 'Armazém de aplicativos personalizados'
TaskExec: 'Executar' TaskExec: 'Executar'
TaskBatch: 'Operação em Lote' TaskBatch: 'Operação em Lote'
FileConvert: 'Conversão de Formato de Arquivo' FileConvert: 'Conversão de Formato de Arquivo'
# tarefa - ClamAV
Clamscan: 'Escanear {{ .name }}' Clamscan: 'Escanear {{ .name }}'
TaskScan: 'Escanear' TaskScan: 'Escanear'
# tarefa - IA
OllamaModelPull: 'Puxar modelo Ollama {{ .name }}' OllamaModelPull: 'Puxar modelo Ollama {{ .name }}'
OllamaModelSize: 'Obtenha o tamanho do modelo Ollama {{ .name }}' OllamaModelSize: 'Obtenha o tamanho do modelo Ollama {{ .name }}'
AIBenchmarkRun: "Executar benchmark de IA"
# tarefa - snapshot
Snapshot: 'Instantâneo' Snapshot: 'Instantâneo'
SnapDBInfo: 'Escrever informações do banco de dados 1Panel' SnapDBInfo: 'Escrever informações do banco de dados 1Panel'
SnapCopy: 'Copiar arquivos e diretórios {{ .name }}' SnapCopy: 'Copiar arquivos e diretórios {{ .name }}'
@@ -493,6 +540,8 @@ RecoverDaemonJson: 'Restaurar arquivo daemon.json de configuração do contêine
RecoverDBData: 'Recuperar dados do banco de dados' RecoverDBData: 'Recuperar dados do banco de dados'
RecoverBackups: 'Restaurar diretório de backup local' RecoverBackups: 'Restaurar diretório de backup local'
RecoverPanelData: 'Diretório de dados de recuperação' RecoverPanelData: 'Diretório de dados de recuperação'
# tarefa - contêiner
ContainerImagePull: 'Puxar imagem do contêiner {{ .name }}' ContainerImagePull: 'Puxar imagem do contêiner {{ .name }}'
ContainerRemoveOld: 'Remover o contêiner original {{ .name }}' ContainerRemoveOld: 'Remover o contêiner original {{ .name }}'
ContainerImageCheck: 'Verifique se a imagem é extraída normalmente' ContainerImageCheck: 'Verifique se a imagem é extraída normalmente'
@@ -501,6 +550,8 @@ ContainerRecreate: 'A atualização do contêiner falhou, agora iniciando a rest
ContainerCreate: 'Criar um novo contêiner {{ .name }}' ContainerCreate: 'Criar um novo contêiner {{ .name }}'
ContainerCreateFailed: 'Falha na criação do contêiner, exclua o contêiner com falha' ContainerCreateFailed: 'Falha na criação do contêiner, exclua o contêiner com falha'
ContainerStartCheck: 'Verifique se o contêiner foi iniciado' ContainerStartCheck: 'Verifique se o contêiner foi iniciado'
# tarefa - imagem
ImageBuild: 'Construção de imagem' ImageBuild: 'Construção de imagem'
ImagePull: 'Puxar imagem' ImagePull: 'Puxar imagem'
ImageRepoAuthFromDB: 'Obter informações de autenticação do repositório do banco de dados' ImageRepoAuthFromDB: 'Obter informações de autenticação do repositório do banco de dados'
@@ -508,6 +559,8 @@ ImagePush: 'Enviar imagem'
ImageRenameTag: 'Modificar tag de imagem' ImageRenameTag: 'Modificar tag de imagem'
ImageNewTag: 'Nova tag de imagem {{ .name }}' ImageNewTag: 'Nova tag de imagem {{ .name }}'
ComposeCreate: 'Criar uma composição' ComposeCreate: 'Criar uma composição'
# tarefa - site
BackupNginxConfig: 'Fazer backup do arquivo de configuração do OpenResty do site' BackupNginxConfig: 'Fazer backup do arquivo de configuração do OpenResty do site'
CompressFileSuccess: 'Diretório compactado com sucesso, compactado para {{ .name }}' CompressFileSuccess: 'Diretório compactado com sucesso, compactado para {{ .name }}'
CompressDir: 'Diretório de compressão' CompressDir: 'Diretório de compressão'
@@ -518,8 +571,15 @@ websiteDir: 'Diretório de sites'
RecoverFailedStartRollBack: 'Falha na recuperação, iniciar reversão' RecoverFailedStartRollBack: 'Falha na recuperação, iniciar reversão'
AppBackupFileIncomplete: 'O arquivo de backup está incompleto e não contém os arquivos app.json ou app.tar.gz' AppBackupFileIncomplete: 'O arquivo de backup está incompleto e não contém os arquivos app.json ou app.tar.gz'
AppAttributesNotMatch: 'O tipo ou nome do aplicativo não corresponde' AppAttributesNotMatch: 'O tipo ou nome do aplicativo não corresponde'
# alerta
ErrAlertMethodNotSupported: 'Esta versão não oferece suporte a este método de alerta'
ErrAlertSync: 'Erro de sincronização de informações de alarme, verifique e' ErrAlertSync: 'Erro de sincronização de informações de alarme, verifique e'
# tarefa - runtime
ErrInstallExtension: 'Já existe uma tarefa de instalação em andamento, aguarde a conclusão da tarefa' ErrInstallExtension: 'Já existe uma tarefa de instalação em andamento, aguarde a conclusão da tarefa'
# modelo de e-mail de alerta
PanelAlertTitle: 'Notificação de Alerta do Painel' PanelAlertTitle: 'Notificação de Alerta do Painel'
TestAlertTitle: 'E-mail de Teste - Verificar Conectividade de E-mail' TestAlertTitle: 'E-mail de Teste - Verificar Conectividade de E-mail'
TestAlert: 'Este é um e-mail de teste para verificar se sua configuração de envio de e-mails está correta.' TestAlert: 'Este é um e-mail de teste para verificar se sua configuração de envio de e-mails está correta.'
@@ -536,6 +596,8 @@ CommonAlert: 'Seu Painel {{ .node }}{{ .ip }}, {{ .msg }}. Faça login no painel
NodeExceptionAlert: 'Seu Painel {{ .node }}{{ .ip }}, {{ .num }} nós estão anormais. Faça login no painel para obter detalhes.' NodeExceptionAlert: 'Seu Painel {{ .node }}{{ .ip }}, {{ .num }} nós estão anormais. Faça login no painel para obter detalhes.'
LicenseExceptionAlert: 'Seu Painel {{ .node }}{{ .ip }}, {{ .num }} licenças estão anormais. Faça login no painel para obter detalhes.' LicenseExceptionAlert: 'Seu Painel {{ .node }}{{ .ip }}, {{ .num }} licenças estão anormais. Faça login no painel para obter detalhes.'
SSHAndPanelLoginAlert: 'Seu Painel {{ .node }}{{ .ip }}, o login {{ .name }} a partir de {{ .loginIp }} é anormal. Faça login no painel para obter detalhes.' SSHAndPanelLoginAlert: 'Seu Painel {{ .node }}{{ .ip }}, o login {{ .name }} a partir de {{ .loginIp }} é anormal. Faça login no painel para obter detalhes.'
# disco
DeviceNotFound: 'Dispositivo {{ .name }} não encontrado' DeviceNotFound: 'Dispositivo {{ .name }} não encontrado'
DeviceIsMounted: 'Dispositivo {{ .name }} está montado desmonte primeiro' DeviceIsMounted: 'Dispositivo {{ .name }} está montado desmonte primeiro'
PartitionDiskErr: 'Falha ao particionar, {{ .err }}' PartitionDiskErr: 'Falha ao particionar, {{ .err }}'
@@ -548,4 +610,13 @@ TerminalAIBlockedRiskyCommand: 'Comando de risco bloqueado: {{ .command }}'
TerminalAIThinking: 'A IA está pensando...' TerminalAIThinking: 'A IA está pensando...'
TerminalAIReadyToExecute: 'Pensamento concluído, pressione Enter para executar (duração: {{ .duration }}, token: {{ .tokens }})' TerminalAIReadyToExecute: 'Pensamento concluído, pressione Enter para executar (duração: {{ .duration }}, token: {{ .tokens }})'
TerminalAIRequestFailed: 'Falha na solicitação de AI: {{ .err }}' TerminalAIRequestFailed: 'Falha na solicitação de AI: {{ .err }}'
FileAISearchEmptyDir: 'Nenhum arquivo ou pasta encontrado neste caminho (ou todos foram filtrados).'
# gateway de IA
ErrAIProxyServiceNotInstalled: 'O serviço {{ .name }} não está instalado'
ErrAIProxyModelAccountNotFound: 'Conta de modelo {{ .id }} não encontrada'
ErrAIProxyModelMapRequired: 'Este campo é obrigatório.'
ErrAIProxyModelMapInvalid: 'O mapeamento de modelos deve ser um objeto JSON válido: {{ .err }}'
ErrAIProxyModelMapEmpty: 'O mapeamento de modelos não pode estar vazio'
ErrAIProxyModelMapEmptyExternalModel: 'O mapeamento de modelos contém um modelo solicitado vazio'
ErrAIProxyModelMapEmptyUpstreamModel: 'O modelo upstream de {{ .model }} não pode estar vazio'
AIProxyUserFallback: 'Usuário excluído (ID: {{ .id }})'
+92 -21
View File
@@ -1,29 +1,47 @@
# базовые ошибки
ErrInvalidParams: 'Неверный запрос: {{ .detail }}' ErrInvalidParams: 'Неверный запрос: {{ .detail }}'
ErrTokenParse: 'Ошибка токена: {{ .detail }}' ErrTokenParse: 'Ошибка токена: {{ .detail }}'
ErrInitialPassword: 'Исходный пароль неверен' ErrInitialPassword: 'Исходный пароль неверен'
ErrInternalServer: 'Внутренняя ошибка: {{ .detail }}' ErrInternalServer: 'Внутренняя ошибка: {{ .detail }}'
ErrRecordExist: 'Запись уже существует'
ErrRecordNotFound: 'Запись не найдена'
ErrStructTransform: 'Ошибка преобразования: {{ .err }}'
ErrNotSupportType: 'Тип не поддерживается: {{ .name }}'
# файловый AI
ErrFileAINotEnabled: 'Поиск с AI в файлах выключен или не выбран аккаунт. В управлении файлами откройте «AI-аккаунт», включите и выберите аккаунт.' ErrFileAINotEnabled: 'Поиск с AI в файлах выключен или не выбран аккаунт. В управлении файлами откройте «AI-аккаунт», включите и выберите аккаунт.'
ErrFileAISearchBadPattern: 'Недопустимый шаблон поиска (regex и т.п.): {{ .detail }}' ErrFileAISearchBadPattern: 'Недопустимый шаблон поиска (regex и т.п.): {{ .detail }}'
FileAISearchEmptyDir: 'В этом пути нет файлов или каталогов для отображения (или все отфильтрованы).'
# удаленная загрузка
ErrWgetRemoteFailed: 'Неверный или недоступный URL удалённой загрузки: {{ .detail }}' ErrWgetRemoteFailed: 'Неверный или недоступный URL удалённой загрузки: {{ .detail }}'
ErrWgetInvalidContentType: 'Удалённый сервер вернул не файл (возможно, страницу ошибки), {{ .detail }}' ErrWgetInvalidContentType: 'Удалённый сервер вернул не файл (возможно, страницу ошибки), {{ .detail }}'
ErrWgetProxyNotConfigured: 'Сначала настройте прокси-сервер в настройках панели' ErrWgetProxyNotConfigured: 'Сначала настройте прокси-сервер в настройках панели'
ErrWgetProxyInvalid: 'Недопустимый адрес прокси-сервера: {{ .detail }}' ErrWgetProxyInvalid: 'Недопустимый адрес прокси-сервера: {{ .detail }}'
ErrRecordExist: 'Запись уже существует'
ErrRecordNotFound: 'Запись не найдена' # вход и безопасность
ErrStructTransform: 'Ошибка преобразования: {{ .err }}'
ErrNotLogin: 'Не авторизован: {{ .detail }}' ErrNotLogin: 'Не авторизован: {{ .detail }}'
ErrPasswordExpired: 'Пароль истёк: {{ .detail }}' ErrPasswordExpired: 'Пароль истёк: {{ .detail }}'
ErrNotSupportType: 'Тип не поддерживается: {{ .name }}'
ErrAlertMethodNotSupported: 'Эта версия не поддерживает данный способ оповещения' # запрос и API
ErrProxy: 'Запрос не удался: {{ .detail }}' ErrProxy: 'Запрос не удался: {{ .detail }}'
ErrApiConfigStatusInvalid: 'API отключено: {{ .detail }}' ErrApiConfigStatusInvalid: 'API отключено: {{ .detail }}'
ErrApiConfigKeyInvalid: 'Неверный API-ключ: {{ .detail }}' ErrApiConfigKeyInvalid: 'Неверный API-ключ: {{ .detail }}'
ErrApiConfigIPInvalid: 'IP не в списке: {{ .detail }}' ErrApiConfigIPInvalid: 'IP не в списке: {{ .detail }}'
ErrApiConfigDisable: 'Доступ по API запрещён: {{ .detail }}' ErrApiConfigDisable: 'Доступ по API запрещён: {{ .detail }}'
ErrApiConfigKeyTimeInvalid: 'Неверная метка времени: {{ .detail }}' ErrApiConfigKeyTimeInvalid: 'Неверная метка времени: {{ .detail }}'
ErrShutDown: 'Команда остановлена вручную' ErrCreateHttpClient: 'Не удалось создать запрос {{ .err }}'
ErrHttpReqTimeOut: 'Истекло время ожидания запроса {{ .err }}'
ErrHttpReqFailed: 'Запрос не выполнен {{ .err }}'
ErrNoSuchHost: 'Не удалось найти запрошенный сервер {{ .err }}'
ErrHttpReqNotFound: 'Запрошенный ресурс {{ .err }} не найден'
# быстрый переход
ErrMinQuickJump: 'Добавьте хотя бы одну быструю ссылку' ErrMinQuickJump: 'Добавьте хотя бы одну быструю ссылку'
ErrMaxQuickJump: 'Не более 4 быстрых ссылок' ErrMaxQuickJump: 'Не более 4 быстрых ссылок'
# общее
ErrShutDown: 'Команда остановлена вручную'
ErrUsernameIsExist: 'Имя пользователя занято' ErrUsernameIsExist: 'Имя пользователя занято'
ErrNameIsExist: 'Имя уже занято' ErrNameIsExist: 'Имя уже занято'
ErrDemoEnvironment: 'Недоступно в демо' ErrDemoEnvironment: 'Недоступно в демо'
@@ -41,6 +59,8 @@ SystemRestart: 'Задача прервана из-за перезапуска
ErrGroupIsDefault: 'Группа по умолчанию, не может быть удалена' ErrGroupIsDefault: 'Группа по умолчанию, не может быть удалена'
ErrGroupIsInWebsiteUse: 'Группа используется другим веб-сайтом и не может быть удалена.' ErrGroupIsInWebsiteUse: 'Группа используется другим веб-сайтом и не может быть удалена.'
Decrypt: 'Расшифровать' Decrypt: 'Расшифровать'
# агент
ErrAgentAccountBound: 'Акаунт привязан к агенту' ErrAgentAccountBound: 'Акаунт привязан к агенту'
ErrTerminalAIAccountInUse: 'Эта учетная запись модели сейчас используется Terminal AI. Смените учетную запись в настройках Terminal AI или отключите Terminal AI и повторите попытку.' ErrTerminalAIAccountInUse: 'Эта учетная запись модели сейчас используется Terminal AI. Смените учетную запись в настройках Terminal AI или отключите Terminal AI и повторите попытку.'
ErrAgentAccountUnavailable: 'Связь с аккаунтом недоступна: {{ .err }}' ErrAgentAccountUnavailable: 'Связь с аккаунтом недоступна: {{ .err }}'
@@ -65,14 +85,8 @@ ErrAgentWebsiteInUse: 'Этот сайт уже связан с другим а
ErrAgentWebsiteUnbindUnsupported: 'Сайты one-click deployment нельзя отвязать вручную' ErrAgentWebsiteUnbindUnsupported: 'Сайты one-click deployment нельзя отвязать вручную'
ErrHermesPairingCodeUnavailable: 'Код сопряжения временно недоступен в Hermes, возможно из-за проблем с сетью. Повторите попытку позже.' ErrHermesPairingCodeUnavailable: 'Код сопряжения временно недоступен в Hermes, возможно из-за проблем с сетью. Повторите попытку позже.'
ErrHermesFeishuGroupAllowlistRequiresAllowlist: 'Когда групповая политика Feishu — белый список, политика личных сообщений не может быть кодом сопряжения.' ErrHermesFeishuGroupAllowlistRequiresAllowlist: 'Когда групповая политика Feishu — белый список, политика личных сообщений не может быть кодом сопряжения.'
ErrAIProxyServiceNotInstalled: 'Сервис {{ .name }} не установлен'
ErrAIProxyModelAccountNotFound: 'Аккаунт модели {{ .id }} не найден' # резервное копирование и настройки оповещений
ErrAIProxyModelMapRequired: 'Это поле обязательно.'
ErrAIProxyModelMapInvalid: 'Сопоставление моделей должно быть допустимым JSON-объектом: {{ .err }}'
ErrAIProxyModelMapEmpty: 'Сопоставление моделей не может быть пустым'
ErrAIProxyModelMapEmptyExternalModel: 'Сопоставление моделей содержит пустую запрошенную модель'
ErrAIProxyModelMapEmptyUpstreamModel: 'Upstream-модель для {{ .model }} не может быть пустой'
AIProxyUserFallback: 'Пользователь {{ .id }}'
Localhost: 'Локальная машина' Localhost: 'Локальная машина'
ErrBackupInUsed: 'Аккаунт бэкапа занят задачей' ErrBackupInUsed: 'Аккаунт бэкапа занят задачей'
ErrBackupCheck: 'Проверка подключения не удалась: {{ .err }}' ErrBackupCheck: 'Проверка подключения не удалась: {{ .err }}'
@@ -80,6 +94,8 @@ ErrBackupLocalDelete: 'Нельзя удалить локальные бэкап
ErrBackupLocalCreate: 'Нельзя создать локальные бэкапы' ErrBackupLocalCreate: 'Нельзя создать локальные бэкапы'
ErrAlertConfigInUse: 'Конфигурация оповещений используется и не может быть удалена' ErrAlertConfigInUse: 'Конфигурация оповещений используется и не может быть удалена'
ErrAlertConfigPhoneExist: 'Номер телефона уже существует' ErrAlertConfigPhoneExist: 'Номер телефона уже существует'
# приложение
ErrPortInUsed: '{{ .detail }} порт уже занят' ErrPortInUsed: '{{ .detail }} порт уже занят'
ErrAppLimit: 'Количество установленных приложений превысило лимит' ErrAppLimit: 'Количество установленных приложений превысило лимит'
ErrNotInstall: 'Приложение не установлено' ErrNotInstall: 'Приложение не установлено'
@@ -97,16 +113,12 @@ ErrFileParseApp: '{{ .name }} анализ файла не удался {{ .err
ErrAppDirNull: 'Папка версии не существует' ErrAppDirNull: 'Папка версии не существует'
LocalAppErr: 'Синхронизация приложения {{ .name }} не удалась {{ .err }}' LocalAppErr: 'Синхронизация приложения {{ .name }} не удалась {{ .err }}'
ErrContainerName: 'Имя контейнера уже существует' ErrContainerName: 'Имя контейнера уже существует'
ErrCreateHttpClient: 'Не удалось создать запрос {{ .err }}'
ErrHttpReqTimeOut: 'Истекло время ожидания запроса {{ .err }}'
ErrHttpReqFailed: 'Запрос не выполнен {{ .err }}'
ErrNoSuchHost: 'Не удалось найти запрошенный сервер {{ .err }}'
ErrHttpReqNotFound: 'Запрошенный ресурс {{ .err }} не найден'
ErrContainerNotFound: 'Контейнер {{ .name }} не существует' ErrContainerNotFound: 'Контейнер {{ .name }} не существует'
ErrContainerMsg: 'Контейнер {{ .name }} ненормален. Подробности смотрите в журнале на странице контейнера.' ErrContainerMsg: 'Контейнер {{ .name }} ненормален. Подробности смотрите в журнале на странице контейнера.'
ErrAppBackup: '{{ .name }} резервное копирование приложения не удалось {{ .err }}' ErrAppBackup: '{{ .name }} резервное копирование приложения не удалось {{ .err }}'
ErrVersionTooLow: 'Текущая версия 1Panel слишком низкая для обновления App Store. Пожалуйста, обновите версию перед началом работы.' ErrVersionTooLow: 'Текущая версия 1Panel слишком низкая для обновления App Store. Пожалуйста, обновите версию перед началом работы.'
ErrAppNameExist: 'Имя приложения уже существует' ErrAppNameExist: 'Имя приложения уже существует'
ErrAppInstallNameExist: 'Имя установки приложения {{ .name }} уже существует'
AppStoreIsSyncing: 'App Store синхронизируется, повторите попытку позже' AppStoreIsSyncing: 'App Store синхронизируется, повторите попытку позже'
ErrGetCompose: 'Не удалось получить файл docker-compose.yml {{ .detail }}' ErrGetCompose: 'Не удалось получить файл docker-compose.yml {{ .detail }}'
ErrAppWarn: 'Ненормальное состояние, проверьте журнал' ErrAppWarn: 'Ненормальное состояние, проверьте журнал'
@@ -131,6 +143,8 @@ ErrDockerFailed: 'Состояние Docker аномально, проверьт
ErrDockerComposeCmdNotFound: 'Команда Docker Compose отсутствует, пожалуйста, установите эту команду на хост-машине сначала' ErrDockerComposeCmdNotFound: 'Команда Docker Compose отсутствует, пожалуйста, установите эту команду на хост-машине сначала'
UseExistImage: 'Образ уже существует, используется существующий образ' UseExistImage: 'Образ уже существует, используется существующий образ'
ErrDatabaseNotFound: 'База данных {{ .name }} не существует' ErrDatabaseNotFound: 'База данных {{ .name }} не существует'
# SSH
ExportIP: 'IP входа' ExportIP: 'IP входа'
ExportArea: 'Местоположение' ExportArea: 'Местоположение'
ExportPort: 'Порт' ExportPort: 'Порт'
@@ -138,6 +152,8 @@ ExportAuthMode: 'Способ входа'
ExportUser: 'Пользователь' ExportUser: 'Пользователь'
ExportStatus: 'Статус входа' ExportStatus: 'Статус входа'
ExportDate: 'Время' ExportDate: 'Время'
# файл
ErrFileCanNotRead: 'Этот файл не поддерживает предварительный просмотр' ErrFileCanNotRead: 'Этот файл не поддерживает предварительный просмотр'
ErrSensitiveFileRead: 'Чтение конфиденциальных файлов запрещено' ErrSensitiveFileRead: 'Чтение конфиденциальных файлов запрещено'
ErrFileToLarge: 'Файл больше 10 МБ и не может быть открыт' ErrFileToLarge: 'Файл больше 10 МБ и не может быть открыт'
@@ -164,6 +180,8 @@ FileDropFailed: 'Не удалось очистить файл {{ .name }}: {{ .
FileDropSuccess: 'Файл {{ .name }} успешно очищен, удалено {{ .count }} файлов, освобождено {{ .size }} дискового пространства' FileDropSuccess: 'Файл {{ .name }} успешно очищен, удалено {{ .count }} файлов, освобождено {{ .size }} дискового пространства'
FileDropSum: 'Очистка файлов завершена успешно, всего удалено {{ .count }} файлов, освобождено {{ .size }} дискового пространства' FileDropSum: 'Очистка файлов завершена успешно, всего удалено {{ .count }} файлов, освобождено {{ .size }} дискового пространства'
ErrBadDecrypt: 'Ошибка пароля расшифровки сжатого пакета, распаковка не удалась, проверьте и повторите попытку' ErrBadDecrypt: 'Ошибка пароля расшифровки сжатого пакета, распаковка не удалась, проверьте и повторите попытку'
# сайт
ErrAliasIsExist: 'Псевдоним уже существует' ErrAliasIsExist: 'Псевдоним уже существует'
ErrBackupMatch: 'Файл резервной копии не соответствует некоторым текущим данным веб-сайта {{ .detail }}' ErrBackupMatch: 'Файл резервной копии не соответствует некоторым текущим данным веб-сайта {{ .detail }}'
ErrBackupExist: 'Соответствующая часть исходных данных в файле резервной копии не существует {{ .detail }}' ErrBackupExist: 'Соответствующая часть исходных данных в файле резервной копии не существует {{ .detail }}'
@@ -193,6 +211,8 @@ delete: 'Удалить'
ErrDefaultWebsite: 'Веб-сайт по умолчанию уже установлен, отмените его перед настройкой' ErrDefaultWebsite: 'Веб-сайт по умолчанию уже установлен, отмените его перед настройкой'
SSL: 'Сертификат' SSL: 'Сертификат'
Set: 'Настройки' Set: 'Настройки'
# SSL-сертификат
ErrSSLCannotDelete: 'Сертификат {{ .name }} используется веб-сайтом и не может быть удален' ErrSSLCannotDelete: 'Сертификат {{ .name }} используется веб-сайтом и не может быть удален'
ErrAccountCannotDelete: 'Учетная запись связана с сертификатом и не может быть удалена' ErrAccountCannotDelete: 'Учетная запись связана с сертификатом и не может быть удалена'
ErrSSLApply: 'Обновление сертификата прошло успешно, перезагрузка OpenResty не удалась, проверьте конфигурацию' ErrSSLApply: 'Обновление сертификата прошло успешно, перезагрузка OpenResty не удалась, проверьте конфигурацию'
@@ -227,6 +247,8 @@ ErrApplySSLCanNotDelete: 'Нельзя удалить сертификат {{ .n
StartPushSSLToNode: 'Начало отправки сертификата на узел' StartPushSSLToNode: 'Начало отправки сертификата на узел'
PushSSLToNodeFailed: 'Не удалось отправить сертификат на узел: {{ .err }}' PushSSLToNodeFailed: 'Не удалось отправить сертификат на узел: {{ .err }}'
PushSSLToNodeSuccess: 'Сертификат успешно отправлен на узел' PushSSLToNodeSuccess: 'Сертификат успешно отправлен на узел'
# MySQL
ErrUserIsExist: 'Текущий пользователь уже существует, пожалуйста, введите еще раз' ErrUserIsExist: 'Текущий пользователь уже существует, пожалуйста, введите еще раз'
ErrDatabaseIsExist: 'Текущая база данных уже существует, пожалуйста, введите ее повторно' ErrDatabaseIsExist: 'Текущая база данных уже существует, пожалуйста, введите ее повторно'
ErrExecTimeOut: 'Время выполнения SQL истекло, проверьте базу данных' ErrExecTimeOut: 'Время выполнения SQL истекло, проверьте базу данных'
@@ -235,7 +257,11 @@ ErrLocalExist: 'Имя уже существует в локальной баз
RemoteBackup: 'Для резервного копирования удаленной базы данных необходимо сначала запустить службу базы данных локального контейнера с помощью образа {{ .name }}, пожалуйста, подождите...' RemoteBackup: 'Для резервного копирования удаленной базы данных необходимо сначала запустить службу базы данных локального контейнера с помощью образа {{ .name }}, пожалуйста, подождите...'
RemoteRecover: 'Для восстановления удаленной базы данных необходимо сначала запустить службу базы данных локального контейнера с помощью образа {{ .name }}, пожалуйста, подождите...' RemoteRecover: 'Для восстановления удаленной базы данных необходимо сначала запустить службу базы данных локального контейнера с помощью образа {{ .name }}, пожалуйста, подождите...'
Arg: 'Аргумент' Arg: 'Аргумент'
# Redis
ErrTypeOfRedis: 'Тип файла восстановления не соответствует текущему методу сохранения. Измените его и повторите попытку' ErrTypeOfRedis: 'Тип файла восстановления не соответствует текущему методу сохранения. Измените его и повторите попытку'
# контейнер
ErrInUsed: '{{ .detail }} используется и не может быть удалено' ErrInUsed: '{{ .detail }} используется и не может быть удалено'
ErrObjectInUsed: 'Этот объект используется и не может быть удален' ErrObjectInUsed: 'Этот объект используется и не может быть удален'
ErrObjectBeDependent: 'Этот образ зависит от других образов и не может быть удален' ErrObjectBeDependent: 'Этот образ зависит от других образов и не может быть удален'
@@ -277,6 +303,8 @@ ComposeRecoverFiles: 'Восстановить файлы compose'
ComposeRecoverContainers: 'Восстановить контейнеры compose' ComposeRecoverContainers: 'Восстановить контейнеры compose'
ComposeRecoverRecord: 'Сохранить запись compose' ComposeRecoverRecord: 'Сохранить запись compose'
ComposeRecoverCleanup: 'Очистить рабочую область восстановления compose' ComposeRecoverCleanup: 'Очистить рабочую область восстановления compose'
# среда выполнения
ErrFileNotExist: 'Файл {{ .detail }} не существует Проверьте целостность исходного файла' ErrFileNotExist: 'Файл {{ .detail }} не существует Проверьте целостность исходного файла'
ErrImageBuildErr: 'Сборка образа не удалась' ErrImageBuildErr: 'Сборка образа не удалась'
ErrImageExist: 'Изображение уже существует Пожалуйста, измените имя изображения.' ErrImageExist: 'Изображение уже существует Пожалуйста, измените имя изображения.'
@@ -289,12 +317,16 @@ ErrNodeModulesNotFound: 'Папка node_modules не существует Из
ErrContainerNameIsNull: 'Имя контейнера не существует' ErrContainerNameIsNull: 'Имя контейнера не существует'
ErrPHPPortIsDefault: 'Порт 9000 зарезервирован как стандартный. Укажите другой порт' ErrPHPPortIsDefault: 'Порт 9000 зарезервирован как стандартный. Укажите другой порт'
ErrPHPRuntimePortFailed: 'Порт {{ .name }} уже используется этой средой выполнения' ErrPHPRuntimePortFailed: 'Порт {{ .name }} уже используется этой средой выполнения'
# инструмент
ErrConfigNotFound: 'Файл конфигурации не существует' ErrConfigNotFound: 'Файл конфигурации не существует'
ErrConfigParse: 'Неверный формат файла конфигурации' ErrConfigParse: 'Неверный формат файла конфигурации'
ErrConfigIsNull: 'Файл конфигурации не может быть пустым' ErrConfigIsNull: 'Файл конфигурации не может быть пустым'
ErrConfigDirNotFound: 'Рабочий каталог не существует' ErrConfigDirNotFound: 'Рабочий каталог не существует'
ErrConfigAlreadyExist: 'Файл конфигурации с таким именем уже существует' ErrConfigAlreadyExist: 'Файл конфигурации с таким именем уже существует'
ErrUserFindErr: 'Поиск пользователя {{ .name }} не удался {{ .err }}' ErrUserFindErr: 'Поиск пользователя {{ .name }} не удался {{ .err }}'
# задание cron
CutWebsiteLogSuccess: 'Журнал веб-сайта {{ .name }} успешно вырезан, путь к резервной копии {{ .path }}' CutWebsiteLogSuccess: 'Журнал веб-сайта {{ .name }} успешно вырезан, путь к резервной копии {{ .path }}'
HandleShell: 'Выполнить скрипт {{ .name }}' HandleShell: 'Выполнить скрипт {{ .name }}'
HandleCurl: 'Доступ к URL {{ .name }}' HandleCurl: 'Доступ к URL {{ .name }}'
@@ -313,6 +345,8 @@ NoSuchResource: 'В базе данных не найдено содержимо
CleanLog: 'Очистить журнал' CleanLog: 'Очистить журнал'
CleanLogByName: 'Очистить журнал {{ .name }}' CleanLogByName: 'Очистить журнал {{ .name }}'
WafIpGroupNotFound: 'Группа IP WAF не найдена. Пожалуйста, перейдите в [Расширенные функции - WAF - Черный/Белый список - Группа IP], чтобы добавить группу IP с помощью метода удаленной загрузки.' WafIpGroupNotFound: 'Группа IP WAF не найдена. Пожалуйста, перейдите в [Расширенные функции - WAF - Черный/Белый список - Группа IP], чтобы добавить группу IP с помощью метода удаленной загрузки.'
# панель инструментов
ErrNotExistUser: 'Текущий пользователь не существует, измените его и повторите попытку' ErrNotExistUser: 'Текущий пользователь не существует, измените его и повторите попытку'
ErrBanAction: 'Настройка не удалась. Текущая служба {{ .name }} недоступна. Проверьте и повторите попытку' ErrBanAction: 'Настройка не удалась. Текущая служба {{ .name }} недоступна. Проверьте и повторите попытку'
ErrClamdscanNotFound: 'Команда clamdscan не обнаружена, обратитесь к документации, чтобы установить ее' ErrClamdscanNotFound: 'Команда clamdscan не обнаружена, обратитесь к документации, чтобы установить ее'
@@ -321,11 +355,15 @@ SetSwap: 'Настроить Swap {{ .path }} - {{ .size }}'
CreateSwap: 'Создать Файл Swap' CreateSwap: 'Создать Файл Swap'
FormatSwap: 'Форматировать Файл Swap' FormatSwap: 'Форматировать Файл Swap'
EnableSwap: 'Включить Swap' EnableSwap: 'Включить Swap'
# защита от изменений
CleanTamperSetting: 'Очистить исторические настройки защиты' CleanTamperSetting: 'Очистить исторические настройки защиты'
SetTamperWithRules: 'Запустить защиту каталога согласно правилам' SetTamperWithRules: 'Запустить защиту каталога согласно правилам'
ProtectDir: 'Защитить каталог {{ .name }}' ProtectDir: 'Защитить каталог {{ .name }}'
IgnoreFile: 'Защитить файл {{ .name }}' IgnoreFile: 'Защитить файл {{ .name }}'
TamperSetSuccessful: 'Настройки защиты завершены, начинаю мониторинг следующих каталогов:' TamperSetSuccessful: 'Настройки защиты завершены, начинаю мониторинг следующих каталогов:'
# WAF
ErrScope: 'Изменение этой конфигурации не поддерживается' ErrScope: 'Изменение этой конфигурации не поддерживается'
ErrStateChange: 'He удалось изменить состояние' ErrStateChange: 'He удалось изменить состояние'
ErrRuleExist: 'Правило уже существует' ErrRuleExist: 'Правило уже существует'
@@ -380,6 +418,8 @@ OpenrestyNotFound: 'OpenResty не установлен'
remoteIpIsNull: 'Список IP пуст' remoteIpIsNull: 'Список IP пуст'
OpenrestyVersionErr: 'Версия OpenResty слишком старая. Обновите до 1.27.1.2-2-2-focal' OpenrestyVersionErr: 'Версия OpenResty слишком старая. Обновите до 1.27.1.2-2-2-focal'
ErrFileTooLarge: 'Файл больше 1 МБ и не может быть загружен' ErrFileTooLarge: 'Файл больше 1 МБ и не может быть загружен'
# задача
TaskStart: '{{ .name }} Задача начинается [START]' TaskStart: '{{ .name }} Задача начинается [START]'
TaskEnd: '{{ .name }} Задача выполнена [ЗАВЕРШЕНО]' TaskEnd: '{{ .name }} Задача выполнена [ЗАВЕРШЕНО]'
TaskFailed: 'Задача {{ .name }} не выполнена' TaskFailed: 'Задача {{ .name }} не выполнена'
@@ -440,10 +480,17 @@ CustomAppstore: 'Хранилище пользовательских прило
TaskExec: 'Выполнить' TaskExec: 'Выполнить'
TaskBatch: 'Пакетная операция' TaskBatch: 'Пакетная операция'
FileConvert: 'Преобразование формата файла' FileConvert: 'Преобразование формата файла'
# задача - ClamAV
Clamscan: 'Сканировать {{ .name }}' Clamscan: 'Сканировать {{ .name }}'
TaskScan: 'Сканировать' TaskScan: 'Сканировать'
# задача - AI
OllamaModelPull: 'Вытянуть модель Ollama {{ .name }}' OllamaModelPull: 'Вытянуть модель Ollama {{ .name }}'
OllamaModelSize: 'Получить размер модели Ollama {{ .name }}' OllamaModelSize: 'Получить размер модели Ollama {{ .name }}'
AIBenchmarkRun: "Выполнить тест производительности AI"
# задача - снимок
Snapshot: 'Снимок' Snapshot: 'Снимок'
SnapDBInfo: 'Запись информации о базе данных 1Panel' SnapDBInfo: 'Запись информации о базе данных 1Panel'
SnapCopy: 'Копировать файлы и каталоги {{ .name }}' SnapCopy: 'Копировать файлы и каталоги {{ .name }}'
@@ -493,6 +540,8 @@ RecoverDaemonJson: 'Восстановить файл конфигурации
RecoverDBData: 'Восстановить данные базы данных' RecoverDBData: 'Восстановить данные базы данных'
RecoverBackups: 'Восстановить локальный каталог резервных копий' RecoverBackups: 'Восстановить локальный каталог резервных копий'
RecoverPanelData: 'Каталог данных восстановления' RecoverPanelData: 'Каталог данных восстановления'
# задача - контейнер
ContainerImagePull: 'Извлечь изображение контейнера {{ .name }}' ContainerImagePull: 'Извлечь изображение контейнера {{ .name }}'
ContainerRemoveOld: 'Удалить исходный контейнер {{ .name }}' ContainerRemoveOld: 'Удалить исходный контейнер {{ .name }}'
ContainerImageCheck: 'Проверьте, нормально ли извлекается изображение' ContainerImageCheck: 'Проверьте, нормально ли извлекается изображение'
@@ -501,6 +550,8 @@ ContainerRecreate: 'Обновление контейнера не удалос
ContainerCreate: 'Создать новый контейнер {{ .name }}' ContainerCreate: 'Создать новый контейнер {{ .name }}'
ContainerCreateFailed: 'Создание контейнера не удалось, удалите неудавшийся контейнер' ContainerCreateFailed: 'Создание контейнера не удалось, удалите неудавшийся контейнер'
ContainerStartCheck: 'Проверить, запущен ли контейнер' ContainerStartCheck: 'Проверить, запущен ли контейнер'
# задача - образ
ImageBuild: 'Создание изображения' ImageBuild: 'Создание изображения'
ImagePull: 'Вытащить изображение' ImagePull: 'Вытащить изображение'
ImageRepoAuthFromDB: 'Получить информацию об аутентификации репозитория из базы данных' ImageRepoAuthFromDB: 'Получить информацию об аутентификации репозитория из базы данных'
@@ -508,6 +559,8 @@ ImagePush: 'Отправить изображение'
ImageRenameTag: 'Изменить тег изображения' ImageRenameTag: 'Изменить тег изображения'
ImageNewTag: 'Новый тег изображения {{ .name }}' ImageNewTag: 'Новый тег изображения {{ .name }}'
ComposeCreate: 'Создать композицию' ComposeCreate: 'Создать композицию'
# задача - сайт
BackupNginxConfig: 'Резервное копирование файла конфигурации OpenResty веб-сайта' BackupNginxConfig: 'Резервное копирование файла конфигурации OpenResty веб-сайта'
CompressFileSuccess: 'Каталог успешно сжат, сжат в {{ .name }}' CompressFileSuccess: 'Каталог успешно сжат, сжат в {{ .name }}'
CompressDir: 'Каталог сжатия' CompressDir: 'Каталог сжатия'
@@ -518,8 +571,15 @@ websiteDir: 'Каталог веб-сайтов'
RecoverFailedStartRollBack: 'Восстановление не удалось, начать откат' RecoverFailedStartRollBack: 'Восстановление не удалось, начать откат'
AppBackupFileIncomplete: 'Файл резервной копии неполный и в нем отсутствуют файлы app.json или app.tar.gz' AppBackupFileIncomplete: 'Файл резервной копии неполный и в нем отсутствуют файлы app.json или app.tar.gz'
AppAttributesNotMatch: 'Тип или имя приложения не совпадают' AppAttributesNotMatch: 'Тип или имя приложения не совпадают'
# оповещение
ErrAlertMethodNotSupported: 'Эта версия не поддерживает данный способ оповещения'
ErrAlertSync: 'Ошибка синхронизации информации о тревоге, проверьте и повторите попытку' ErrAlertSync: 'Ошибка синхронизации информации о тревоге, проверьте и повторите попытку'
# задача - среда выполнения
ErrInstallExtension: 'Уже выполняется задача установки, подождите, пока задача завершится' ErrInstallExtension: 'Уже выполняется задача установки, подождите, пока задача завершится'
# шаблон письма оповещения
PanelAlertTitle: 'Уведомление панели' PanelAlertTitle: 'Уведомление панели'
TestAlertTitle: 'Тестовое письмо - проверка подключения' TestAlertTitle: 'Тестовое письмо - проверка подключения'
TestAlert: 'Это тестовое письмо для проверки правильности настройки отправки писем.' TestAlert: 'Это тестовое письмо для проверки правильности настройки отправки писем.'
@@ -536,6 +596,8 @@ CommonAlert: 'Ваш панель {{ .node }}{{ .ip }}, {{ .msg }}. Войдит
NodeExceptionAlert: 'Ваш панель {{ .node }}{{ .ip }}, {{ .num }} узлов работают с ошибками. Войдите в панель для получения деталей.' NodeExceptionAlert: 'Ваш панель {{ .node }}{{ .ip }}, {{ .num }} узлов работают с ошибками. Войдите в панель для получения деталей.'
LicenseExceptionAlert: 'Ваш панель {{ .node }}{{ .ip }}, {{ .num }} лицензий имеют ошибки. Войдите в панель для получения деталей.' LicenseExceptionAlert: 'Ваш панель {{ .node }}{{ .ip }}, {{ .num }} лицензий имеют ошибки. Войдите в панель для получения деталей.'
SSHAndPanelLoginAlert: 'Ваш панель {{ .node }}{{ .ip }}, вход {{ .name }} с адреса {{ .loginIp }} является аномальным. Войдите в панель для получения деталей.' SSHAndPanelLoginAlert: 'Ваш панель {{ .node }}{{ .ip }}, вход {{ .name }} с адреса {{ .loginIp }} является аномальным. Войдите в панель для получения деталей.'
# диск
DeviceNotFound: 'Устройство {{ .name }} не найдено' DeviceNotFound: 'Устройство {{ .name }} не найдено'
DeviceIsMounted: 'Устройство {{ .name }} подключено, сначала отключите' DeviceIsMounted: 'Устройство {{ .name }} подключено, сначала отключите'
PartitionDiskErr: 'Не удалось разделить, {{ .err }}' PartitionDiskErr: 'Не удалось разделить, {{ .err }}'
@@ -543,9 +605,18 @@ FormatDiskErr: 'Не удалось отформатировать диск, {{
MountDiskErr: 'Не удалось подключить диск, {{ .err }}' MountDiskErr: 'Не удалось подключить диск, {{ .err }}'
XfsNotFound: 'Файловая система xfs не обнаружена, сначала установите xfsprogs' XfsNotFound: 'Файловая система xfs не обнаружена, сначала установите xfsprogs'
# terminal # терминал
TerminalAIBlockedRiskyCommand: 'Опасная команда заблокирована: {{ .command }}' TerminalAIBlockedRiskyCommand: 'Опасная команда заблокирована: {{ .command }}'
TerminalAIThinking: 'AI думает...' TerminalAIThinking: 'AI думает...'
TerminalAIReadyToExecute: 'Обдумывание завершено, нажмите Enter для выполнения (время: {{ .duration }}, token: {{ .tokens }})' TerminalAIReadyToExecute: 'Обдумывание завершено, нажмите Enter для выполнения (время: {{ .duration }}, token: {{ .tokens }})'
TerminalAIRequestFailed: 'Ошибка запроса AI: {{ .err }}' TerminalAIRequestFailed: 'Ошибка запроса AI: {{ .err }}'
FileAISearchEmptyDir: 'В этом пути нет файлов или каталогов для отображения (или все отфильтрованы).'
# AI-шлюз
ErrAIProxyServiceNotInstalled: 'Сервис {{ .name }} не установлен'
ErrAIProxyModelAccountNotFound: 'Аккаунт модели {{ .id }} не найден'
ErrAIProxyModelMapRequired: 'Это поле обязательно.'
ErrAIProxyModelMapInvalid: 'Сопоставление моделей должно быть допустимым JSON-объектом: {{ .err }}'
ErrAIProxyModelMapEmpty: 'Сопоставление моделей не может быть пустым'
ErrAIProxyModelMapEmptyExternalModel: 'Сопоставление моделей содержит пустую запрошенную модель'
ErrAIProxyModelMapEmptyUpstreamModel: 'Upstream-модель для {{ .model }} не может быть пустой'
AIProxyUserFallback: 'Удаленный пользователь (ID: {{ .id }})'
+91 -20
View File
@@ -1,29 +1,47 @@
# temel hatalar
ErrInvalidParams: 'İstek geçersiz: {{ .detail }}' ErrInvalidParams: 'İstek geçersiz: {{ .detail }}'
ErrTokenParse: 'Token hatası: {{ .detail }}' ErrTokenParse: 'Token hatası: {{ .detail }}'
ErrInitialPassword: 'Orijinal şifre yanlış' ErrInitialPassword: 'Orijinal şifre yanlış'
ErrInternalServer: 'Sunucu hatası: {{ .detail }}' ErrInternalServer: 'Sunucu hatası: {{ .detail }}'
ErrRecordExist: 'Kayıt zaten var'
ErrRecordNotFound: 'Kayıt bulunamadı'
ErrStructTransform: 'Dönüşüm hatası: {{ .err }}'
ErrNotSupportType: 'Bu tür desteklenmiyor: {{ .name }}'
# dosya AI
ErrFileAINotEnabled: 'Dosya yönetimi AI araması kapalı veya hesap yok. Dosya Yönetimi’nde AI hesabını açıp etkinleştirin ve bir hesap seçin.' ErrFileAINotEnabled: 'Dosya yönetimi AI araması kapalı veya hesap yok. Dosya Yönetimi’nde AI hesabını açıp etkinleştirin ve bir hesap seçin.'
ErrFileAISearchBadPattern: 'Geçersiz arama deseni (regex vb.): {{ .detail }}' ErrFileAISearchBadPattern: 'Geçersiz arama deseni (regex vb.): {{ .detail }}'
FileAISearchEmptyDir: 'Bu yol altında listelenecek dosya veya klasör yok (veya tümü filtrelendi).'
# uzaktan indirme
ErrWgetRemoteFailed: 'Uzak indirme başarısız veya URL erişilemiyor: {{ .detail }}' ErrWgetRemoteFailed: 'Uzak indirme başarısız veya URL erişilemiyor: {{ .detail }}'
ErrWgetInvalidContentType: 'Uzak URL bir dosya değil, muhtemelen bir hata sayfası döndürdü, {{ .detail }}' ErrWgetInvalidContentType: 'Uzak URL bir dosya değil, muhtemelen bir hata sayfası döndürdü, {{ .detail }}'
ErrWgetProxyNotConfigured: 'Önce panel ayarlarında bir proxy sunucusu yapılandırın' ErrWgetProxyNotConfigured: 'Önce panel ayarlarında bir proxy sunucusu yapılandırın'
ErrWgetProxyInvalid: 'Proxy sunucusu adresi geçersiz: {{ .detail }}' ErrWgetProxyInvalid: 'Proxy sunucusu adresi geçersiz: {{ .detail }}'
ErrRecordExist: 'Kayıt zaten var'
ErrRecordNotFound: 'Kayıt bulunamadı' # oturum açma ve güvenlik
ErrStructTransform: 'Dönüşüm hatası: {{ .err }}'
ErrNotLogin: 'Oturum açılmamış: {{ .detail }}' ErrNotLogin: 'Oturum açılmamış: {{ .detail }}'
ErrPasswordExpired: 'Şifre süresi doldu: {{ .detail }}' ErrPasswordExpired: 'Şifre süresi doldu: {{ .detail }}'
ErrNotSupportType: 'Bu tür desteklenmiyor: {{ .name }}'
ErrAlertMethodNotSupported: 'Bu sürüm bu uyarı yöntemini desteklemiyor' # istek ve API
ErrProxy: 'İstek başarısız: {{ .detail }}' ErrProxy: 'İstek başarısız: {{ .detail }}'
ErrApiConfigStatusInvalid: 'API kapalı: {{ .detail }}' ErrApiConfigStatusInvalid: 'API kapalı: {{ .detail }}'
ErrApiConfigKeyInvalid: 'Geçersiz API anahtarı: {{ .detail }}' ErrApiConfigKeyInvalid: 'Geçersiz API anahtarı: {{ .detail }}'
ErrApiConfigIPInvalid: 'IP izinli değil: {{ .detail }}' ErrApiConfigIPInvalid: 'IP izinli değil: {{ .detail }}'
ErrApiConfigDisable: 'API erişimi kapalı: {{ .detail }}' ErrApiConfigDisable: 'API erişimi kapalı: {{ .detail }}'
ErrApiConfigKeyTimeInvalid: 'Zaman damgası hatalı: {{ .detail }}' ErrApiConfigKeyTimeInvalid: 'Zaman damgası hatalı: {{ .detail }}'
ErrShutDown: 'Komut manuel durduruldu' ErrCreateHttpClient: 'İstek oluşturma başarısız {{ .err }}'
ErrHttpReqTimeOut: 'İstek zaman aşımı {{ .err }}'
ErrHttpReqFailed: 'İstek başarısız {{ .err }}'
ErrNoSuchHost: 'İstenen sunucu bulunamıyor {{ .err }}'
ErrHttpReqNotFound: 'İstenen kaynak {{ .err }} bulunamadı'
# hızlı geçiş
ErrMinQuickJump: 'En az bir hızlı erişim ekle' ErrMinQuickJump: 'En az bir hızlı erişim ekle'
ErrMaxQuickJump: '4 hızlı erişim hakkı var' ErrMaxQuickJump: '4 hızlı erişim hakkı var'
# genel
ErrShutDown: 'Komut manuel durduruldu'
ErrUsernameIsExist: 'Kullanıcı adı mevcut' ErrUsernameIsExist: 'Kullanıcı adı mevcut'
ErrNameIsExist: 'İsim mevcut' ErrNameIsExist: 'İsim mevcut'
ErrDemoEnvironment: 'Demo modunda yok' ErrDemoEnvironment: 'Demo modunda yok'
@@ -41,6 +59,8 @@ SystemRestart: 'Sistem yeniden başlatması nedeniyle görev kesildi'
ErrGroupIsDefault: 'Varsayılan grup, silinemez' ErrGroupIsDefault: 'Varsayılan grup, silinemez'
ErrGroupIsInWebsiteUse: 'Grup başka bir web sitesi tarafından kullanılıyor ve silinemez.' ErrGroupIsInWebsiteUse: 'Grup başka bir web sitesi tarafından kullanılıyor ve silinemez.'
Decrypt: 'Şifre Çöz' Decrypt: 'Şifre Çöz'
# ajan
ErrAgentAccountBound: 'Hesap bir ajana bağlı' ErrAgentAccountBound: 'Hesap bir ajana bağlı'
ErrTerminalAIAccountInUse: 'Bu model hesabi su anda Terminal AI tarafindan kullaniliyor. Terminal AI ayarlarinda baska bir hesaba gecin veya Terminal AI yi devre disi birakip tekrar deneyin.' ErrTerminalAIAccountInUse: 'Bu model hesabi su anda Terminal AI tarafindan kullaniliyor. Terminal AI ayarlarinda baska bir hesaba gecin veya Terminal AI yi devre disi birakip tekrar deneyin.'
ErrAgentAccountUnavailable: 'Hesap bağlantısı yok: {{ .err }}' ErrAgentAccountUnavailable: 'Hesap bağlantısı yok: {{ .err }}'
@@ -65,14 +85,8 @@ ErrAgentWebsiteInUse: 'Bu web sitesi zaten başka bir ajana bağlı'
ErrAgentWebsiteUnbindUnsupported: 'Tek tıkla dağıtılan web sitelerinin bağlantısı manuel olarak kaldırılamaz' ErrAgentWebsiteUnbindUnsupported: 'Tek tıkla dağıtılan web sitelerinin bağlantısı manuel olarak kaldırılamaz'
ErrHermesPairingCodeUnavailable: 'Eşleştirme kodu Hermes içinde geçici olarak bulunamıyor; bu durum ağ kaynaklı olabilir. Lütfen daha sonra tekrar deneyin.' ErrHermesPairingCodeUnavailable: 'Eşleştirme kodu Hermes içinde geçici olarak bulunamıyor; bu durum ağ kaynaklı olabilir. Lütfen daha sonra tekrar deneyin.'
ErrHermesFeishuGroupAllowlistRequiresAllowlist: 'Feishu grup ilkesi izin listesi olduğunda, DM ilkesi eşleştirme kodu olamaz.' ErrHermesFeishuGroupAllowlistRequiresAllowlist: 'Feishu grup ilkesi izin listesi olduğunda, DM ilkesi eşleştirme kodu olamaz.'
ErrAIProxyServiceNotInstalled: '{{ .name }} servisi kurulu değil'
ErrAIProxyModelAccountNotFound: 'Model hesabı {{ .id }} bulunamadı' # yedekleme ve uyarı ayarları
ErrAIProxyModelMapRequired: 'Bu alan zorunludur.'
ErrAIProxyModelMapInvalid: 'Model eşlemesi geçerli bir JSON nesnesi olmalıdır: {{ .err }}'
ErrAIProxyModelMapEmpty: 'Model eşlemesi boş olamaz'
ErrAIProxyModelMapEmptyExternalModel: 'Model eşlemesi boş bir istek modeli içeriyor'
ErrAIProxyModelMapEmptyUpstreamModel: '{{ .model }} için upstream model boş olamaz'
AIProxyUserFallback: 'Kullanıcı {{ .id }}'
Localhost: 'Yerel Makine' Localhost: 'Yerel Makine'
ErrBackupInUsed: 'Yedek hesabı görevde kullanılıyor' ErrBackupInUsed: 'Yedek hesabı görevde kullanılıyor'
ErrBackupCheck: 'Bağlantı testi başarısız: {{ .err }}' ErrBackupCheck: 'Bağlantı testi başarısız: {{ .err }}'
@@ -80,6 +94,8 @@ ErrBackupLocalDelete: 'Yerel yedek silme yok'
ErrBackupLocalCreate: 'Yerel yedek oluşturma yok' ErrBackupLocalCreate: 'Yerel yedek oluşturma yok'
ErrAlertConfigInUse: 'Uyarı yapılandırması kullanımda ve silinemez' ErrAlertConfigInUse: 'Uyarı yapılandırması kullanımda ve silinemez'
ErrAlertConfigPhoneExist: 'Telefon numarasi zaten mevcut' ErrAlertConfigPhoneExist: 'Telefon numarasi zaten mevcut'
# uygulama
ErrPortInUsed: '{{ .detail }} portu zaten kullanılıyor' ErrPortInUsed: '{{ .detail }} portu zaten kullanılıyor'
ErrAppLimit: 'Yüklenen uygulama sayısı sınırı aştı' ErrAppLimit: 'Yüklenen uygulama sayısı sınırı aştı'
ErrNotInstall: 'Uygulama yüklenmedi' ErrNotInstall: 'Uygulama yüklenmedi'
@@ -97,16 +113,12 @@ ErrFileParseApp: '{{ .name }} dosya ayrıştırma başarısız {{ .err }}'
ErrAppDirNull: 'Sürüm klasörü mevcut değil' ErrAppDirNull: 'Sürüm klasörü mevcut değil'
LocalAppErr: 'Uygulama {{ .name }} senkronizasyonu başarısız {{ .err }}' LocalAppErr: 'Uygulama {{ .name }} senkronizasyonu başarısız {{ .err }}'
ErrContainerName: 'Konteyner adı zaten mevcut' ErrContainerName: 'Konteyner adı zaten mevcut'
ErrCreateHttpClient: 'İstek oluşturma başarısız {{ .err }}'
ErrHttpReqTimeOut: 'İstek zaman aşımı {{ .err }}'
ErrHttpReqFailed: 'İstek başarısız {{ .err }}'
ErrNoSuchHost: 'İstenen sunucu bulunamıyor {{ .err }}'
ErrHttpReqNotFound: 'İstenen kaynak {{ .err }} bulunamadı'
ErrContainerNotFound: '{{ .name }} konteyneri mevcut değil' ErrContainerNotFound: '{{ .name }} konteyneri mevcut değil'
ErrContainerMsg: '{{ .name }} konteyneri anormal. Lütfen ayrıntılar için konteyner sayfasındaki günlüğü kontrol edin' ErrContainerMsg: '{{ .name }} konteyneri anormal. Lütfen ayrıntılar için konteyner sayfasındaki günlüğü kontrol edin'
ErrAppBackup: '{{ .name }} uygulama yedeklemesi başarısız {{ .err }}' ErrAppBackup: '{{ .name }} uygulama yedeklemesi başarısız {{ .err }}'
ErrVersionTooLow: 'Mevcut 1Panel sürümü Uygulama Mağazasını güncellemek için çok düşük. Lütfen işlemden önce sürümü yükseltin.' ErrVersionTooLow: 'Mevcut 1Panel sürümü Uygulama Mağazasını güncellemek için çok düşük. Lütfen işlemden önce sürümü yükseltin.'
ErrAppNameExist: 'Uygulama adı zaten mevcut' ErrAppNameExist: 'Uygulama adı zaten mevcut'
ErrAppInstallNameExist: '{{ .name }} uygulama kurulum adı zaten mevcut'
AppStoreIsSyncing: 'Uygulama Mağazası senkronize ediliyor, lütfen daha sonra tekrar deneyin' AppStoreIsSyncing: 'Uygulama Mağazası senkronize ediliyor, lütfen daha sonra tekrar deneyin'
ErrGetCompose: 'docker-compose.yml dosyası alınamadı {{ .detail }}' ErrGetCompose: 'docker-compose.yml dosyası alınamadı {{ .detail }}'
ErrAppWarn: 'Anormal durum, lütfen günlüğü kontrol edin' ErrAppWarn: 'Anormal durum, lütfen günlüğü kontrol edin'
@@ -131,6 +143,8 @@ ErrDockerFailed: 'Docker durumu anormal, lütfen servis durumunu kontrol edin'
ErrDockerComposeCmdNotFound: 'Docker Compose komutu mevcut değil, lütfen önce bu komutu host makinesine yükleyin' ErrDockerComposeCmdNotFound: 'Docker Compose komutu mevcut değil, lütfen önce bu komutu host makinesine yükleyin'
UseExistImage: 'Görüntü zaten mevcut, mevcut görüntü kullanılıyor' UseExistImage: 'Görüntü zaten mevcut, mevcut görüntü kullanılıyor'
ErrDatabaseNotFound: '{{ .name }} veritabanı mevcut değil' ErrDatabaseNotFound: '{{ .name }} veritabanı mevcut değil'
# SSH
ExportIP: 'Giriş IP' ExportIP: 'Giriş IP'
ExportArea: 'Konum' ExportArea: 'Konum'
ExportPort: 'Port' ExportPort: 'Port'
@@ -138,6 +152,8 @@ ExportAuthMode: 'Giriş Yöntemi'
ExportUser: 'Kullanıcı' ExportUser: 'Kullanıcı'
ExportStatus: 'Giriş Durumu' ExportStatus: 'Giriş Durumu'
ExportDate: 'Zaman' ExportDate: 'Zaman'
# dosya
ErrFileCanNotRead: 'Bu dosya önizlemeyi desteklemiyor' ErrFileCanNotRead: 'Bu dosya önizlemeyi desteklemiyor'
ErrSensitiveFileRead: 'Hassas dosyaların okunmasına izin verilmez' ErrSensitiveFileRead: 'Hassas dosyaların okunmasına izin verilmez'
ErrFileToLarge: 'Dosya 10M dan büyük ve açılamıyor' ErrFileToLarge: 'Dosya 10M dan büyük ve açılamıyor'
@@ -164,6 +180,8 @@ FileDropFailed: '{{ .name }} dosyası temizlenemedi: {{ .err }}'
FileDropSuccess: '{{ .name }} dosyası başarıyla temizlendi, {{ .count }} dosya silindi, {{ .size }} disk alanı boşaltıldı' FileDropSuccess: '{{ .name }} dosyası başarıyla temizlendi, {{ .count }} dosya silindi, {{ .size }} disk alanı boşaltıldı'
FileDropSum: 'Dosya temizleme tamamlandı, toplam {{ .count }} dosya silindi, toplam {{ .size }} disk alanı boşaltıldı' FileDropSum: 'Dosya temizleme tamamlandı, toplam {{ .count }} dosya silindi, toplam {{ .size }} disk alanı boşaltıldı'
ErrBadDecrypt: 'Sıkıştırılmış paket şifre çözme parolası hatalı, açma başarısız, lütfen kontrol edip tekrar deneyin' ErrBadDecrypt: 'Sıkıştırılmış paket şifre çözme parolası hatalı, açma başarısız, lütfen kontrol edip tekrar deneyin'
# web sitesi
ErrAliasIsExist: 'Takma ad zaten mevcut' ErrAliasIsExist: 'Takma ad zaten mevcut'
ErrBackupMatch: 'Yedekleme dosyası mevcut web sitesi verilerinin bir kısmıyla eşleşmiyor {{ .detail }}' ErrBackupMatch: 'Yedekleme dosyası mevcut web sitesi verilerinin bir kısmıyla eşleşmiyor {{ .detail }}'
ErrBackupExist: 'Yedekleme dosyasındaki kaynak verilerin karşılık gelen kısmı mevcut değil {{ .detail }}' ErrBackupExist: 'Yedekleme dosyasındaki kaynak verilerin karşılık gelen kısmı mevcut değil {{ .detail }}'
@@ -193,6 +211,8 @@ delete: 'Sil'
ErrDefaultWebsite: 'Varsayılan bir web sitesi zaten ayarlanmış. Yeni bir tane ayarlamadan önce lütfen iptal edin' ErrDefaultWebsite: 'Varsayılan bir web sitesi zaten ayarlanmış. Yeni bir tane ayarlamadan önce lütfen iptal edin'
SSL: 'Sertifika' SSL: 'Sertifika'
Set: 'Ayarlar' Set: 'Ayarlar'
# SSL sertifikası
ErrSSLCannotDelete: '{{ .name }} sertifikası bir web sitesi tarafından kullanılıyor ve silinemez' ErrSSLCannotDelete: '{{ .name }} sertifikası bir web sitesi tarafından kullanılıyor ve silinemez'
ErrAccountCannotDelete: 'Hesap bir sertifikayla ilişkili ve silinemez' ErrAccountCannotDelete: 'Hesap bir sertifikayla ilişkili ve silinemez'
ErrSSLApply: 'Sertifika yenileme başarılı, openresty yeniden yükleme başarısız, lütfen yapılandırmayı kontrol edin' ErrSSLApply: 'Sertifika yenileme başarılı, openresty yeniden yükleme başarısız, lütfen yapılandırmayı kontrol edin'
@@ -227,6 +247,8 @@ ErrApplySSLCanNotDelete: 'İşlemde olan sertifika {{ .name }} silinemez, lütfe
StartPushSSLToNode: 'Sertifika düğüme gönderilmeye başlandı' StartPushSSLToNode: 'Sertifika düğüme gönderilmeye başlandı'
PushSSLToNodeFailed: 'Sertifika düğüme gönderilemedi: {{ .err }}' PushSSLToNodeFailed: 'Sertifika düğüme gönderilemedi: {{ .err }}'
PushSSLToNodeSuccess: 'Sertifika düğüme başarıyla gönderildi' PushSSLToNodeSuccess: 'Sertifika düğüme başarıyla gönderildi'
# MySQL
ErrUserIsExist: 'Mevcut kullanıcı zaten mevcut, lütfen yeniden girin' ErrUserIsExist: 'Mevcut kullanıcı zaten mevcut, lütfen yeniden girin'
ErrDatabaseIsExist: 'Mevcut veritabanı zaten mevcut, lütfen yeniden girin' ErrDatabaseIsExist: 'Mevcut veritabanı zaten mevcut, lütfen yeniden girin'
ErrExecTimeOut: 'SQL yürütme zaman aşımı, lütfen veritabanını kontrol edin' ErrExecTimeOut: 'SQL yürütme zaman aşımı, lütfen veritabanını kontrol edin'
@@ -235,7 +257,11 @@ ErrLocalExist: 'Yerel veritabanında bu ad zaten mevcut, lütfen değiştirin ve
RemoteBackup: 'Uzak veritabanını yedeklemek için önce {{ .name }} görüntüsü kullanılarak yerel konteyner veritabanı hizmetinin başlatılması gerekiyor, lütfen bekleyin...' RemoteBackup: 'Uzak veritabanını yedeklemek için önce {{ .name }} görüntüsü kullanılarak yerel konteyner veritabanı hizmetinin başlatılması gerekiyor, lütfen bekleyin...'
RemoteRecover: 'Uzak veritabanını geri yüklemek için önce {{ .name }} görüntüsü kullanılarak yerel konteyner veritabanı hizmetinin başlatılması gerekiyor, lütfen bekleyin...' RemoteRecover: 'Uzak veritabanını geri yüklemek için önce {{ .name }} görüntüsü kullanılarak yerel konteyner veritabanı hizmetinin başlatılması gerekiyor, lütfen bekleyin...'
Arg: 'Argüman' Arg: 'Argüman'
# Redis
ErrTypeOfRedis: 'Kurtarma dosyası türü mevcut kalıcılık yöntemiyle eşleşmiyor, lütfen değiştirin ve tekrar deneyin' ErrTypeOfRedis: 'Kurtarma dosyası türü mevcut kalıcılık yöntemiyle eşleşmiyor, lütfen değiştirin ve tekrar deneyin'
# konteyner
ErrInUsed: '{{ .detail }} kullanımda ve silinemez' ErrInUsed: '{{ .detail }} kullanımda ve silinemez'
ErrObjectInUsed: 'Bu nesne kullanımda ve silinemez' ErrObjectInUsed: 'Bu nesne kullanımda ve silinemez'
ErrObjectBeDependent: 'Bu görüntü diğer görüntüler tarafından bağımlıdır ve silinemez' ErrObjectBeDependent: 'Bu görüntü diğer görüntüler tarafından bağımlıdır ve silinemez'
@@ -277,6 +303,8 @@ ComposeRecoverFiles: 'Compose dosyalarını geri yükle'
ComposeRecoverContainers: 'Compose konteynerlerini geri yükle' ComposeRecoverContainers: 'Compose konteynerlerini geri yükle'
ComposeRecoverRecord: 'Compose kaydını sakla' ComposeRecoverRecord: 'Compose kaydını sakla'
ComposeRecoverCleanup: 'Compose geri yükleme çalışma alanını temizle' ComposeRecoverCleanup: 'Compose geri yükleme çalışma alanını temizle'
# çalışma zamanı
ErrFileNotExist: '{{ .detail }} dosyası mevcut değil Lütfen kaynak dosyanın bütünlüğünü kontrol edin' ErrFileNotExist: '{{ .detail }} dosyası mevcut değil Lütfen kaynak dosyanın bütünlüğünü kontrol edin'
ErrImageBuildErr: 'Image yapı başarısız' ErrImageBuildErr: 'Image yapı başarısız'
ErrImageExist: 'Görüntü zaten var Lütfen görüntü adını değiştirin.' ErrImageExist: 'Görüntü zaten var Lütfen görüntü adını değiştirin.'
@@ -289,12 +317,16 @@ ErrNodeModulesNotFound: 'node_modules klasörü mevcut değil Lütfen çalışma
ErrContainerNameIsNull: 'Konteyner adı mevcut değil' ErrContainerNameIsNull: 'Konteyner adı mevcut değil'
ErrPHPPortIsDefault: '9000 portu varsayılan port, lütfen değiştirin ve tekrar deneyin' ErrPHPPortIsDefault: '9000 portu varsayılan port, lütfen değiştirin ve tekrar deneyin'
ErrPHPRuntimePortFailed: '{{ .name }} portu mevcut çalışma ortamı tarafından zaten kullanılıyor, lütfen değiştirin ve tekrar deneyin' ErrPHPRuntimePortFailed: '{{ .name }} portu mevcut çalışma ortamı tarafından zaten kullanılıyor, lütfen değiştirin ve tekrar deneyin'
# araç
ErrConfigNotFound: 'Yapılandırma dosyası mevcut değil' ErrConfigNotFound: 'Yapılandırma dosyası mevcut değil'
ErrConfigParse: 'Yapılandırma dosyası formatı yanlış' ErrConfigParse: 'Yapılandırma dosyası formatı yanlış'
ErrConfigIsNull: 'Yapılandırma dosyası boş olamaz' ErrConfigIsNull: 'Yapılandırma dosyası boş olamaz'
ErrConfigDirNotFound: 'Çalışma dizini mevcut değil' ErrConfigDirNotFound: 'Çalışma dizini mevcut değil'
ErrConfigAlreadyExist: 'Aynı ada sahip bir yapılandırma dosyası zaten mevcut' ErrConfigAlreadyExist: 'Aynı ada sahip bir yapılandırma dosyası zaten mevcut'
ErrUserFindErr: 'Kullanıcı {{ .name }} arama başarısız {{ .err }}' ErrUserFindErr: 'Kullanıcı {{ .name }} arama başarısız {{ .err }}'
# cron görevi
CutWebsiteLogSuccess: '{{ .name }} web sitesi günlüğü başarıyla kesildi, yedekleme yolu {{ .path }}' CutWebsiteLogSuccess: '{{ .name }} web sitesi günlüğü başarıyla kesildi, yedekleme yolu {{ .path }}'
HandleShell: 'Betik {{ .name }} yürüt' HandleShell: 'Betik {{ .name }} yürüt'
HandleCurl: 'URL''ye Eriş {{ .name }}' HandleCurl: 'URL''ye Eriş {{ .name }}'
@@ -313,6 +345,8 @@ NoSuchResource: 'Veritabanında yedek içeriği bulunamadı, atlanıyor...'
CleanLog: 'Günlüğü temizle' CleanLog: 'Günlüğü temizle'
CleanLogByName: '{{ .name }} günlüğünü temizle' CleanLogByName: '{{ .name }} günlüğünü temizle'
WafIpGroupNotFound: 'WAF IP grubu bulunamadı. Lütfen [Gelişmiş Özellikler - WAF - Kara/Beyaz Liste - IP Grubu] bölümüne giderek uzaktan indirme yöntemiyle bir IP grubu ekleyin.' WafIpGroupNotFound: 'WAF IP grubu bulunamadı. Lütfen [Gelişmiş Özellikler - WAF - Kara/Beyaz Liste - IP Grubu] bölümüne giderek uzaktan indirme yöntemiyle bir IP grubu ekleyin.'
# araç kutusu
ErrNotExistUser: 'Mevcut kullanıcı mevcut değil, lütfen değiştirin ve tekrar deneyin' ErrNotExistUser: 'Mevcut kullanıcı mevcut değil, lütfen değiştirin ve tekrar deneyin'
ErrBanAction: 'Ayarlama başarısız. Mevcut {{ .name }} servisi kullanılamıyor. Lütfen kontrol edin ve tekrar deneyin' ErrBanAction: 'Ayarlama başarısız. Mevcut {{ .name }} servisi kullanılamıyor. Lütfen kontrol edin ve tekrar deneyin'
ErrClamdscanNotFound: 'clamdscan komutu tespit edilmedi, lütfen yüklemek için belgeleri inceleyin' ErrClamdscanNotFound: 'clamdscan komutu tespit edilmedi, lütfen yüklemek için belgeleri inceleyin'
@@ -321,11 +355,15 @@ SetSwap: 'Swap Ayarla {{ .path }} - {{ .size }}'
CreateSwap: 'Swap Dosyası Oluştur' CreateSwap: 'Swap Dosyası Oluştur'
FormatSwap: 'Swap Dosyasını Biçimlendir' FormatSwap: 'Swap Dosyasını Biçimlendir'
EnableSwap: 'Swap Etkinleştir' EnableSwap: 'Swap Etkinleştir'
# kurcalama koruması
CleanTamperSetting: 'Geçmiş koruma ayarlarını temizle' CleanTamperSetting: 'Geçmiş koruma ayarlarını temizle'
SetTamperWithRules: 'Kurallara göre dizin korumasını başlat' SetTamperWithRules: 'Kurallara göre dizin korumasını başlat'
ProtectDir: 'Dizini koru {{ .name }}' ProtectDir: 'Dizini koru {{ .name }}'
IgnoreFile: 'Dosyayı koru {{ .name }}' IgnoreFile: 'Dosyayı koru {{ .name }}'
TamperSetSuccessful: 'Koruma ayarları tamamlandı, aşağıdaki dizinler izlenmeye başlanıyor:' TamperSetSuccessful: 'Koruma ayarları tamamlandı, aşağıdaki dizinler izlenmeye başlanıyor:'
# WAF
ErrScope: 'Bu yapılandırmayı değiştirme desteklenmiyor' ErrScope: 'Bu yapılandırmayı değiştirme desteklenmiyor'
ErrStateChange: 'Durum değiştirme başarısız' ErrStateChange: 'Durum değiştirme başarısız'
ErrRuleExist: 'Kural zaten mevcut' ErrRuleExist: 'Kural zaten mevcut'
@@ -380,6 +418,8 @@ OpenrestyNotFound: 'OpenResty yüklü değil'
remoteIpIsNull: 'IP listesi boş' remoteIpIsNull: 'IP listesi boş'
OpenrestyVersionErr: 'OpenResty sürümü çok eski. 1.27.1.2-2-2-focal sürümüne yükseltin' OpenrestyVersionErr: 'OpenResty sürümü çok eski. 1.27.1.2-2-2-focal sürümüne yükseltin'
ErrFileTooLarge: 'Dosya 1 MB''den büyük olduğu için yüklenemiyor' ErrFileTooLarge: 'Dosya 1 MB''den büyük olduğu için yüklenemiyor'
# görev
TaskStart: '{{ .name }} görevi başlıyor [BAŞLAT]' TaskStart: '{{ .name }} görevi başlıyor [BAŞLAT]'
TaskEnd: '{{ .name }} Görev tamamlandı [TAMAMLANDI]' TaskEnd: '{{ .name }} Görev tamamlandı [TAMAMLANDI]'
TaskFailed: '{{ .name }} görev başarısız' TaskFailed: '{{ .name }} görev başarısız'
@@ -440,10 +480,17 @@ CustomAppstore: 'Özel uygulama deposu'
TaskExec: 'Çalıştır' TaskExec: 'Çalıştır'
TaskBatch: 'Toplu İşlem' TaskBatch: 'Toplu İşlem'
FileConvert: 'Dosya Formatı Dönüştürme' FileConvert: 'Dosya Formatı Dönüştürme'
# görev - ClamAV
Clamscan: '{{ .name }} Tara' Clamscan: '{{ .name }} Tara'
TaskScan: 'Tara' TaskScan: 'Tara'
# görev - AI
OllamaModelPull: 'Ollama modeli {{ .name }} çek' OllamaModelPull: 'Ollama modeli {{ .name }} çek'
OllamaModelSize: 'Ollama modeli {{ .name }} boyutunu al' OllamaModelSize: 'Ollama modeli {{ .name }} boyutunu al'
AIBenchmarkRun: "AI kıyaslama testini çalıştır"
# görev - anlık görüntü
Snapshot: 'Anlık Görüntü' Snapshot: 'Anlık Görüntü'
SnapDBInfo: '1Panel veritabanı bilgilerini yaz' SnapDBInfo: '1Panel veritabanı bilgilerini yaz'
SnapCopy: 'Dosya ve dizinleri {{ .name }} kopyala' SnapCopy: 'Dosya ve dizinleri {{ .name }} kopyala'
@@ -493,6 +540,8 @@ RecoverDaemonJson: 'Konteyner yapılandırma daemon.json dosyasını geri yükle
RecoverDBData: 'Veritabanı verilerini kurtar' RecoverDBData: 'Veritabanı verilerini kurtar'
RecoverBackups: 'Yerel yedekleme dizinini geri yükle' RecoverBackups: 'Yerel yedekleme dizinini geri yükle'
RecoverPanelData: 'Veri dizinini kurtar' RecoverPanelData: 'Veri dizinini kurtar'
# görev - konteyner
ContainerImagePull: 'Konteyner imajını çek {{ .name }}' ContainerImagePull: 'Konteyner imajını çek {{ .name }}'
ContainerRemoveOld: 'Orijinal konteyneri kaldır {{ .name }}' ContainerRemoveOld: 'Orijinal konteyneri kaldır {{ .name }}'
ContainerImageCheck: 'İmajın normal çekilip çekilmediğini kontrol et' ContainerImageCheck: 'İmajın normal çekilip çekilmediğini kontrol et'
@@ -501,6 +550,8 @@ ContainerRecreate: 'Konteyner güncellemesi başarısız, şimdi orijinal kontey
ContainerCreate: 'Yeni konteyner oluştur {{ .name }}' ContainerCreate: 'Yeni konteyner oluştur {{ .name }}'
ContainerCreateFailed: 'Konteyner oluşturma başarısız, başarısız konteyneri sil' ContainerCreateFailed: 'Konteyner oluşturma başarısız, başarısız konteyneri sil'
ContainerStartCheck: 'Konteynerin başlatılıp başlatılmadığını kontrol et' ContainerStartCheck: 'Konteynerin başlatılıp başlatılmadığını kontrol et'
# görev - imaj
ImageBuild: 'İmaj Oluşturma' ImageBuild: 'İmaj Oluşturma'
ImagePull: 'İmaj çek' ImagePull: 'İmaj çek'
ImageRepoAuthFromDB: 'Veritabanından depo kimlik doğrulama bilgilerini al' ImageRepoAuthFromDB: 'Veritabanından depo kimlik doğrulama bilgilerini al'
@@ -508,6 +559,8 @@ ImagePush: 'İmaj gönder'
ImageRenameTag: 'İmaj etiketini değiştir' ImageRenameTag: 'İmaj etiketini değiştir'
ImageNewTag: 'Yeni imaj etiketi {{ .name }}' ImageNewTag: 'Yeni imaj etiketi {{ .name }}'
ComposeCreate: 'Kompozisyon oluştur' ComposeCreate: 'Kompozisyon oluştur'
# görev - web sitesi
BackupNginxConfig: 'Web sitesi OpenResty yapılandırma dosyasını yedekle' BackupNginxConfig: 'Web sitesi OpenResty yapılandırma dosyasını yedekle'
CompressFileSuccess: 'Dizin başarıyla sıkıştırıldı, şuraya sıkıştırıldı {{ .name }}' CompressFileSuccess: 'Dizin başarıyla sıkıştırıldı, şuraya sıkıştırıldı {{ .name }}'
CompressDir: 'Sıkıştırma dizini' CompressDir: 'Sıkıştırma dizini'
@@ -518,8 +571,15 @@ websiteDir: 'Web Sitesi Dizini'
RecoverFailedStartRollBack: 'Kurtarma başarısız, geri almayı başlat' RecoverFailedStartRollBack: 'Kurtarma başarısız, geri almayı başlat'
AppBackupFileIncomplete: 'Yedekleme dosyası eksik ve app.json veya app.tar.gz dosyalarından yoksun' AppBackupFileIncomplete: 'Yedekleme dosyası eksik ve app.json veya app.tar.gz dosyalarından yoksun'
AppAttributesNotMatch: 'Uygulama türü veya adı eşleşmiyor' AppAttributesNotMatch: 'Uygulama türü veya adı eşleşmiyor'
# uyarı
ErrAlertMethodNotSupported: 'Bu sürüm bu uyarı yöntemini desteklemiyor'
ErrAlertSync: 'Alarm bilgisi senkronizasyon hatası, lütfen kontrol edin ve tekrar deneyin' ErrAlertSync: 'Alarm bilgisi senkronizasyon hatası, lütfen kontrol edin ve tekrar deneyin'
# görev - çalışma zamanı
ErrInstallExtension: 'Zaten devam eden bir kurulum görevi var, görevin bitmesini bekleyin' ErrInstallExtension: 'Zaten devam eden bir kurulum görevi var, görevin bitmesini bekleyin'
# uyarı e-posta şablonu
PanelAlertTitle: 'Panel Uyarı Bildirimi' PanelAlertTitle: 'Panel Uyarı Bildirimi'
TestAlertTitle: 'Test E-postası - E-posta Bağlantısını Doğrula' TestAlertTitle: 'Test E-postası - E-posta Bağlantısını Doğrula'
TestAlert: 'Bu, e-posta gönderim ayarlarınızın doğru yapılandırıldığını doğrulamak için gönderilen bir test e-postasıdır.' TestAlert: 'Bu, e-posta gönderim ayarlarınızın doğru yapılandırıldığını doğrulamak için gönderilen bir test e-postasıdır.'
@@ -536,6 +596,8 @@ CommonAlert: 'Paneliniz {{ .node }}{{ .ip }}, {{ .msg }}. Detaylar için panelin
NodeExceptionAlert: 'Paneliniz {{ .node }}{{ .ip }}, {{ .num }} düğüm anormal durumda. Detaylar için paneline giriş yapın.' NodeExceptionAlert: 'Paneliniz {{ .node }}{{ .ip }}, {{ .num }} düğüm anormal durumda. Detaylar için paneline giriş yapın.'
LicenseExceptionAlert: 'Paneliniz {{ .node }}{{ .ip }}, {{ .num }} lisans anormal durumda. Detaylar için paneline giriş yapın.' LicenseExceptionAlert: 'Paneliniz {{ .node }}{{ .ip }}, {{ .num }} lisans anormal durumda. Detaylar için paneline giriş yapın.'
SSHAndPanelLoginAlert: 'Paneliniz {{ .node }}{{ .ip }}, {{ .loginIp }} adresinden {{ .name }} girişi anormal. Detaylar için paneline giriş yapın.' SSHAndPanelLoginAlert: 'Paneliniz {{ .node }}{{ .ip }}, {{ .loginIp }} adresinden {{ .name }} girişi anormal. Detaylar için paneline giriş yapın.'
# disk
DeviceNotFound: 'Cihaz {{ .name }} bulunamadı' DeviceNotFound: 'Cihaz {{ .name }} bulunamadı'
DeviceIsMounted: 'Cihaz {{ .name }} bağlandı, önce çıkarın' DeviceIsMounted: 'Cihaz {{ .name }} bağlandı, önce çıkarın'
PartitionDiskErr: 'Bölümleme başarısız, {{ .err }}' PartitionDiskErr: 'Bölümleme başarısız, {{ .err }}'
@@ -548,4 +610,13 @@ TerminalAIBlockedRiskyCommand: 'Riskli komut engellendi: {{ .command }}'
TerminalAIThinking: 'AI dusunuyor...' TerminalAIThinking: 'AI dusunuyor...'
TerminalAIReadyToExecute: 'Dusunme tamamlandi, calistirmak icin Enter tusuna basin (sure: {{ .duration }}, token: {{ .tokens }})' TerminalAIReadyToExecute: 'Dusunme tamamlandi, calistirmak icin Enter tusuna basin (sure: {{ .duration }}, token: {{ .tokens }})'
TerminalAIRequestFailed: 'AI istegi basarisiz oldu: {{ .err }}' TerminalAIRequestFailed: 'AI istegi basarisiz oldu: {{ .err }}'
FileAISearchEmptyDir: 'Bu yol altında listelenecek dosya veya klasör yok (veya tümü filtrelendi).'
# AI ağ geçidi
ErrAIProxyServiceNotInstalled: '{{ .name }} servisi kurulu değil'
ErrAIProxyModelAccountNotFound: 'Model hesabı {{ .id }} bulunamadı'
ErrAIProxyModelMapRequired: 'Bu alan zorunludur.'
ErrAIProxyModelMapInvalid: 'Model eşlemesi geçerli bir JSON nesnesi olmalıdır: {{ .err }}'
ErrAIProxyModelMapEmpty: 'Model eşlemesi boş olamaz'
ErrAIProxyModelMapEmptyExternalModel: 'Model eşlemesi boş bir istek modeli içeriyor'
ErrAIProxyModelMapEmptyUpstreamModel: '{{ .model }} için upstream model boş olamaz'
AIProxyUserFallback: 'Silinen kullanıcı (ID: {{ .id }})'
+91 -21
View File
@@ -1,29 +1,47 @@
# 基礎錯誤
ErrInvalidParams: '請求參數錯誤: {{ .detail }}' ErrInvalidParams: '請求參數錯誤: {{ .detail }}'
ErrTokenParse: 'Token 產生錯誤: {{ .detail }}' ErrTokenParse: 'Token 產生錯誤: {{ .detail }}'
ErrInitialPassword: '原密碼錯誤' ErrInitialPassword: '原密碼錯誤'
ErrInternalServer: '服務內部錯誤: {{ .detail }}' ErrInternalServer: '服務內部錯誤: {{ .detail }}'
ErrRecordExist: '記錄已存在'
ErrRecordNotFound: '記錄未能找到'
ErrStructTransform: '型別轉換失敗: {{ .err }}'
ErrNotSupportType: '系統暫不支援目前類型: {{ .name }}'
# 檔案 AI
ErrFileAINotEnabled: '請先在檔案管理頁透過「AI 帳號」啟用檔案 AI 搜尋並選擇帳號。' ErrFileAINotEnabled: '請先在檔案管理頁透過「AI 帳號」啟用檔案 AI 搜尋並選擇帳號。'
ErrFileAISearchBadPattern: '搜尋條件無效(正則或全詞): {{ .detail }}' ErrFileAISearchBadPattern: '搜尋條件無效(正則或全詞): {{ .detail }}'
FileAISearchEmptyDir: '目前目錄下沒有可列出的檔案或資料夾(或均被過濾)。'
# 遠端下載
ErrWgetRemoteFailed: '遠端下載網址無效或無法存取:{{ .detail }}' ErrWgetRemoteFailed: '遠端下載網址無效或無法存取:{{ .detail }}'
ErrWgetInvalidContentType: '遠端網址未回傳檔案內容(可能是錯誤頁),{{ .detail }}' ErrWgetInvalidContentType: '遠端網址未回傳檔案內容(可能是錯誤頁),{{ .detail }}'
ErrWgetProxyNotConfigured: '請先在面板設定中設定代理伺服器' ErrWgetProxyNotConfigured: '請先在面板設定中設定代理伺服器'
ErrWgetProxyInvalid: '代理伺服器位址無效:{{ .detail }}' ErrWgetProxyInvalid: '代理伺服器位址無效:{{ .detail }}'
ErrRecordExist: '記錄已存在'
ErrRecordNotFound: '記錄未能找到' # 登入與安全
ErrStructTransform: '型別轉換失敗: {{ .err }}'
ErrNotLogin: '使用者未登入: {{ .detail }}' ErrNotLogin: '使用者未登入: {{ .detail }}'
ErrPasswordExpired: '目前密碼已過期: {{ .detail }}' ErrPasswordExpired: '目前密碼已過期: {{ .detail }}'
ErrNotSupportType: '系統暫不支援目前類型: {{ .name }}'
ErrAlertMethodNotSupported: '當前版本不支援此告警方式' # 請求與 API
ErrProxy: '請求錯誤,請檢查該節點狀態: {{ .detail }}' ErrProxy: '請求錯誤,請檢查該節點狀態: {{ .detail }}'
ErrApiConfigStatusInvalid: 'API 介面禁止存取: {{ .detail }}' ErrApiConfigStatusInvalid: 'API 介面禁止存取: {{ .detail }}'
ErrApiConfigKeyInvalid: 'API 介面金鑰錯誤: {{ .detail }}' ErrApiConfigKeyInvalid: 'API 介面金鑰錯誤: {{ .detail }}'
ErrApiConfigIPInvalid: '呼叫 API 介面 IP 不在白名單: {{ .detail }}' ErrApiConfigIPInvalid: '呼叫 API 介面 IP 不在白名單: {{ .detail }}'
ErrApiConfigDisable: '此介面禁止使用 API 介面呼叫: {{ .detail }}' ErrApiConfigDisable: '此介面禁止使用 API 介面呼叫: {{ .detail }}'
ErrApiConfigKeyTimeInvalid: 'API 介面時間戳記錯誤: {{ .detail }}' ErrApiConfigKeyTimeInvalid: 'API 介面時間戳記錯誤: {{ .detail }}'
ErrShutDown: '指令被手動結束!' ErrCreateHttpClient: '建立請求失敗{{ .err }}'
ErrHttpReqTimeOut: '請求逾時{{ .err }}'
ErrHttpReqFailed: '請求失敗{{ .err }}'
ErrNoSuchHost: '無法找到請求的伺服器{{ .err }}'
ErrHttpReqNotFound: '無法找到要求的資源{{ .err }}'
# 快速跳轉
ErrMinQuickJump: '請至少設定一個快速跳轉入口!' ErrMinQuickJump: '請至少設定一個快速跳轉入口!'
ErrMaxQuickJump: '最多可設定四個快速跳轉入口!' ErrMaxQuickJump: '最多可設定四個快速跳轉入口!'
# 通用
ErrShutDown: '指令被手動結束!'
ErrUsernameIsExist: '使用者名稱已存在' ErrUsernameIsExist: '使用者名稱已存在'
ErrNameIsExist: '名稱已存在' ErrNameIsExist: '名稱已存在'
ErrDemoEnvironment: '示範伺服器,禁止此操作!' ErrDemoEnvironment: '示範伺服器,禁止此操作!'
@@ -41,6 +59,8 @@ SystemRestart: '系統重新啟動導致任務中斷'
ErrGroupIsDefault: '預設分組,無法刪除' ErrGroupIsDefault: '預設分組,無法刪除'
ErrGroupIsInWebsiteUse: '分組正在被其他網站使用,無法刪除' ErrGroupIsInWebsiteUse: '分組正在被其他網站使用,無法刪除'
Decrypt: '解密' Decrypt: '解密'
# 智慧體
ErrAgentAccountBound: '該帳號已綁定到智能體,無法刪除,請重試。' ErrAgentAccountBound: '該帳號已綁定到智能體,無法刪除,請重試。'
ErrTerminalAIAccountInUse: '該模型帳號正被終端 AI 使用,請在終端 AI 設定中更換帳號或關閉終端 AI 後再試。' ErrTerminalAIAccountInUse: '該模型帳號正被終端 AI 使用,請在終端 AI 設定中更換帳號或關閉終端 AI 後再試。'
ErrAgentAccountUnavailable: '帳號連線資訊不可用,錯誤:{{ .err }},請重試' ErrAgentAccountUnavailable: '帳號連線資訊不可用,錯誤:{{ .err }},請重試'
@@ -65,14 +85,8 @@ ErrAgentWebsiteInUse: '該網站已被其他智能體關聯'
ErrAgentWebsiteUnbindUnsupported: '一鍵部署網站不支援手動解綁' ErrAgentWebsiteUnbindUnsupported: '一鍵部署網站不支援手動解綁'
ErrHermesPairingCodeUnavailable: '配對碼在 Hermes 中暫時不存在,可能是由於網路原因,請稍後再試' ErrHermesPairingCodeUnavailable: '配對碼在 Hermes 中暫時不存在,可能是由於網路原因,請稍後再試'
ErrHermesFeishuGroupAllowlistRequiresAllowlist: '飛書群組策略為白名單時,私聊策略不能為配對碼' ErrHermesFeishuGroupAllowlistRequiresAllowlist: '飛書群組策略為白名單時,私聊策略不能為配對碼'
ErrAIProxyServiceNotInstalled: '{{ .name }} 服務未安裝'
ErrAIProxyModelAccountNotFound: '模型帳號 {{ .id }} 不存在' # 備份與告警設定
ErrAIProxyModelMapRequired: '請填寫必填項'
ErrAIProxyModelMapInvalid: '模型映射必須是合法的 JSON 物件:{{ .err }}'
ErrAIProxyModelMapEmpty: '模型映射不能為空'
ErrAIProxyModelMapEmptyExternalModel: '模型映射中存在空的請求模型'
ErrAIProxyModelMapEmptyUpstreamModel: '模型 {{ .model }} 的上游模型不能為空'
AIProxyUserFallback: '使用者 {{ .id }}'
Localhost: '本機' Localhost: '本機'
ErrBackupInUsed: '此備份帳號已在排程任務中使用,無法刪除' ErrBackupInUsed: '此備份帳號已在排程任務中使用,無法刪除'
ErrBackupCheck: '備份帳號測試連線失敗{{ .err }}' ErrBackupCheck: '備份帳號測試連線失敗{{ .err }}'
@@ -80,6 +94,8 @@ ErrBackupLocalDelete: '暫時不支援刪除本機伺服器備份帳號'
ErrBackupLocalCreate: '暫時不支援建立本機伺服器備份帳號' ErrBackupLocalCreate: '暫時不支援建立本機伺服器備份帳號'
ErrAlertConfigInUse: '告警配置正在使用中,無法刪除' ErrAlertConfigInUse: '告警配置正在使用中,無法刪除'
ErrAlertConfigPhoneExist: '手機號碼已存在' ErrAlertConfigPhoneExist: '手機號碼已存在'
# 應用
ErrPortInUsed: '{{ .detail }} 連接埠已被佔用!' ErrPortInUsed: '{{ .detail }} 連接埠已被佔用!'
ErrAppLimit: '應用程式超出安裝數量限制' ErrAppLimit: '應用程式超出安裝數量限制'
ErrNotInstall: '應用程式未安裝' ErrNotInstall: '應用程式未安裝'
@@ -97,16 +113,12 @@ ErrFileParseApp: '{{ .name }} 檔案解析失敗{{ .err }}'
ErrAppDirNull: '版本資料夾不存在' ErrAppDirNull: '版本資料夾不存在'
LocalAppErr: '應用程式{{ .name }} 同步失敗!{{ .err }}' LocalAppErr: '應用程式{{ .name }} 同步失敗!{{ .err }}'
ErrContainerName: '容器名稱已存在' ErrContainerName: '容器名稱已存在'
ErrCreateHttpClient: '建立請求失敗{{ .err }}'
ErrHttpReqTimeOut: '請求逾時{{ .err }}'
ErrHttpReqFailed: '請求失敗{{ .err }}'
ErrNoSuchHost: '無法找到請求的伺服器{{ .err }}'
ErrHttpReqNotFound: '無法找到要求的資源{{ .err }}'
ErrContainerNotFound: '{{ .name }} 容器不存在' ErrContainerNotFound: '{{ .name }} 容器不存在'
ErrContainerMsg: '{{ .name }} 容器異常,請在容器頁面上檢視日誌' ErrContainerMsg: '{{ .name }} 容器異常,請在容器頁面上檢視日誌'
ErrAppBackup: '{{ .name }} 應用備份失敗 {{ .err }}' ErrAppBackup: '{{ .name }} 應用備份失敗 {{ .err }}'
ErrVersionTooLow: '目前 1Panel 版本過低,無法更新應用程式商店,請升級版本之後操作' ErrVersionTooLow: '目前 1Panel 版本過低,無法更新應用程式商店,請升級版本之後操作'
ErrAppNameExist: '應用程式名稱已存在' ErrAppNameExist: '應用程式名稱已存在'
ErrAppInstallNameExist: '應用程式安裝名稱 {{ .name }} 已存在'
AppStoreIsSyncing: '應用程式商店正在同步中,請稍後重試' AppStoreIsSyncing: '應用程式商店正在同步中,請稍後重試'
ErrGetCompose: 'docker-compose.yml 檔案取得失敗!{{ .detail }}' ErrGetCompose: 'docker-compose.yml 檔案取得失敗!{{ .detail }}'
ErrAppWarn: '狀態異常,請檢視日誌' ErrAppWarn: '狀態異常,請檢視日誌'
@@ -131,6 +143,8 @@ ErrDockerFailed: 'Docker 狀態異常,請檢查服務狀態'
ErrDockerComposeCmdNotFound: 'Docker Compose 指令不存在,請先在宿主機安裝此指令' ErrDockerComposeCmdNotFound: 'Docker Compose 指令不存在,請先在宿主機安裝此指令'
UseExistImage: '映像已存在,使用現有映像' UseExistImage: '映像已存在,使用現有映像'
ErrDatabaseNotFound: '資料庫 {{ .name }} 不存在' ErrDatabaseNotFound: '資料庫 {{ .name }} 不存在'
# SSH
ExportIP: '登入IP' ExportIP: '登入IP'
ExportArea: '歸屬地' ExportArea: '歸屬地'
ExportPort: '埠' ExportPort: '埠'
@@ -138,6 +152,8 @@ ExportAuthMode: '登入方式'
ExportUser: '使用者' ExportUser: '使用者'
ExportStatus: '登入狀態' ExportStatus: '登入狀態'
ExportDate: '時間' ExportDate: '時間'
# 檔案
ErrFileCanNotRead: '此檔案不支援預覽' ErrFileCanNotRead: '此檔案不支援預覽'
ErrSensitiveFileRead: '不允許讀取敏感檔案' ErrSensitiveFileRead: '不允許讀取敏感檔案'
ErrFileToLarge: '檔案超過10M,無法開啟' ErrFileToLarge: '檔案超過10M,無法開啟'
@@ -164,6 +180,8 @@ FileDropFailed: '清理檔案 {{ .name }} 失敗: {{ .err }}'
FileDropSuccess: '清理檔案 {{ .name }} 成功,清理 {{ .count }} 個檔案,釋放 {{ .size }} 磁碟空間' FileDropSuccess: '清理檔案 {{ .name }} 成功,清理 {{ .count }} 個檔案,釋放 {{ .size }} 磁碟空間'
FileDropSum: '檔案清理完成,共清理 {{ .count }} 個檔案,共釋放 {{ .size }} 磁碟空間' FileDropSum: '檔案清理完成,共清理 {{ .count }} 個檔案,共釋放 {{ .size }} 磁碟空間'
ErrBadDecrypt: '壓縮檔解壓密碼錯誤,解壓失敗,請重試。' ErrBadDecrypt: '壓縮檔解壓密碼錯誤,解壓失敗,請重試。'
# 網站
ErrAliasIsExist: '代號已存在' ErrAliasIsExist: '代號已存在'
ErrBackupMatch: '該備份檔案與目前網站部分資料不符{{ .detail }}' ErrBackupMatch: '該備份檔案與目前網站部分資料不符{{ .detail }}'
ErrBackupExist: '該備份檔案對應部分來源資料不存在{{ .detail }}' ErrBackupExist: '該備份檔案對應部分來源資料不存在{{ .detail }}'
@@ -193,6 +211,8 @@ delete: '刪除'
ErrDefaultWebsite: '已經設定預設網站,請取消後再設定!' ErrDefaultWebsite: '已經設定預設網站,請取消後再設定!'
SSL: '憑證' SSL: '憑證'
Set: '設定' Set: '設定'
# SSL 憑證
ErrSSLCannotDelete: '{{ .name }} 憑證正在被網站使用,無法刪除' ErrSSLCannotDelete: '{{ .name }} 憑證正在被網站使用,無法刪除'
ErrAccountCannotDelete: '帳號關聯憑證,無法刪除' ErrAccountCannotDelete: '帳號關聯憑證,無法刪除'
ErrSSLApply: '憑證續簽成功,openresty reload 失敗,請檢查設定!' ErrSSLApply: '憑證續簽成功,openresty reload 失敗,請檢查設定!'
@@ -227,6 +247,8 @@ ErrApplySSLCanNotDelete: '正在申請的憑證 {{ .name }} 無法刪除,請
StartPushSSLToNode: '開始推送憑證到節點' StartPushSSLToNode: '開始推送憑證到節點'
PushSSLToNodeFailed: '推送憑證到節點失敗: {{ .err }}' PushSSLToNodeFailed: '推送憑證到節點失敗: {{ .err }}'
PushSSLToNodeSuccess: '推送憑證到節點成功' PushSSLToNodeSuccess: '推送憑證到節點成功'
# MySQL
ErrUserIsExist: '目前使用者已存在,請重新輸入' ErrUserIsExist: '目前使用者已存在,請重新輸入'
ErrDatabaseIsExist: '目前資料庫已存在,請重新輸入' ErrDatabaseIsExist: '目前資料庫已存在,請重新輸入'
ErrExecTimeOut: 'SQL 執行逾時,請檢查資料庫' ErrExecTimeOut: 'SQL 執行逾時,請檢查資料庫'
@@ -235,7 +257,11 @@ ErrLocalExist: '本機資料庫已存在該名稱,請修改後重試'
RemoteBackup: '備份遠端資料庫需要先使用映像 {{ .name }} 啟動本機容器資料庫服務,請稍候...' RemoteBackup: '備份遠端資料庫需要先使用映像 {{ .name }} 啟動本機容器資料庫服務,請稍候...'
RemoteRecover: '復原遠端資料庫需要先使用映像 {{ .name }} 啟動本機容器資料庫服務,請稍候...' RemoteRecover: '復原遠端資料庫需要先使用映像 {{ .name }} 啟動本機容器資料庫服務,請稍候...'
Arg: '參數' Arg: '參數'
# Redis
ErrTypeOfRedis: '復原檔案類型與目前持久化方式不符,請修改後重試' ErrTypeOfRedis: '復原檔案類型與目前持久化方式不符,請修改後重試'
# 容器
ErrInUsed: '{{ .detail }} 正被使用,無法刪除!' ErrInUsed: '{{ .detail }} 正被使用,無法刪除!'
ErrObjectInUsed: '該對象正被使用,無法刪除!' ErrObjectInUsed: '該對象正被使用,無法刪除!'
ErrObjectBeDependent: '該映像正被其他映像所依賴,無法刪除!' ErrObjectBeDependent: '該映像正被其他映像所依賴,無法刪除!'
@@ -277,6 +303,8 @@ ComposeRecoverFiles: '還原編排檔案'
ComposeRecoverContainers: '還原編排容器' ComposeRecoverContainers: '還原編排容器'
ComposeRecoverRecord: '保存編排記錄' ComposeRecoverRecord: '保存編排記錄'
ComposeRecoverCleanup: '清理編排還原工作目錄' ComposeRecoverCleanup: '清理編排還原工作目錄'
# 執行環境
ErrFileNotExist: '{{ .detail }} 檔案不存在!請檢查來源檔案完整性!' ErrFileNotExist: '{{ .detail }} 檔案不存在!請檢查來源檔案完整性!'
ErrImageBuildErr: '映像build 失敗' ErrImageBuildErr: '映像build 失敗'
ErrImageExist: '映像已存在!請修改映像名稱。' ErrImageExist: '映像已存在!請修改映像名稱。'
@@ -289,12 +317,16 @@ ErrNodeModulesNotFound: 'node_modules 資料夾不存在!請編輯執行環境
ErrContainerNameIsNull: '容器名稱不存在' ErrContainerNameIsNull: '容器名稱不存在'
ErrPHPPortIsDefault: '9000 埠為預設埠,請修改後重試' ErrPHPPortIsDefault: '9000 埠為預設埠,請修改後重試'
ErrPHPRuntimePortFailed: '{{ .name }} 埠已被目前執行環境使用,請修改後重試' ErrPHPRuntimePortFailed: '{{ .name }} 埠已被目前執行環境使用,請修改後重試'
# 工具
ErrConfigNotFound: '設定檔不存在' ErrConfigNotFound: '設定檔不存在'
ErrConfigParse: '設定檔格式有誤' ErrConfigParse: '設定檔格式有誤'
ErrConfigIsNull: '設定檔不允許為空' ErrConfigIsNull: '設定檔不允許為空'
ErrConfigDirNotFound: '執行目錄不存在' ErrConfigDirNotFound: '執行目錄不存在'
ErrConfigAlreadyExist: '已存在同名設定檔' ErrConfigAlreadyExist: '已存在同名設定檔'
ErrUserFindErr: '使用者{{ .name }} 尋找失敗{{ .err }}' ErrUserFindErr: '使用者{{ .name }} 尋找失敗{{ .err }}'
# 計劃任務
CutWebsiteLogSuccess: '{{ .name }} 網站日誌切割成功,備份路徑{{ .path }}' CutWebsiteLogSuccess: '{{ .name }} 網站日誌切割成功,備份路徑{{ .path }}'
HandleShell: '執行腳本{{ .name }}' HandleShell: '執行腳本{{ .name }}'
HandleCurl: '存取 URL {{ .name }}' HandleCurl: '存取 URL {{ .name }}'
@@ -313,6 +345,8 @@ NoSuchResource: '資料庫中未能查詢到備份內容,跳過...'
CleanLog: '清理日誌' CleanLog: '清理日誌'
CleanLogByName: '清理 {{ .name }} 日誌' CleanLogByName: '清理 {{ .name }} 日誌'
WafIpGroupNotFound: 'WAF IP 群組未找到,請先到【進階功能-WAF-黑白名單-IP群組】添加遠端下載方式的IP群組' WafIpGroupNotFound: 'WAF IP 群組未找到,請先到【進階功能-WAF-黑白名單-IP群組】添加遠端下載方式的IP群組'
# 工具箱
ErrNotExistUser: '目前使用者不存在,請修改後重試!' ErrNotExistUser: '目前使用者不存在,請修改後重試!'
ErrBanAction: '設定失敗,目前{{ .name }} 服務不可用,請重試' ErrBanAction: '設定失敗,目前{{ .name }} 服務不可用,請重試'
ErrClamdscanNotFound: '未偵測到clamdscan 指令,請參考檔案安裝!' ErrClamdscanNotFound: '未偵測到clamdscan 指令,請參考檔案安裝!'
@@ -321,11 +355,15 @@ SetSwap: '設定 Swap {{ .path }} - {{ .size }}'
CreateSwap: '建立 Swap 檔案' CreateSwap: '建立 Swap 檔案'
FormatSwap: '格式化 Swap 檔案' FormatSwap: '格式化 Swap 檔案'
EnableSwap: '啟用 Swap' EnableSwap: '啟用 Swap'
# 防篡改
CleanTamperSetting: '清理歷史防護設定' CleanTamperSetting: '清理歷史防護設定'
SetTamperWithRules: '根據規則啟動目錄防護' SetTamperWithRules: '根據規則啟動目錄防護'
ProtectDir: '防護目錄 {{ .name }}' ProtectDir: '防護目錄 {{ .name }}'
IgnoreFile: '保護檔案 {{ .name }}' IgnoreFile: '保護檔案 {{ .name }}'
TamperSetSuccessful: '防護設定完成,開始監聽以下目錄:' TamperSetSuccessful: '防護設定完成,開始監聽以下目錄:'
# WAF
ErrScope: '不支援修改此設定' ErrScope: '不支援修改此設定'
ErrStateChange: '狀態修改失敗' ErrStateChange: '狀態修改失敗'
ErrRuleExist: '規則已存在' ErrRuleExist: '規則已存在'
@@ -380,6 +418,8 @@ OpenrestyNotFound: 'OpenResty 未安裝'
remoteIpIsNull: 'IP 列表為空' remoteIpIsNull: 'IP 列表為空'
OpenrestyVersionErr: 'OpenResty 版本過低,請升級 OpenResty 至 1.27.1.2-2-2-focal' OpenrestyVersionErr: 'OpenResty 版本過低,請升級 OpenResty 至 1.27.1.2-2-2-focal'
ErrFileTooLarge: '檔案超過 1MB,無法上傳' ErrFileTooLarge: '檔案超過 1MB,無法上傳'
# 任務
TaskStart: '{{ .name }} 任務開始[START]' TaskStart: '{{ .name }} 任務開始[START]'
TaskEnd: '{{ .name }} 任務結束[COMPLETED]' TaskEnd: '{{ .name }} 任務結束[COMPLETED]'
TaskFailed: '{{ .name }} 任務失敗' TaskFailed: '{{ .name }} 任務失敗'
@@ -440,11 +480,17 @@ CustomAppstore: '自訂應用程式倉庫'
TaskExec: '執行' TaskExec: '執行'
TaskBatch: '批次操作' TaskBatch: '批次操作'
FileConvert: '檔案格式轉換' FileConvert: '檔案格式轉換'
# 任務 - ClamAV
Clamscan: '掃描 {{ .name }}' Clamscan: '掃描 {{ .name }}'
TaskScan: '掃描' TaskScan: '掃描'
# 任務 - AI
OllamaModelPull: '拉取 Ollama 模型{{ .name }}' OllamaModelPull: '拉取 Ollama 模型{{ .name }}'
OllamaModelSize: '取得 Ollama 模型{{ .name }} 大小' OllamaModelSize: '取得 Ollama 模型{{ .name }} 大小'
AIBenchmarkRun: '執行 AI 基準測試' AIBenchmarkRun: '執行 AI 基準測試'
# 任務 - 快照
Snapshot: '快照' Snapshot: '快照'
SnapDBInfo: '寫入1Panel 資料庫資訊' SnapDBInfo: '寫入1Panel 資料庫資訊'
SnapCopy: '複製檔案&目錄{{ .name }}' SnapCopy: '複製檔案&目錄{{ .name }}'
@@ -494,6 +540,8 @@ RecoverDaemonJson: '復原容器設定daemon.json 檔'
RecoverDBData: '復原資料庫資料' RecoverDBData: '復原資料庫資料'
RecoverBackups: '還原本機備份目錄' RecoverBackups: '還原本機備份目錄'
RecoverPanelData: '復原資料目錄' RecoverPanelData: '復原資料目錄'
# 任務 - 容器
ContainerImagePull: '拉取容器映像{{ .name }}' ContainerImagePull: '拉取容器映像{{ .name }}'
ContainerRemoveOld: '刪除原容器{{ .name }}' ContainerRemoveOld: '刪除原容器{{ .name }}'
ContainerImageCheck: '檢查映像是否正常拉取' ContainerImageCheck: '檢查映像是否正常拉取'
@@ -502,6 +550,8 @@ ContainerRecreate: '容器更新失敗,現在開始復原原容器'
ContainerCreate: '建立新容器{{ .name }}' ContainerCreate: '建立新容器{{ .name }}'
ContainerCreateFailed: '容器建立失敗,刪除失敗容器' ContainerCreateFailed: '容器建立失敗,刪除失敗容器'
ContainerStartCheck: '檢查容器是否已啟動' ContainerStartCheck: '檢查容器是否已啟動'
# 任務 - 映像
ImageBuild: '映像建置' ImageBuild: '映像建置'
ImagePull: '拉取映像' ImagePull: '拉取映像'
ImageRepoAuthFromDB: '從資料庫取得倉庫認證資訊' ImageRepoAuthFromDB: '從資料庫取得倉庫認證資訊'
@@ -509,6 +559,8 @@ ImagePush: '推播映像'
ImageRenameTag: '修改映像Tag' ImageRenameTag: '修改映像Tag'
ImageNewTag: '新映像Tag {{ .name }}' ImageNewTag: '新映像Tag {{ .name }}'
ComposeCreate: '建立編排' ComposeCreate: '建立編排'
# 任務 - 網站
BackupNginxConfig: '備份網站OpenResty 設定檔' BackupNginxConfig: '備份網站OpenResty 設定檔'
CompressFileSuccess: '壓縮目錄成功,壓縮為{{ .name }}' CompressFileSuccess: '壓縮目錄成功,壓縮為{{ .name }}'
CompressDir: '壓縮目錄' CompressDir: '壓縮目錄'
@@ -519,8 +571,15 @@ websiteDir: '網站目錄'
RecoverFailedStartRollBack: '復原失敗,開始回溯' RecoverFailedStartRollBack: '復原失敗,開始回溯'
AppBackupFileIncomplete: '備份檔案不完整缺少 app.json 或 app.tar.gz 檔案' AppBackupFileIncomplete: '備份檔案不完整缺少 app.json 或 app.tar.gz 檔案'
AppAttributesNotMatch: '應用程式類型或名稱不一致' AppAttributesNotMatch: '應用程式類型或名稱不一致'
# 告警
ErrAlertMethodNotSupported: '當前版本不支援此告警方式'
ErrAlertSync: '警告訊息同步錯誤,請重試。' ErrAlertSync: '警告訊息同步錯誤,請重試。'
# 任務 - 執行環境
ErrInstallExtension: '已有安裝任務正在進行,請等待任務結束' ErrInstallExtension: '已有安裝任務正在進行,請等待任務結束'
# 告警郵件範本
PanelAlertTitle: '面板警示通知' PanelAlertTitle: '面板警示通知'
TestAlertTitle: '測試郵件 - 驗證信箱連通性' TestAlertTitle: '測試郵件 - 驗證信箱連通性'
TestAlert: '這是一封測試郵件,用於確認您的郵件發送設定是否正確。' TestAlert: '這是一封測試郵件,用於確認您的郵件發送設定是否正確。'
@@ -537,6 +596,8 @@ CommonAlert: '您的 {{ .node }}{{ .ip }} 面板,{{ .msg }},詳情請登入
NodeExceptionAlert: '您的 {{ .node }}{{ .ip }} 面板,{{ .num }} 個節點出現異常,詳情請登入面板檢視。' NodeExceptionAlert: '您的 {{ .node }}{{ .ip }} 面板,{{ .num }} 個節點出現異常,詳情請登入面板檢視。'
LicenseExceptionAlert: '您的 {{ .node }}{{ .ip }} 面板,{{ .num }} 個授權出現異常,詳情請登入面板檢視。' LicenseExceptionAlert: '您的 {{ .node }}{{ .ip }} 面板,{{ .num }} 個授權出現異常,詳情請登入面板檢視。'
SSHAndPanelLoginAlert: '您的 {{ .node }}{{ .ip }} 面板,來自 {{ .loginIp }} 的 {{ .name }} 登入出現異常,詳情請登入面板檢視。' SSHAndPanelLoginAlert: '您的 {{ .node }}{{ .ip }} 面板,來自 {{ .loginIp }} 的 {{ .name }} 登入出現異常,詳情請登入面板檢視。'
# 磁碟
DeviceNotFound: '裝置 {{ .name }} 未找到' DeviceNotFound: '裝置 {{ .name }} 未找到'
DeviceIsMounted: '裝置 {{ .name }} 已掛載,請先移除' DeviceIsMounted: '裝置 {{ .name }} 已掛載,請先移除'
PartitionDiskErr: '分區失敗,{{ .err }}' PartitionDiskErr: '分區失敗,{{ .err }}'
@@ -544,9 +605,18 @@ FormatDiskErr: '格式化磁碟失敗,{{ .err }}'
MountDiskErr: '掛載磁碟失敗,{{ .err }}' MountDiskErr: '掛載磁碟失敗,{{ .err }}'
XfsNotFound: '未偵測到 xfs 檔案系統,請先安裝 xfsprogs' XfsNotFound: '未偵測到 xfs 檔案系統,請先安裝 xfsprogs'
# terminal # 終端
TerminalAIBlockedRiskyCommand: '已攔截風險命令:{{ .command }}' TerminalAIBlockedRiskyCommand: '已攔截風險命令:{{ .command }}'
TerminalAIThinking: 'AI 正在思考...' TerminalAIThinking: 'AI 正在思考...'
TerminalAIReadyToExecute: '思考完成,請按 Enter 執行(耗時 {{ .duration }},token:{{ .tokens }})' TerminalAIReadyToExecute: '思考完成,請按 Enter 執行(耗時 {{ .duration }},token:{{ .tokens }})'
TerminalAIRequestFailed: 'AI 請求失敗:{{ .err }}' TerminalAIRequestFailed: 'AI 請求失敗:{{ .err }}'
FileAISearchEmptyDir: '目前目錄下沒有可列出的檔案或資料夾(或均被過濾)。'
# AI 閘道
ErrAIProxyServiceNotInstalled: '{{ .name }} 服務未安裝'
ErrAIProxyModelAccountNotFound: '模型帳號 {{ .id }} 不存在'
ErrAIProxyModelMapRequired: '請填寫必填項'
ErrAIProxyModelMapInvalid: '模型映射必須是合法的 JSON 物件:{{ .err }}'
ErrAIProxyModelMapEmpty: '模型映射不能為空'
ErrAIProxyModelMapEmptyExternalModel: '模型映射中存在空的請求模型'
ErrAIProxyModelMapEmptyUpstreamModel: '模型 {{ .model }} 的上游模型不能為空'
AIProxyUserFallback: '已刪除使用者 (ID: {{ .id }})'
+54 -44
View File
@@ -1,32 +1,47 @@
# 基础错误
ErrInvalidParams: "参数错误: {{ .detail }}" ErrInvalidParams: "参数错误: {{ .detail }}"
ErrTokenParse: "Token 错误: {{ .detail }}" ErrTokenParse: "Token 错误: {{ .detail }}"
ErrInitialPassword: "原密码错误" ErrInitialPassword: "原密码错误"
ErrInternalServer: "服务错误: {{ .detail }}" ErrInternalServer: "服务错误: {{ .detail }}"
ErrRecordExist: "记录已存在"
ErrRecordNotFound: "记录不存在"
ErrStructTransform: "类型转换失败: {{ .err }}"
ErrNotSupportType: "不支持当前类型: {{ .name }}"
# 文件 AI
ErrFileAINotEnabled: "生成 AI 总结需在文件管理中启用并保存文件 AI 账号。关闭 AI 时仍可使用纯内容检索。" ErrFileAINotEnabled: "生成 AI 总结需在文件管理中启用并保存文件 AI 账号。关闭 AI 时仍可使用纯内容检索。"
ErrFileAISearchBadPattern: "搜索条件无效(正则或全词匹配): {{ .detail }}" ErrFileAISearchBadPattern: "搜索条件无效(正则或全词匹配): {{ .detail }}"
FileAISearchEmptyDir: "当前目录下没有可列出的文件或文件夹(或均被过滤)。"
# 远程下载
ErrWgetRemoteFailed: "远程下载地址无效或无法访问:{{ .detail }}" ErrWgetRemoteFailed: "远程下载地址无效或无法访问:{{ .detail }}"
ErrWgetInvalidContentType: "远程地址返回的不是文件内容(可能是错误页),{{ .detail }}" ErrWgetInvalidContentType: "远程地址返回的不是文件内容(可能是错误页),{{ .detail }}"
ErrWgetProxyNotConfigured: "请先在面板设置中配置代理服务器" ErrWgetProxyNotConfigured: "请先在面板设置中配置代理服务器"
ErrWgetProxyInvalid: "代理服务器地址无效:{{ .detail }}" ErrWgetProxyInvalid: "代理服务器地址无效:{{ .detail }}"
ErrRecordExist: "记录已存在"
ErrRecordNotFound: "记录不存在" # 登录与安全
ErrStructTransform: "类型转换失败: {{ .err }}"
ErrNotLogin: "用户未登录: {{ .detail }}" ErrNotLogin: "用户未登录: {{ .detail }}"
ErrPasswordExpired: "当前密码已过期: {{ .detail }}" ErrPasswordExpired: "当前密码已过期: {{ .detail }}"
ErrNotSupportType: "不支持当前类型: {{ .name }}"
ErrAlertMethodNotSupported: "当前版本不支持此告警方式" # 请求与 API
ErrProxy: "请求失败,请检查节点状态: {{ .detail }}" ErrProxy: "请求失败,请检查节点状态: {{ .detail }}"
ErrApiConfigStatusInvalid: "API 禁止访问: {{ .detail }}" ErrApiConfigStatusInvalid: "API 禁止访问: {{ .detail }}"
ErrApiConfigKeyInvalid: "API 接口密钥错误: {{ .detail }}" ErrApiConfigKeyInvalid: "API 接口密钥错误: {{ .detail }}"
ErrApiConfigIPInvalid: "调用 API 接口 IP 不在白名单: {{ .detail }}" ErrApiConfigIPInvalid: "调用 API 接口 IP 不在白名单: {{ .detail }}"
ErrApiConfigDisable: "此接口禁止 API 调用: {{ .detail }}" ErrApiConfigDisable: "此接口禁止 API 调用: {{ .detail }}"
ErrApiConfigKeyTimeInvalid: "API 时间戳错误: {{ .detail }}" ErrApiConfigKeyTimeInvalid: "API 时间戳错误: {{ .detail }}"
ErrShutDown: "命令已手动终止" ErrCreateHttpClient: "创建请求失败 {{ .err }}"
ErrHttpReqTimeOut: "请求超时 {{ .err }}"
ErrHttpReqFailed: "请求失败 {{ .err }}"
ErrNoSuchHost: "无法找到请求的服务器 {{ .err }}"
ErrHttpReqNotFound: "无法找到请求的资源 {{ .err }}"
# 快速跳转
ErrMinQuickJump: "至少设置 1 个快速跳转入口" ErrMinQuickJump: "至少设置 1 个快速跳转入口"
ErrMaxQuickJump: "最多设置 4 个快速跳转入口" ErrMaxQuickJump: "最多设置 4 个快速跳转入口"
#common # 通用
ErrShutDown: "命令已手动终止"
ErrUsernameIsExist: "用户名已存在" ErrUsernameIsExist: "用户名已存在"
ErrNameIsExist: "名称已存在" ErrNameIsExist: "名称已存在"
ErrDemoEnvironment: "演示环境,禁止操作" ErrDemoEnvironment: "演示环境,禁止操作"
@@ -45,7 +60,7 @@ ErrGroupIsDefault: "默认分组不可删除"
ErrGroupIsInWebsiteUse: "分组正在被其他网站使用,无法删除" ErrGroupIsInWebsiteUse: "分组正在被其他网站使用,无法删除"
Decrypt: "解密" Decrypt: "解密"
#agent # 智能体
ErrAgentAccountBound: "该账号已绑定智能体,无法删除" ErrAgentAccountBound: "该账号已绑定智能体,无法删除"
ErrTerminalAIAccountInUse: "该模型账号正被终端 AI 使用,请在终端 AI 设置中更换账号或关闭终端 AI 后重试" ErrTerminalAIAccountInUse: "该模型账号正被终端 AI 使用,请在终端 AI 设置中更换账号或关闭终端 AI 后重试"
ErrAgentAccountUnavailable: "账号连接信息不可用: {{ .err }}" ErrAgentAccountUnavailable: "账号连接信息不可用: {{ .err }}"
@@ -71,7 +86,7 @@ ErrAgentWebsiteUnbindUnsupported: "一键部署网站不支持手动解绑"
ErrHermesPairingCodeUnavailable: "配对码在 hermes 中暂时不存在,可能是由于网络原因,请稍后尝试" ErrHermesPairingCodeUnavailable: "配对码在 hermes 中暂时不存在,可能是由于网络原因,请稍后尝试"
ErrHermesFeishuGroupAllowlistRequiresAllowlist: "飞书群组策略为白名单时,私聊策略不能为配对码" ErrHermesFeishuGroupAllowlistRequiresAllowlist: "飞书群组策略为白名单时,私聊策略不能为配对码"
#backup # 备份与告警配置
Localhost: '本机' Localhost: '本机'
ErrBackupInUsed: "该备份账号已在计划任务中使用,无法删除" ErrBackupInUsed: "该备份账号已在计划任务中使用,无法删除"
ErrBackupCheck: "备份账号测试连接失败 {{ .err }}" ErrBackupCheck: "备份账号测试连接失败 {{ .err }}"
@@ -80,7 +95,7 @@ ErrBackupLocalCreate: "暂不支持创建本地服务器备份账号"
ErrAlertConfigInUse: "告警配置正在使用中,无法删除" ErrAlertConfigInUse: "告警配置正在使用中,无法删除"
ErrAlertConfigPhoneExist: "手机号已存在" ErrAlertConfigPhoneExist: "手机号已存在"
#app # 应用
ErrPortInUsed: "{{ .detail }} 端口已被占用!" ErrPortInUsed: "{{ .detail }} 端口已被占用!"
ErrAppLimit: "应用安装数量超限" ErrAppLimit: "应用安装数量超限"
ErrNotInstall: "应用未安装" ErrNotInstall: "应用未安装"
@@ -98,16 +113,12 @@ ErrFileParseApp: '{{ .name }} 文件解析失败 {{ .err }}'
ErrAppDirNull: '版本文件夹不存在' ErrAppDirNull: '版本文件夹不存在'
LocalAppErr: "应用 {{ .name }} 同步失败!{{ .err }}" LocalAppErr: "应用 {{ .name }} 同步失败!{{ .err }}"
ErrContainerName: "容器名称已存在" ErrContainerName: "容器名称已存在"
ErrCreateHttpClient: "创建请求失败 {{ .err }}"
ErrHttpReqTimeOut: "请求超时 {{ .err }}"
ErrHttpReqFailed: "请求失败 {{ .err }}"
ErrNoSuchHost: "无法找到请求的服务器 {{ .err }}"
ErrHttpReqNotFound: "无法找到请求的资源 {{ .err }}"
ErrContainerNotFound: '{{ .name }} 容器不存在' ErrContainerNotFound: '{{ .name }} 容器不存在'
ErrContainerMsg: '{{ .name }} 容器异常,具体请在容器页面查看日志' ErrContainerMsg: '{{ .name }} 容器异常,具体请在容器页面查看日志'
ErrAppBackup: '{{ .name }} 应用备份失败 {{ .err }}' ErrAppBackup: '{{ .name }} 应用备份失败 {{ .err }}'
ErrVersionTooLow: '当前 1Panel 版本过低,无法更新应用商店,请升级版本之后操作' ErrVersionTooLow: '当前 1Panel 版本过低,无法更新应用商店,请升级版本之后操作'
ErrAppNameExist: '应用名称已存在' ErrAppNameExist: '应用名称已存在'
ErrAppInstallNameExist: '应用安装名称 {{ .name }} 已存在'
AppStoreIsSyncing: '应用商店同步中,请稍后重试' AppStoreIsSyncing: '应用商店同步中,请稍后重试'
ErrGetCompose: "docker-compose.yml 文件获取失败!{{ .detail }}" ErrGetCompose: "docker-compose.yml 文件获取失败!{{ .detail }}"
ErrAppWarn: "状态异常,请查看日志" ErrAppWarn: "状态异常,请查看日志"
@@ -133,7 +144,7 @@ ErrDockerComposeCmdNotFound: "Docker Compose 命令不存在,请先在宿主
UseExistImage: "镜像已存在,使用存量镜像" UseExistImage: "镜像已存在,使用存量镜像"
ErrDatabaseNotFound: "数据库 {{ .name }} 不存在" ErrDatabaseNotFound: "数据库 {{ .name }} 不存在"
#ssh # SSH
ExportIP: "登录 IP" ExportIP: "登录 IP"
ExportArea: "归属地" ExportArea: "归属地"
ExportPort: "端口" ExportPort: "端口"
@@ -142,7 +153,7 @@ ExportUser: "用户"
ExportStatus: "登录状态" ExportStatus: "登录状态"
ExportDate: "时间" ExportDate: "时间"
#file # 文件
ErrFileCanNotRead: "此文件不支持预览" ErrFileCanNotRead: "此文件不支持预览"
ErrSensitiveFileRead: "不允许读取敏感文件" ErrSensitiveFileRead: "不允许读取敏感文件"
ErrFileToLarge: "文件超过 10M,无法打开" ErrFileToLarge: "文件超过 10M,无法打开"
@@ -170,7 +181,7 @@ FileDropSuccess: "清理 {{ .name }} 成功,文件 {{ .count }},释放 {{ .s
FileDropSum: "文件清理完成,共 {{ .count }},释放 {{ .size }}" FileDropSum: "文件清理完成,共 {{ .count }},释放 {{ .size }}"
ErrBadDecrypt: "压缩包密码错误,解压失败,请检查后重试" ErrBadDecrypt: "压缩包密码错误,解压失败,请检查后重试"
#website # 网站
ErrAliasIsExist: "标识已存在" ErrAliasIsExist: "标识已存在"
ErrBackupMatch: '该备份文件与当前网站部分数据不匹配 {{ .detail }}' ErrBackupMatch: '该备份文件与当前网站部分数据不匹配 {{ .detail }}'
ErrBackupExist: '该备份文件对应部分源数据不存在 {{ .detail }}' ErrBackupExist: '该备份文件对应部分源数据不存在 {{ .detail }}'
@@ -201,7 +212,7 @@ ErrDefaultWebsite: "已设置默认网站,请先取消再设置"
SSL: '证书' SSL: '证书'
Set: '设置' Set: '设置'
#ssl # SSL 证书
ErrSSLCannotDelete: "{{ .name }} 证书正在被网站使用,无法删除" ErrSSLCannotDelete: "{{ .name }} 证书正在被网站使用,无法删除"
ErrAccountCannotDelete: "账号关联证书,无法删除" ErrAccountCannotDelete: "账号关联证书,无法删除"
ErrSSLApply: "证书续签成功,但 OpenResty reload 失败,请检查配置" ErrSSLApply: "证书续签成功,但 OpenResty reload 失败,请检查配置"
@@ -237,7 +248,7 @@ StartPushSSLToNode: "开始推送证书到节点"
PushSSLToNodeFailed: "推送证书到节点失败: {{ .err }}" PushSSLToNodeFailed: "推送证书到节点失败: {{ .err }}"
PushSSLToNodeSuccess: "推送证书到节点成功" PushSSLToNodeSuccess: "推送证书到节点成功"
#mysql # MySQL
ErrUserIsExist: "用户已存在,请重新输入" ErrUserIsExist: "用户已存在,请重新输入"
ErrDatabaseIsExist: "数据库已存在,请重新输入" ErrDatabaseIsExist: "数据库已存在,请重新输入"
ErrExecTimeOut: "SQL 执行超时,请检查数据库" ErrExecTimeOut: "SQL 执行超时,请检查数据库"
@@ -247,10 +258,10 @@ RemoteBackup: "备份远程数据库前需先用镜像 {{ .name }} 启动本地
RemoteRecover: "恢复远程数据库前需先用镜像 {{ .name }} 启动本地容器数据库服务,请稍候" RemoteRecover: "恢复远程数据库前需先用镜像 {{ .name }} 启动本地容器数据库服务,请稍候"
Arg: "参数" Arg: "参数"
#redis # Redis
ErrTypeOfRedis: "恢复文件类型与当前持久化方式不符,请修改后重试" ErrTypeOfRedis: "恢复文件类型与当前持久化方式不符,请修改后重试"
#container # 容器
ErrInUsed: "{{ .detail }} 正被使用,无法删除!" ErrInUsed: "{{ .detail }} 正被使用,无法删除!"
ErrObjectInUsed: "该对象正被使用,无法删除!" ErrObjectInUsed: "该对象正被使用,无法删除!"
ErrObjectBeDependent: "该镜像正被其他镜像所依赖,无法删除!" ErrObjectBeDependent: "该镜像正被其他镜像所依赖,无法删除!"
@@ -293,7 +304,7 @@ ComposeRecoverContainers: "恢复编排容器"
ComposeRecoverRecord: "保存编排记录" ComposeRecoverRecord: "保存编排记录"
ComposeRecoverCleanup: "清理编排恢复工作目录" ComposeRecoverCleanup: "清理编排恢复工作目录"
#runtime # 运行环境
ErrFileNotExist: "{{ .detail }} 文件不存在!请检查源文件完整性!" ErrFileNotExist: "{{ .detail }} 文件不存在!请检查源文件完整性!"
ErrImageBuildErr: "镜像 build 失败" ErrImageBuildErr: "镜像 build 失败"
ErrImageExist: "镜像已存在!请修改镜像名称" ErrImageExist: "镜像已存在!请修改镜像名称"
@@ -307,7 +318,7 @@ ErrContainerNameIsNull: "容器名称不存在"
ErrPHPPortIsDefault: "9000 端口为默认端口,请修改后重试" ErrPHPPortIsDefault: "9000 端口为默认端口,请修改后重试"
ErrPHPRuntimePortFailed: "{{ .name }} 端口已被当前运行环境使用,请修改后重试" ErrPHPRuntimePortFailed: "{{ .name }} 端口已被当前运行环境使用,请修改后重试"
#tool # 工具
ErrConfigNotFound: "配置文件不存在" ErrConfigNotFound: "配置文件不存在"
ErrConfigParse: "配置文件格式有误" ErrConfigParse: "配置文件格式有误"
ErrConfigIsNull: "配置文件不允许为空" ErrConfigIsNull: "配置文件不允许为空"
@@ -315,7 +326,7 @@ ErrConfigDirNotFound: "运行目录不存在"
ErrConfigAlreadyExist: "已存在同名配置文件" ErrConfigAlreadyExist: "已存在同名配置文件"
ErrUserFindErr: "用户 {{ .name }} 查找失败 {{ .err }}" ErrUserFindErr: "用户 {{ .name }} 查找失败 {{ .err }}"
#cronjob # 计划任务
CutWebsiteLogSuccess: "{{ .name }} 网站日志切割成功,备份路径 {{ .path }}" CutWebsiteLogSuccess: "{{ .name }} 网站日志切割成功,备份路径 {{ .path }}"
HandleShell: "执行脚本 {{ .name }}" HandleShell: "执行脚本 {{ .name }}"
HandleCurl: "访问 URL {{ .name }}" HandleCurl: "访问 URL {{ .name }}"
@@ -335,7 +346,7 @@ CleanLog: "清理日志"
CleanLogByName: "清理 {{ .name }} 日志" CleanLogByName: "清理 {{ .name }} 日志"
WafIpGroupNotFound: "WAF IP组未找到,请先到【高级功能-WAF-黑白名单-IP组】添加远程下载方式的IP组" WafIpGroupNotFound: "WAF IP组未找到,请先到【高级功能-WAF-黑白名单-IP组】添加远程下载方式的IP组"
#toolbox # 工具箱
ErrNotExistUser: "当前用户不存在,请修改后重试!" ErrNotExistUser: "当前用户不存在,请修改后重试!"
ErrBanAction: "设置失败,{{ .name }} 服务不可用,请检查后重试" ErrBanAction: "设置失败,{{ .name }} 服务不可用,请检查后重试"
ErrClamdscanNotFound: "未检测到 clamdscan 命令,请按文档安装" ErrClamdscanNotFound: "未检测到 clamdscan 命令,请按文档安装"
@@ -345,14 +356,14 @@ CreateSwap: "创建 Swap 文件"
FormatSwap: "格式化 Swap 文件" FormatSwap: "格式化 Swap 文件"
EnableSwap: "启用 Swap" EnableSwap: "启用 Swap"
#tamper # 防篡改
CleanTamperSetting: "清理历史防护设置" CleanTamperSetting: "清理历史防护设置"
SetTamperWithRules: "根据规则启动目录防护" SetTamperWithRules: "根据规则启动目录防护"
ProtectDir: "防护目录 {{ .name }}" ProtectDir: "防护目录 {{ .name }}"
IgnoreFile: "保护文件 {{ .name }}" IgnoreFile: "保护文件 {{ .name }}"
TamperSetSuccessful: "防护设置完成,开始监听以下目录:" TamperSetSuccessful: "防护设置完成,开始监听以下目录:"
#waf # WAF
ErrScope: "不支持修改此配置" ErrScope: "不支持修改此配置"
ErrStateChange: "状态修改失败" ErrStateChange: "状态修改失败"
ErrRuleExist: "规则已存在" ErrRuleExist: "规则已存在"
@@ -408,7 +419,7 @@ remoteIpIsNull: "IP 列表为空"
OpenrestyVersionErr: "OpenResty 版本过低,请升级到 1.27.1.2-2-2-focal" OpenrestyVersionErr: "OpenResty 版本过低,请升级到 1.27.1.2-2-2-focal"
ErrFileTooLarge: "文件超过 1MB,无法上传" ErrFileTooLarge: "文件超过 1MB,无法上传"
#task # 任务
TaskStart: "{{ .name }} 任务开始 [START]" TaskStart: "{{ .name }} 任务开始 [START]"
TaskEnd: "{{ .name }} 任务结束 [COMPLETED]" TaskEnd: "{{ .name }} 任务结束 [COMPLETED]"
TaskFailed: "{{ .name }} 任务失败" TaskFailed: "{{ .name }} 任务失败"
@@ -470,16 +481,16 @@ TaskExec: "执行"
TaskBatch: "批量操作" TaskBatch: "批量操作"
FileConvert: "文件格式转换" FileConvert: "文件格式转换"
# task - clam # 任务 - ClamAV
Clamscan: "扫描 {{ .name }}" Clamscan: "扫描 {{ .name }}"
TaskScan: "扫描" TaskScan: "扫描"
# task - ai # 任务 - AI
OllamaModelPull: "拉取 Ollama 模型 {{ .name }}" OllamaModelPull: "拉取 Ollama 模型 {{ .name }}"
OllamaModelSize: "获取 Ollama 模型 {{ .name }} 大小" OllamaModelSize: "获取 Ollama 模型 {{ .name }} 大小"
AIBenchmarkRun: "执行 AI 基准测试" AIBenchmarkRun: "执行 AI 基准测试"
# task - snapshot # 任务 - 快照
Snapshot: "快照" Snapshot: "快照"
SnapDBInfo: "写入 1Panel 数据库信息" SnapDBInfo: "写入 1Panel 数据库信息"
SnapCopy: "复制文件/目录 {{ .name }}" SnapCopy: "复制文件/目录 {{ .name }}"
@@ -505,7 +516,6 @@ SnapCompressSize: "快照文件大小 {{ .name }}"
SnapUpload: "上传快照文件" SnapUpload: "上传快照文件"
SnapUploadTo: "上传快照文件到 {{ .name }}" SnapUploadTo: "上传快照文件到 {{ .name }}"
SnapUploadRes: "上传快照文件到 {{ .name }}" SnapUploadRes: "上传快照文件到 {{ .name }}"
SnapshotRecover: "快照恢复" SnapshotRecover: "快照恢复"
RecoverDownload: "下载快照文件" RecoverDownload: "下载快照文件"
Download: "下载" Download: "下载"
@@ -531,7 +541,7 @@ RecoverDBData: "恢复数据库数据"
RecoverBackups: "恢复本地备份目录" RecoverBackups: "恢复本地备份目录"
RecoverPanelData: "恢复数据目录" RecoverPanelData: "恢复数据目录"
# task - container # 任务 - 容器
ContainerImagePull: "拉取容器镜像 {{ .name }}" ContainerImagePull: "拉取容器镜像 {{ .name }}"
ContainerRemoveOld: "删除原容器 {{ .name }}" ContainerRemoveOld: "删除原容器 {{ .name }}"
ContainerImageCheck: "检查镜像是否正常拉取" ContainerImageCheck: "检查镜像是否正常拉取"
@@ -541,7 +551,7 @@ ContainerCreate: "创建新容器 {{ .name }}"
ContainerCreateFailed: "容器创建失败,删除失败容器" ContainerCreateFailed: "容器创建失败,删除失败容器"
ContainerStartCheck: "检查容器是否已启动" ContainerStartCheck: "检查容器是否已启动"
# task - image # 任务 - 镜像
ImageBuild: "镜像构建" ImageBuild: "镜像构建"
ImagePull: "拉取镜像" ImagePull: "拉取镜像"
ImageRepoAuthFromDB: "从数据库获取仓库认证信息" ImageRepoAuthFromDB: "从数据库获取仓库认证信息"
@@ -550,7 +560,7 @@ ImageRenameTag: "修改镜像 Tag"
ImageNewTag: "新镜像 Tag {{ .name }}" ImageNewTag: "新镜像 Tag {{ .name }}"
ComposeCreate: "创建编排" ComposeCreate: "创建编排"
# task - website # 任务 - 网站
BackupNginxConfig: "备份网站 OpenResty 配置文件" BackupNginxConfig: "备份网站 OpenResty 配置文件"
CompressFileSuccess: "压缩目录成功,压缩为 {{ .name }}" CompressFileSuccess: "压缩目录成功,压缩为 {{ .name }}"
CompressDir: "压缩目录" CompressDir: "压缩目录"
@@ -562,13 +572,14 @@ RecoverFailedStartRollBack: "恢复失败,开始回滚"
AppBackupFileIncomplete: "备份文件不完整,缺少 app.json 或 app.tar.gz 文件" AppBackupFileIncomplete: "备份文件不完整,缺少 app.json 或 app.tar.gz 文件"
AppAttributesNotMatch: "应用类型或名称不一致" AppAttributesNotMatch: "应用类型或名称不一致"
#alert # 告警
ErrAlertMethodNotSupported: "当前版本不支持此告警方式"
ErrAlertSync: "告警信息同步错误,请检查后重试" ErrAlertSync: "告警信息同步错误,请检查后重试"
#task - runtime # 任务 - 运行环境
ErrInstallExtension: "已有安装任务正在进行,请等待任务结束" ErrInstallExtension: "已有安装任务正在进行,请等待任务结束"
# alert mail template # 告警邮件模板
PanelAlertTitle: "面板告警通知" PanelAlertTitle: "面板告警通知"
TestAlertTitle: "测试邮件 - 验证邮箱连通性" TestAlertTitle: "测试邮件 - 验证邮箱连通性"
TestAlert: "这是一封测试邮件,用于验证邮箱发件配置。" TestAlert: "这是一封测试邮件,用于验证邮箱发件配置。"
@@ -586,7 +597,7 @@ NodeExceptionAlert: "您的 {{ .node }}{{ .ip }} 面板,{{ .num }} 个节点
LicenseExceptionAlert: "您的 {{ .node }}{{ .ip }} 面板,{{ .num }} 个许可证存在异常,请登录面板查看详情。" LicenseExceptionAlert: "您的 {{ .node }}{{ .ip }} 面板,{{ .num }} 个许可证存在异常,请登录面板查看详情。"
SSHAndPanelLoginAlert: "您的 {{ .node }}{{ .ip }} 面板,面板 {{ .name }} 登录 {{ .loginIp }} 异常,请登录面板查看详情。" SSHAndPanelLoginAlert: "您的 {{ .node }}{{ .ip }} 面板,面板 {{ .name }} 登录 {{ .loginIp }} 异常,请登录面板查看详情。"
#disk # 磁盘
DeviceNotFound: "设备 {{ .name }} 未找到" DeviceNotFound: "设备 {{ .name }} 未找到"
DeviceIsMounted: "设备 {{ .name }} 已挂载,请先卸载" DeviceIsMounted: "设备 {{ .name }} 已挂载,请先卸载"
PartitionDiskErr: "分区失败,{{ .err }}" PartitionDiskErr: "分区失败,{{ .err }}"
@@ -594,14 +605,13 @@ FormatDiskErr: "格式化磁盘失败,{{ .err }}"
MountDiskErr: "挂载磁盘失败,{{ .err }}" MountDiskErr: "挂载磁盘失败,{{ .err }}"
XfsNotFound: "未检测到 xfs 文件系统,请先安装 xfsprogs" XfsNotFound: "未检测到 xfs 文件系统,请先安装 xfsprogs"
# terminal # 终端
TerminalAIBlockedRiskyCommand: "已拦截风险命令:{{ .command }}" TerminalAIBlockedRiskyCommand: "已拦截风险命令:{{ .command }}"
TerminalAIThinking: "AI 正在思考..." TerminalAIThinking: "AI 正在思考..."
TerminalAIReadyToExecute: "思考完成,请回车执行(耗时 {{ .duration }},token:{{ .tokens }})" TerminalAIReadyToExecute: "思考完成,请回车执行(耗时 {{ .duration }},token:{{ .tokens }})"
TerminalAIRequestFailed: "AI 请求失败:{{ .err }}" TerminalAIRequestFailed: "AI 请求失败:{{ .err }}"
FileAISearchEmptyDir: "当前目录下没有可列出的文件或文件夹(或均被过滤)。"
# ai proxy # AI 网关
ErrAIProxyServiceNotInstalled: "{{ .name }} 服务未安装" ErrAIProxyServiceNotInstalled: "{{ .name }} 服务未安装"
ErrAIProxyModelAccountNotFound: "模型账号 {{ .id }} 不存在" ErrAIProxyModelAccountNotFound: "模型账号 {{ .id }} 不存在"
ErrAIProxyModelMapRequired: "请填写必填项" ErrAIProxyModelMapRequired: "请填写必填项"
@@ -609,4 +619,4 @@ ErrAIProxyModelMapInvalid: "模型映射必须是合法的 JSON 对象:{{ .err
ErrAIProxyModelMapEmpty: "模型映射不能为空" ErrAIProxyModelMapEmpty: "模型映射不能为空"
ErrAIProxyModelMapEmptyExternalModel: "模型映射中存在空的请求模型" ErrAIProxyModelMapEmptyExternalModel: "模型映射中存在空的请求模型"
ErrAIProxyModelMapEmptyUpstreamModel: "模型 {{ .model }} 的上游模型不能为空" ErrAIProxyModelMapEmptyUpstreamModel: "模型 {{ .model }} 的上游模型不能为空"
AIProxyUserFallback: "用户 {{ .id }}" AIProxyUserFallback: "已删除用户 (ID: {{ .id }})"
+1
View File
@@ -40,6 +40,7 @@ func InitAgentDB() {
migrations.UpdateWebsiteSSL, migrations.UpdateWebsiteSSL,
migrations.AddQuickJump, migrations.AddQuickJump,
migrations.UpdateMcpServerAddType, migrations.UpdateMcpServerAddType,
migrations.UpdateMcpServerGatewayConfig,
migrations.InitLocalSSHConn, migrations.InitLocalSSHConn,
migrations.InitLocalSSHShow, migrations.InitLocalSSHShow,
migrations.InitRecordStatus, migrations.InitRecordStatus,
+19
View File
@@ -685,6 +685,25 @@ var UpdateMcpServerAddType = &gormigrate.Migration{
}, },
} }
var UpdateMcpServerGatewayConfig = &gormigrate.Migration{
ID: "20260615-update-mcp-server-gateway-config",
Migrate: func(tx *gorm.DB) error {
if err := tx.AutoMigrate(&model.McpServer{}); err != nil {
return err
}
if err := tx.Model(&model.McpServer{}).Where("gateway_image IS NULL OR gateway_image = ''").Where("type = ?", "uvx").Update("gateway_image", "supercorp/supergateway:uvx").Error; err != nil {
return err
}
if err := tx.Model(&model.McpServer{}).Where("gateway_image IS NULL OR gateway_image = ''").Where("type <> ? OR type IS NULL OR type = ''", "uvx").Update("gateway_image", "supercorp/supergateway:3.4.3").Error; err != nil {
return err
}
if err := tx.Model(&model.McpServer{}).Where("protocol_version IS NULL OR protocol_version = ''").Update("protocol_version", "2025-06-18").Error; err != nil {
return err
}
return nil
},
}
var InitLocalSSHConn = &gormigrate.Migration{ var InitLocalSSHConn = &gormigrate.Migration{
ID: "20250905-init-local-ssh", ID: "20250905-init-local-ssh",
Migrate: func(tx *gorm.DB) error { Migrate: func(tx *gorm.DB) error {
+3
View File
@@ -29,10 +29,13 @@ func (a *AIToolsRouter) InitRouter(Router *gin.RouterGroup) {
aiToolsRouter.GET("/gpu/options", baseApi.GetCPUOptions) aiToolsRouter.GET("/gpu/options", baseApi.GetCPUOptions)
aiToolsRouter.POST("/mcp/search", baseApi.PageMcpServers) aiToolsRouter.POST("/mcp/search", baseApi.PageMcpServers)
aiToolsRouter.POST("/mcp/server/detail", baseApi.LoadMcpServerDetail)
aiToolsRouter.POST("/mcp/server", baseApi.CreateMcpServer) aiToolsRouter.POST("/mcp/server", baseApi.CreateMcpServer)
aiToolsRouter.POST("/mcp/server/update", baseApi.UpdateMcpServer) aiToolsRouter.POST("/mcp/server/update", baseApi.UpdateMcpServer)
aiToolsRouter.POST("/mcp/server/del", baseApi.DeleteMcpServer) aiToolsRouter.POST("/mcp/server/del", baseApi.DeleteMcpServer)
aiToolsRouter.POST("/mcp/server/op", baseApi.OperateMcpServer) aiToolsRouter.POST("/mcp/server/op", baseApi.OperateMcpServer)
aiToolsRouter.POST("/mcp/server/status/sync", baseApi.SyncMcpServerStatus)
aiToolsRouter.POST("/mcp/server/connection/test", baseApi.TestMcpServerConnection)
aiToolsRouter.POST("/mcp/domain/bind", baseApi.BindMcpDomain) aiToolsRouter.POST("/mcp/domain/bind", baseApi.BindMcpDomain)
aiToolsRouter.GET("/mcp/domain/get", baseApi.GetMcpBindDomain) aiToolsRouter.GET("/mcp/domain/get", baseApi.GetMcpBindDomain)
aiToolsRouter.POST("/mcp/domain/update", baseApi.UpdateMcpBindDomain) aiToolsRouter.POST("/mcp/domain/update", baseApi.UpdateMcpBindDomain)
+1
View File
@@ -21,6 +21,7 @@ func (a *WebsiteSSLRouter) InitRouter(Router *gin.RouterGroup) {
groupRouter.GET("/website/:websiteId", baseApi.GetWebsiteSSLByWebsiteId) groupRouter.GET("/website/:websiteId", baseApi.GetWebsiteSSLByWebsiteId)
groupRouter.GET("/:id", baseApi.GetWebsiteSSLById) groupRouter.GET("/:id", baseApi.GetWebsiteSSLById)
groupRouter.POST("/update", baseApi.UpdateWebsiteSSL) groupRouter.POST("/update", baseApi.UpdateWebsiteSSL)
groupRouter.POST("/push", baseApi.PushWebsiteSSLToNode)
groupRouter.POST("/upload", baseApi.UploadWebsiteSSL) groupRouter.POST("/upload", baseApi.UploadWebsiteSSL)
groupRouter.POST("/obtain", baseApi.ApplyWebsiteSSL) groupRouter.POST("/obtain", baseApi.ApplyWebsiteSSL)
groupRouter.POST("/download", baseApi.DownloadWebsiteSSL) groupRouter.POST("/download", baseApi.DownloadWebsiteSSL)
-1
View File
@@ -60,7 +60,6 @@ func pushByLegacyMethod(alertRepo repo.IAlertRepo, alert dto.AlertDTO, pushAlert
} }
config, err := alertRepo.GetConfig(alertRepo.WithByType(configType)) config, err := alertRepo.GetConfig(alertRepo.WithByType(configType))
if err != nil { if err != nil {
global.LOG.Errorf("alert config not found for type %s: %v", configType, err)
return return
} }
sendAlert(alertRepo, alert, pushAlert, config) sendAlert(alertRepo, alert, pushAlert, config)
+39
View File
@@ -2,6 +2,7 @@ package cmd
import ( import (
"bytes" "bytes"
"fmt"
"io" "io"
"os" "os"
"os/exec" "os/exec"
@@ -67,3 +68,41 @@ func Which(name string) bool {
_, err := exec.LookPath(name) _, err := exec.LookPath(name)
return err == nil return err == nil
} }
func commandStartDiagnostics(name, resolvedName, workDir string, env []string) string {
items := []string{
fmt.Sprintf("command=%q", name),
fmt.Sprintf("resolved=%q", resolvedName),
fmt.Sprintf("path=%q", envValue(env, "PATH")),
}
if workDir != "" {
items = append(items, describeWorkDir(workDir))
}
return "; " + strings.Join(items, "; ")
}
func describeWorkDir(name string) string {
statText := "stat=ok"
if info, err := os.Stat(name); err != nil {
statText = fmt.Sprintf("stat=%v", err)
} else {
statText = fmt.Sprintf("stat=mode:%s", info.Mode().String())
}
lstatText := "lstat=ok"
if info, err := os.Lstat(name); err != nil {
lstatText = fmt.Sprintf("lstat=%v", err)
} else {
lstatText = fmt.Sprintf("lstat=mode:%s", info.Mode().String())
}
return fmt.Sprintf("workdir=%q[%s %s]", name, statText, lstatText)
}
func envValue(env []string, key string) string {
prefix := key + "="
for i := len(env) - 1; i >= 0; i-- {
if strings.HasPrefix(env[i], prefix) {
return strings.TrimPrefix(env[i], prefix)
}
}
return os.Getenv(key)
}
+7 -1
View File
@@ -274,7 +274,10 @@ func startPipeCommands(cmds []*exec.Cmd) error {
for i := len(cmds) - 1; i >= 0; i-- { for i := len(cmds) - 1; i >= 0; i-- {
if err := cmds[i].Start(); err != nil { if err := cmds[i].Start(); err != nil {
killStarted(cmds[i+1:]) killStarted(cmds[i+1:])
return err if os.IsNotExist(err) {
return fmt.Errorf("cmd start failed: %w%s", err, commandStartDiagnostics(cmds[i].Args[0], cmds[i].Path, cmds[i].Dir, cmds[i].Env))
}
return fmt.Errorf("cmd start failed: %w", err)
} }
} }
return nil return nil
@@ -376,6 +379,9 @@ func (c *CommandHelper) run(name string, arg ...string) (string, error) {
}() }()
if err := cmd.Start(); err != nil { if err := cmd.Start(); err != nil {
if os.IsNotExist(err) {
return "", fmt.Errorf("cmd start failed: %w%s", err, commandStartDiagnostics(cmd.Args[0], cmd.Path, cmd.Dir, cmd.Env))
}
return "", fmt.Errorf("cmd start failed: %w", err) return "", fmt.Errorf("cmd start failed: %w", err)
} }
if c.taskItem != nil { if c.taskItem != nil {
+5 -1
View File
@@ -49,7 +49,7 @@ func Up(filePath string) (string, error) {
} }
func UpWithTask(filePath string, task *task.Task, forcePull bool) error { func UpWithTask(filePath string, task *task.Task, forcePull bool) error {
if err := pullComposeImages(filePath, forcePull, task); err != nil { if err := PullComposeImages(filePath, forcePull, task); err != nil {
return err return err
} }
base, extra := getComposeBaseCmd() base, extra := getComposeBaseCmd()
@@ -58,6 +58,10 @@ func UpWithTask(filePath string, task *task.Task, forcePull bool) error {
return cmd.NewCommandMgr(cmd.WithTask(*task), cmd.WithTimeout(20*time.Minute)).Run(base, args...) return cmd.NewCommandMgr(cmd.WithTask(*task), cmd.WithTimeout(20*time.Minute)).Run(base, args...)
} }
func PullComposeImages(filePath string, forcePull bool, task *task.Task) error {
return pullComposeImages(filePath, forcePull, task)
}
func pullComposeImages(filePath string, forcePull bool, task *task.Task) error { func pullComposeImages(filePath string, forcePull bool, task *task.Task) error {
images, err := GetComposeImages(filePath) images, err := GetComposeImages(filePath)
if err != nil { if err != nil {
+18 -5
View File
@@ -199,20 +199,33 @@ func (c Client) PullImageWithProcessAndOptions(task *task.Task, imageName string
return err return err
} }
defer out.Close() defer out.Close()
return handlePullImageProcess(out, task)
}
func handlePullImageProcess(out io.Reader, task *task.Task) error {
decoder := json.NewDecoder(out) decoder := json.NewDecoder(out)
for { for {
var progress map[string]interface{} var progress map[string]interface{}
if err = decoder.Decode(&progress); err != nil { if err := decoder.Decode(&progress); err != nil {
if err == io.EOF { if err == io.EOF {
break break
} }
return err return err
} }
status, _ := progress["status"].(string) if msg, ok := progress["errorDetail"]; ok {
if status == "Downloading" || status == "Extracting" { return fmt.Errorf("image pull failed, err: %v", msg)
logProcess(progress, task)
} }
if status == "Pull complete" || status == "Download complete" { if msg, ok := progress["error"]; ok {
return fmt.Errorf("image pull failed, err: %v", msg)
}
if task == nil {
continue
}
status, _ := progress["status"].(string)
switch status {
case "Downloading", "Extracting":
logProcess(progress, task)
case "Pull complete", "Download complete", "Already exists", "Verifying Checksum":
id, _ := progress["id"].(string) id, _ := progress["id"].(string)
progressStr := fmt.Sprintf("%s %s", status, id) progressStr := fmt.Sprintf("%s %s", status, id)
_ = setLog(id, progressStr, task) _ = setLog(id, progressStr, task)
+2 -2
View File
@@ -1376,8 +1376,8 @@ func (f FileOp) TarGzFilesWithCompressPro(list []string, dst, secret string) err
} }
func (f FileOp) TarGzExtractPro(src, dst string, secret string) error { func (f FileOp) TarGzExtractPro(src, dst string, secret string) error {
if _, err := os.Stat(path.Dir(dst)); err != nil && os.IsNotExist(err) { if _, err := os.Stat(dst); err != nil && os.IsNotExist(err) {
if err = os.MkdirAll(path.Dir(dst), os.ModePerm); err != nil { if err = os.MkdirAll(dst, os.ModePerm); err != nil {
return err return err
} }
} }
+70
View File
@@ -2,11 +2,21 @@ package req_helper
import ( import (
"bytes" "bytes"
"crypto/md5"
"crypto/rand"
"crypto/tls" "crypto/tls"
"encoding/hex"
"encoding/json"
"fmt" "fmt"
"github.com/1Panel-dev/1Panel/agent/app/model" "github.com/1Panel-dev/1Panel/agent/app/model"
"github.com/1Panel-dev/1Panel/agent/global" "github.com/1Panel-dev/1Panel/agent/global"
"io"
"net/http" "net/http"
"os"
"path"
"path/filepath"
"strings"
"time"
) )
func PostLocalCore(url string) error { func PostLocalCore(url string) error {
@@ -27,6 +37,12 @@ func PostLocalCore(url string) error {
if err != nil { if err != nil {
return err return err
} }
req.Header.Set("Content-Type", "application/json")
token, err := loadDailyLocalToken()
if err != nil {
return err
}
req.Header.Set("X-Panel-Local-Token", token)
tr := &http.Transport{ tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
} }
@@ -39,5 +55,59 @@ func PostLocalCore(url string) error {
return err return err
} }
defer resp.Body.Close() defer resp.Body.Close()
bodyBytes, err := io.ReadAll(resp.Body)
if err != nil {
return err
}
if resp.StatusCode < http.StatusOK || resp.StatusCode >= http.StatusMultipleChoices {
return fmt.Errorf("core request failed: status=%s, body=%s", resp.Status, strings.TrimSpace(string(bodyBytes)))
}
var result struct {
Code int `json:"code"`
Message string `json:"message"`
}
if len(bytes.TrimSpace(bodyBytes)) > 0 {
if err := json.Unmarshal(bodyBytes, &result); err == nil && result.Code != 0 && result.Code != http.StatusOK {
return fmt.Errorf("core request failed: code=%d, message=%s", result.Code, result.Message)
}
}
return nil return nil
} }
func loadDailyLocalToken() (string, error) {
secret, err := loadOrGenerateLocalSecret()
if err != nil {
return "", err
}
today := time.Now().Format("2006-01-02")
h := md5.New()
h.Write([]byte(secret + "-" + today))
return hex.EncodeToString(h.Sum(nil))[:16], nil
}
func loadOrGenerateLocalSecret() (string, error) {
secretFilePath := path.Join(global.Dir.TmpDir, ".secret")
data, err := os.ReadFile(secretFilePath)
if err == nil {
secret := strings.TrimSpace(string(data))
if secret != "" {
return secret, nil
}
}
if err != nil && !os.IsNotExist(err) {
return "", err
}
dir := filepath.Dir(secretFilePath)
if err := os.MkdirAll(dir, 0755); err != nil {
return "", err
}
key := make([]byte, 32)
if _, err := rand.Read(key); err != nil {
return "", err
}
secret := hex.EncodeToString(key)
if err := os.WriteFile(secretFilePath, []byte(secret), 0600); err != nil {
return "", err
}
return secret, nil
}
+37 -19
View File
@@ -20,6 +20,8 @@ import (
"github.com/go-acme/lego/v5/providers/dns/freemyip" "github.com/go-acme/lego/v5/providers/dns/freemyip"
"github.com/go-acme/lego/v5/providers/dns/godaddy" "github.com/go-acme/lego/v5/providers/dns/godaddy"
"github.com/go-acme/lego/v5/providers/dns/huaweicloud" "github.com/go-acme/lego/v5/providers/dns/huaweicloud"
"github.com/go-acme/lego/v5/providers/dns/ionos"
"github.com/go-acme/lego/v5/providers/dns/ionoscloud"
"github.com/go-acme/lego/v5/providers/dns/namecheap" "github.com/go-acme/lego/v5/providers/dns/namecheap"
"github.com/go-acme/lego/v5/providers/dns/namedotcom" "github.com/go-acme/lego/v5/providers/dns/namedotcom"
"github.com/go-acme/lego/v5/providers/dns/namesilo" "github.com/go-acme/lego/v5/providers/dns/namesilo"
@@ -37,34 +39,35 @@ import (
) )
type DnsType string type DnsType string
const ( const (
AcmeDNS DnsType = "AcmeDNS"
AliYun DnsType = "AliYun" AliYun DnsType = "AliYun"
AliESA DnsType = "AliESA" AliESA DnsType = "AliESA"
AWSRoute53 DnsType = "AWSRoute53" BaiduCloud DnsType = "BaiduCloud"
CloudFlare DnsType = "CloudFlare"
CloudDns DnsType = "CloudDns" CloudDns DnsType = "CloudDns"
NameSilo DnsType = "NameSilo" CloudFlare DnsType = "CloudFlare"
ClouDNS DnsType = "ClouDNS"
Dynadot DnsType = "Dynadot"
Dynu DnsType = "Dynu"
FreeMyIP DnsType = "FreeMyIP"
Godaddy DnsType = "Godaddy"
HuaweiCloud DnsType = "HuaweiCloud"
Ionos DnsType = "Ionos"
IonosCloud DnsType = "IonosCloud"
NameCheap DnsType = "NameCheap" NameCheap DnsType = "NameCheap"
NameCom DnsType = "NameCom" NameCom DnsType = "NameCom"
Godaddy DnsType = "Godaddy" NameSilo DnsType = "NameSilo"
TencentCloud DnsType = "TencentCloud"
RainYun DnsType = "RainYun"
Volcengine DnsType = "Volcengine"
HuaweiCloud DnsType = "HuaweiCloud"
FreeMyIP DnsType = "FreeMyIP"
Vercel DnsType = "Vercel"
Spaceship DnsType = "Spaceship"
WestCN DnsType = "WestCN"
ClouDNS DnsType = "ClouDNS"
RegRu DnsType = "RegRu"
Dynu DnsType = "Dynu"
Dynadot DnsType = "Dynadot"
BaiduCloud DnsType = "BaiduCloud"
Ovh DnsType = "Ovh" Ovh DnsType = "Ovh"
AcmeDNS DnsType = "AcmeDNS"
PorkBun DnsType = "PorkBun" PorkBun DnsType = "PorkBun"
RainYun DnsType = "RainYun"
RegRu DnsType = "RegRu"
AWSRoute53 DnsType = "AWSRoute53"
Spaceship DnsType = "Spaceship"
Technitium DnsType = "Technitium" Technitium DnsType = "Technitium"
TencentCloud DnsType = "TencentCloud"
Vercel DnsType = "Vercel"
Volcengine DnsType = "Volcengine"
WestCN DnsType = "WestCN"
) )
type DNSParam struct { type DNSParam struct {
@@ -76,6 +79,7 @@ type DNSParam struct {
APIkey string `json:"apiKey"` APIkey string `json:"apiKey"`
APIUser string `json:"apiUser"` APIUser string `json:"apiUser"`
APISecret string `json:"apiSecret"` APISecret string `json:"apiSecret"`
APIPrefix string `json:"apiPrefix"`
SecretID string `json:"secretID"` SecretID string `json:"secretID"`
ClientID string `json:"clientID"` ClientID string `json:"clientID"`
Password string `json:"password"` Password string `json:"password"`
@@ -219,6 +223,20 @@ func getDNSProviderConfig(dnsType DnsType, params string, httpClient *http.Clien
config.PollingInterval = pollingInterval config.PollingInterval = pollingInterval
config.TTL = int32(ttl) config.TTL = int32(ttl)
p, err = huaweicloud.NewDNSProviderConfig(config) p, err = huaweicloud.NewDNSProviderConfig(config)
case Ionos:
config := newDNSProviderConfig(ionos.NewDefaultConfig(), httpClient)
config.APIKey = param.APIPrefix + "." + param.APISecret
config.PropagationTimeout = propagationTimeout
config.PollingInterval = pollingInterval
config.TTL = ttl
p, err = ionos.NewDNSProviderConfig(config)
case IonosCloud:
config := newDNSProviderConfig(ionoscloud.NewDefaultConfig(), httpClient)
config.APIToken = param.Token
config.PropagationTimeout = propagationTimeout
config.PollingInterval = pollingInterval
config.TTL = ttl
p, err = ionoscloud.NewDNSProviderConfig(config)
case FreeMyIP: case FreeMyIP:
config := newDNSProviderConfig(freemyip.NewDefaultConfig(), httpClient) config := newDNSProviderConfig(freemyip.NewDefaultConfig(), httpClient)
config.Token = param.Token config.Token = param.Token
+106 -3
View File
@@ -5,6 +5,8 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"os" "os"
"os/exec"
"strconv"
"strings" "strings"
"time" "time"
@@ -250,8 +252,13 @@ func getSSHSessions(config SSHSessionConfig) (res []byte, err error) {
ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout) ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout)
defer cancel() defer cancel()
if sessions, ok := loadLoginctlSSHSessions(ctx); ok && len(sessions) > 0 {
res, err = json.Marshal(filterSSHSessions(sessions, config))
return
}
users, err = host.UsersWithContext(ctx) users, err = host.UsersWithContext(ctx)
if err != nil { if err != nil || len(users) == 0 {
res, err = json.Marshal(result) res, err = json.Marshal(result)
return return
} }
@@ -275,6 +282,22 @@ func getSSHSessions(config SSHSessionConfig) (res []byte, err error) {
return return
} }
connections, err := net.ConnectionsMaxWithContext(ctx, "all", 32768)
if err != nil {
res, err = json.Marshal(result)
return
}
pidConnections := make(map[int32][]net.ConnectionStat, 256)
for _, conn := range connections {
if conn.Pid == 0 || conn.Raddr.IP == "" {
continue
}
if _, ok := usersByHost[conn.Raddr.IP]; !ok {
continue
}
pidConnections[conn.Pid] = append(pidConnections[conn.Pid], conn)
}
processes, err = process.ProcessesWithContext(ctx) processes, err = process.ProcessesWithContext(ctx)
if err != nil { if err != nil {
res, err = json.Marshal(result) res, err = json.Marshal(result)
@@ -286,12 +309,12 @@ func getSSHSessions(config SSHSessionConfig) (res []byte, err error) {
if name != "sshd" || proc.Pid == 0 { if name != "sshd" || proc.Pid == 0 {
continue continue
} }
connections, _ := proc.Connections() connections := pidConnections[proc.Pid]
if len(connections) == 0 { if len(connections) == 0 {
continue continue
} }
cmdline, cmdErr := proc.Cmdline() cmdline, cmdErr := proc.CmdlineWithContext(ctx)
if cmdErr != nil { if cmdErr != nil {
continue continue
} }
@@ -320,6 +343,86 @@ func getSSHSessions(config SSHSessionConfig) (res []byte, err error) {
return return
} }
func loadLoginctlSSHSessions(ctx context.Context) ([]sshSession, bool) {
if _, err := exec.LookPath("loginctl"); err != nil {
return nil, false
}
output, err := exec.CommandContext(ctx, "loginctl", "list-sessions", "--no-legend", "--no-pager").Output()
if err != nil {
return nil, false
}
var result []sshSession
for _, line := range strings.Split(string(output), "\n") {
fields := strings.Fields(line)
if len(fields) == 0 {
continue
}
sessionOutput, err := exec.CommandContext(ctx, "loginctl", "show-session", fields[0], "--no-pager",
"-p", "Name", "-p", "Remote", "-p", "RemoteHost", "-p", "TTY", "-p", "Timestamp", "-p", "Leader", "-p", "Service", "-p", "State").Output()
if err != nil {
continue
}
session, ok := parseLoginctlSSHSession(string(sessionOutput))
if !ok {
continue
}
result = append(result, session)
}
return result, true
}
func filterSSHSessions(sessions []sshSession, config SSHSessionConfig) []sshSession {
result := make([]sshSession, 0, len(sessions))
for _, session := range sessions {
if config.LoginUser != "" && !strings.Contains(session.Username, config.LoginUser) {
continue
}
if config.LoginIP != "" && !strings.Contains(session.Host, config.LoginIP) {
continue
}
result = append(result, session)
}
return result
}
func parseLoginctlSSHSession(output string) (sshSession, bool) {
props := map[string]string{}
for _, line := range strings.Split(output, "\n") {
key, value, ok := strings.Cut(line, "=")
if ok {
props[key] = strings.TrimSpace(value)
}
}
service := props["Service"]
if props["Remote"] != "yes" || props["Name"] == "" || props["RemoteHost"] == "" || props["State"] != "active" || (service != "sshd" && service != "ssh") {
return sshSession{}, false
}
pid, _ := strconv.ParseInt(props["Leader"], 10, 32)
return sshSession{
Username: props["Name"],
Host: props["RemoteHost"],
Terminal: props["TTY"],
PID: int32(pid),
LoginTime: parseLoginctlTimestamp(props["Timestamp"]),
}, true
}
func parseLoginctlTimestamp(value string) string {
fields := strings.Fields(value)
for i := 0; i < len(fields)-1; i++ {
if strings.Count(fields[i], "-") != 2 || strings.Count(fields[i+1], ":") != 2 {
continue
}
candidate := fields[i] + " " + fields[i+1]
t, err := time.ParseInLocation("2006-01-02 15:04:05", candidate, time.Local)
if err != nil {
return candidate
}
return t.Format("2006-1-2 15:04:05")
}
return value
}
func getNetConnections(config NetConfig) (res []byte, err error) { func getNetConnections(config NetConfig) (res []byte, err error) {
result := make([]ProcessConnect, 0, 1024) result := make([]ProcessConnect, 0, 1024)
ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout) ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout)
+11 -10
View File
@@ -248,16 +248,17 @@ func (b *BaseApi) GetLoginSetting(c *gin.Context) {
ip := common.GetRealClientIP(c) ip := common.GetRealClientIP(c)
needCaptcha := global.IPTracker.NeedCaptcha(ip) needCaptcha := global.IPTracker.NeedCaptcha(ip)
res := &dto.LoginSetting{ res := &dto.LoginSetting{
IsDemo: global.CONF.Base.IsDemo, IsDemo: global.CONF.Base.IsDemo,
IsIntl: global.CONF.Base.Edition == "intl", IsIntl: global.CONF.Base.Edition == "intl",
IsFxplay: global.CONF.Base.IsFxplay, IsFxplay: global.CONF.Base.IsFxplay,
IsOffline: global.CONF.Base.IsOffline, IsOffline: global.CONF.Base.IsOffline,
IsEnterprise: global.CONF.Base.IsEnterprise, IsEnterprise: global.CONF.Base.IsEnterprise,
Language: settingInfo.Language, Language: settingInfo.Language,
MenuTabs: settingInfo.MenuTabs, MenuTabs: settingInfo.MenuTabs,
PanelName: settingInfo.PanelName, MenuAccordion: settingInfo.MenuAccordion,
Theme: settingInfo.Theme, PanelName: settingInfo.PanelName,
NeedCaptcha: needCaptcha, Theme: settingInfo.Theme,
NeedCaptcha: needCaptcha,
} }
res.PasskeySetting = xpack.AuthProvider.PasskeyStatus(c) res.PasskeySetting = xpack.AuthProvider.PasskeyStatus(c)
helper.SuccessWithData(c, res) helper.SuccessWithData(c, res)
+2 -1
View File
@@ -3,6 +3,7 @@ package v2
import ( import (
"encoding/base64" "encoding/base64"
"errors" "errors"
"net"
"net/http" "net/http"
"os" "os"
"path" "path"
@@ -350,7 +351,7 @@ func (b *BaseApi) UpdatePort(c *gin.Context) {
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"重载系统 SSL","formatEN":"reload system SSL"} // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"重载系统 SSL","formatEN":"reload system SSL"}
func (b *BaseApi) ReloadSSL(c *gin.Context) { func (b *BaseApi) ReloadSSL(c *gin.Context) {
clientIP := c.ClientIP() clientIP := c.ClientIP()
if clientIP != "127.0.0.1" { if ip := net.ParseIP(clientIP); ip == nil || !ip.IsLoopback() {
helper.InternalServer(c, errors.New("only localhost can reload ssl")) helper.InternalServer(c, errors.New("only localhost can reload ssl"))
return return
} }
+51 -3
View File
@@ -1,8 +1,11 @@
package auth package auth
import ( import (
"crypto/hmac"
"crypto/md5" "crypto/md5"
"crypto/sha256"
"encoding/hex" "encoding/hex"
"errors"
"net" "net"
"strconv" "strconv"
"strings" "strings"
@@ -10,6 +13,7 @@ import (
"github.com/1Panel-dev/1Panel/core/app/api/v2/helper" "github.com/1Panel-dev/1Panel/core/app/api/v2/helper"
"github.com/1Panel-dev/1Panel/core/app/repo" "github.com/1Panel-dev/1Panel/core/app/repo"
"github.com/1Panel-dev/1Panel/core/buserr"
"github.com/1Panel-dev/1Panel/core/constant" "github.com/1Panel-dev/1Panel/core/constant"
"github.com/1Panel-dev/1Panel/core/global" "github.com/1Panel-dev/1Panel/core/global"
"github.com/1Panel-dev/1Panel/core/utils/common" "github.com/1Panel-dev/1Panel/core/utils/common"
@@ -42,6 +46,11 @@ func APIAuthMiddleware(loadConfig APIAuthConfigLoader, onSuccess APIAuthSuccessH
config, err := loadConfig(c) config, err := loadConfig(c)
if err != nil { if err != nil {
var bizErr buserr.BusinessError
if errors.As(err, &bizErr) && strings.HasPrefix(bizErr.Msg, "ErrApiConfig") {
helper.BadAuth(c, bizErr.Msg, bizErr.Err)
return
}
helper.InternalServer(c, err) helper.InternalServer(c, err)
return return
} }
@@ -93,7 +102,7 @@ func LoadAPIAuthConfig(_ *gin.Context) (APIAuthConfig, error) {
return config, nil return config, nil
} }
func isValid1PanelTimestamp(panelTimestamp string, apiKeyValidityTime int) bool { func IsValid1PanelTimestamp(panelTimestamp string, apiKeyValidityTime int) bool {
apiTime := apiKeyValidityTime apiTime := apiKeyValidityTime
if apiTime < 0 { if apiTime < 0 {
return false return false
@@ -115,11 +124,32 @@ func isValid1PanelTimestamp(panelTimestamp string, apiKeyValidityTime int) bool
return nowTime-panelTime <= int64(apiTime)*60+tolerance return nowTime-panelTime <= int64(apiTime)*60+tolerance
} }
func isValid1PanelToken(panelToken string, panelTimestamp string, apiKey string) bool { func IsValid1PanelToken(panelToken string, panelTimestamp string, apiKey string) bool {
return IsValid1PanelTokenWithVersion(panelToken, panelTimestamp, apiKey, "")
}
func IsValid1PanelTokenWithVersion(panelToken string, panelTimestamp string, apiKey string, signatureVersion string) bool {
panelToken = strings.ToLower(strings.TrimSpace(panelToken))
version := strings.ToLower(strings.TrimSpace(signatureVersion))
switch version {
case "v1", "md5":
return isValidMD5Token(panelToken, panelTimestamp, apiKey)
case "hmac-sha256":
return isValidHMACSHA256Token(panelToken, panelTimestamp, apiKey)
default:
return isValidMD5Token(panelToken, panelTimestamp, apiKey) || isValidHMACSHA256Token(panelToken, panelTimestamp, apiKey)
}
}
func isValidMD5Token(panelToken string, panelTimestamp string, apiKey string) bool {
return panelToken == GenerateMD5("1panel"+apiKey+panelTimestamp) return panelToken == GenerateMD5("1panel"+apiKey+panelTimestamp)
} }
func isIPInWhiteList(clientIP string, ipWhiteString string) bool { func isValidHMACSHA256Token(panelToken string, panelTimestamp string, apiKey string) bool {
return panelToken == GenerateHMACSHA256(apiKey, "1panel:"+panelTimestamp)
}
func IsIPInWhiteList(clientIP string, ipWhiteString string) bool {
if strings.TrimSpace(ipWhiteString) == "" { if strings.TrimSpace(ipWhiteString) == "" {
global.LOG.Error("IP whitelist is empty") global.LOG.Error("IP whitelist is empty")
return false return false
@@ -158,8 +188,26 @@ func isIPInWhiteList(clientIP string, ipWhiteString string) bool {
return false return false
} }
func isValid1PanelTimestamp(panelTimestamp string, apiKeyValidityTime int) bool {
return IsValid1PanelTimestamp(panelTimestamp, apiKeyValidityTime)
}
func isValid1PanelToken(panelToken string, panelTimestamp string, apiKey string) bool {
return IsValid1PanelToken(panelToken, panelTimestamp, apiKey)
}
func isIPInWhiteList(clientIP string, ipWhiteString string) bool {
return IsIPInWhiteList(clientIP, ipWhiteString)
}
func GenerateMD5(param string) string { func GenerateMD5(param string) string {
hash := md5.New() hash := md5.New()
hash.Write([]byte(param)) hash.Write([]byte(param))
return hex.EncodeToString(hash.Sum(nil)) return hex.EncodeToString(hash.Sum(nil))
} }
func GenerateHMACSHA256(secret string, message string) string {
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(message))
return hex.EncodeToString(mac.Sum(nil))
}
+1 -1
View File
@@ -23,7 +23,7 @@ type Login struct {
Password string `json:"password" validate:"required"` Password string `json:"password" validate:"required"`
Captcha string `json:"captcha"` Captcha string `json:"captcha"`
CaptchaID string `json:"captchaID"` CaptchaID string `json:"captchaID"`
Language string `json:"language" validate:"required,oneof=zh en 'zh-Hant' ko ja ru ms 'pt-BR' tr 'es-ES'"` Language string `json:"language" validate:"required,oneof=zh en 'zh-Hant' ko ja ru ms 'pt-BR' tr 'es-ES' fa"`
} }
type SystemSetting struct { type SystemSetting struct {
+15 -11
View File
@@ -17,6 +17,7 @@ type SettingInfo struct {
Edition string `json:"edition"` Edition string `json:"edition"`
Theme string `json:"theme"` Theme string `json:"theme"`
MenuTabs string `json:"menuTabs"` MenuTabs string `json:"menuTabs"`
MenuAccordion string `json:"menuAccordion"`
Language string `json:"language"` Language string `json:"language"`
DocSource string `json:"docSource"` DocSource string `json:"docSource"`
@@ -52,16 +53,17 @@ type SettingBaseInfo struct {
DeveloperMode string `json:"developerMode"` DeveloperMode string `json:"developerMode"`
UpgradeBackupCopies string `json:"upgradeBackupCopies"` UpgradeBackupCopies string `json:"upgradeBackupCopies"`
Port string `json:"port"` Port string `json:"port"`
Ipv6 string `json:"ipv6"` Ipv6 string `json:"ipv6"`
BindAddress string `json:"bindAddress"` BindAddress string `json:"bindAddress"`
PanelName string `json:"panelName"` PanelName string `json:"panelName"`
Edition string `json:"edition"` Edition string `json:"edition"`
Theme string `json:"theme"` Theme string `json:"theme"`
MenuTabs string `json:"menuTabs"` MenuTabs string `json:"menuTabs"`
Language string `json:"language"` MenuAccordion string `json:"menuAccordion"`
HideMenu string `json:"hideMenu"` Language string `json:"language"`
DocSource string `json:"docSource"` HideMenu string `json:"hideMenu"`
DocSource string `json:"docSource"`
ServerPort string `json:"serverPort"` ServerPort string `json:"serverPort"`
SecurityEntrance string `json:"securityEntrance"` SecurityEntrance string `json:"securityEntrance"`
@@ -246,12 +248,13 @@ type TerminalInfo struct {
} }
type AppstoreUpdate struct { type AppstoreUpdate struct {
Scope string `json:"scope" validate:"required,oneof=UninstallDeleteImage UpgradeBackup UninstallDeleteBackup InstallAllowPort"` Scope string `json:"scope" validate:"required,oneof=UninstallDeleteImage UpgradeBackup UpgradeDeleteImage UninstallDeleteBackup InstallAllowPort"`
Status string `json:"status" validate:"required,oneof=Disable Enable"` Status string `json:"status" validate:"required,oneof=Disable Enable"`
} }
type AppstoreConfig struct { type AppstoreConfig struct {
UninstallDeleteImage string `json:"uninstallDeleteImage"` UninstallDeleteImage string `json:"uninstallDeleteImage"`
UpgradeBackup string `json:"upgradeBackup"` UpgradeBackup string `json:"upgradeBackup"`
UpgradeDeleteImage string `json:"upgradeDeleteImage"`
UninstallDeleteBackup string `json:"uninstallDeleteBackup"` UninstallDeleteBackup string `json:"uninstallDeleteBackup"`
InstallAllowPort string `json:"installAllowPort"` InstallAllowPort string `json:"installAllowPort"`
} }
@@ -264,6 +267,7 @@ type LoginSetting struct {
IsEnterprise bool `json:"isEnterprise"` IsEnterprise bool `json:"isEnterprise"`
Language string `json:"language"` Language string `json:"language"`
MenuTabs string `json:"menuTabs"` MenuTabs string `json:"menuTabs"`
MenuAccordion string `json:"menuAccordion"`
PanelName string `json:"panelName"` PanelName string `json:"panelName"`
Theme string `json:"theme"` Theme string `json:"theme"`
NeedCaptcha bool `json:"needCaptcha"` NeedCaptcha bool `json:"needCaptcha"`
+8
View File
@@ -43,6 +43,14 @@ func WithByName(name string) global.DBOption {
return g.Where("`name` = ?", name) return g.Where("`name` = ?", name)
} }
} }
func WithByLikeName(name string) global.DBOption {
return func(g *gorm.DB) *gorm.DB {
if len(name) == 0 {
return g
}
return g.Where("name like ?", "%"+name+"%")
}
}
func WithByUserID(userID string) global.DBOption { func WithByUserID(userID string) global.DBOption {
return func(g *gorm.DB) *gorm.DB { return func(g *gorm.DB) *gorm.DB {
return g.Where("user_id = ?", userID) return g.Where("user_id = ?", userID)
+13 -1
View File
@@ -101,6 +101,10 @@ func (u *SettingService) GetSettingInfo() (*dto.SettingInfo, error) {
info.Edition = "cn" info.Edition = "cn"
_ = settingRepo.UpdateOrCreate("Edition", info.Edition) _ = settingRepo.UpdateOrCreate("Edition", info.Edition)
} }
if info.MenuAccordion == "" {
info.MenuAccordion = constant.StatusDisable
_ = settingRepo.UpdateOrCreate("MenuAccordion", info.MenuAccordion)
}
if info.ProxyPasswdKeep != constant.StatusEnable { if info.ProxyPasswdKeep != constant.StatusEnable {
info.ProxyPasswd = "" info.ProxyPasswd = ""
} else { } else {
@@ -140,6 +144,10 @@ func (u *SettingService) GetSettingBaseInfo() (*dto.SettingBaseInfo, error) {
info.Edition = "cn" info.Edition = "cn"
_ = settingRepo.UpdateOrCreate("Edition", info.Edition) _ = settingRepo.UpdateOrCreate("Edition", info.Edition)
} }
if info.MenuAccordion == "" {
info.MenuAccordion = constant.StatusDisable
_ = settingRepo.UpdateOrCreate("MenuAccordion", info.MenuAccordion)
}
return &info, err return &info, err
} }
@@ -704,6 +712,10 @@ func (u *SettingService) GetAppstoreConfig() (*dto.AppstoreConfig, error) {
if res.UpgradeBackup == "" { if res.UpgradeBackup == "" {
res.UpgradeBackup = constant.StatusDisable res.UpgradeBackup = constant.StatusDisable
} }
res.UpgradeDeleteImage, _ = settingRepo.GetValueByKey("UpgradeDeleteImage")
if res.UpgradeDeleteImage == "" {
res.UpgradeDeleteImage = constant.StatusDisable
}
res.UninstallDeleteBackup, _ = settingRepo.GetValueByKey("UninstallDeleteBackup") res.UninstallDeleteBackup, _ = settingRepo.GetValueByKey("UninstallDeleteBackup")
if res.UninstallDeleteBackup == "" { if res.UninstallDeleteBackup == "" {
res.UninstallDeleteBackup = constant.StatusDisable res.UninstallDeleteBackup = constant.StatusDisable
@@ -762,7 +774,7 @@ func checkProxy(req dto.ProxyUpdate) error {
case "", "close": case "", "close":
return nil return nil
default: default:
return buserr.WithDetail("ErrNotSupportType", req.ProxyType, nil) return buserr.WithName("ErrNotSupportType", req.ProxyType)
} }
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
+5
View File
@@ -49,6 +49,9 @@ type SubTask struct {
const ( const (
TaskInstall = "TaskInstall" TaskInstall = "TaskInstall"
TaskCreate = "TaskCreate"
TaskUpdate = "TaskUpdate"
TaskDelete = "TaskDelete"
TaskUpgrade = "TaskUpgrade" TaskUpgrade = "TaskUpgrade"
TaskAddNode = "TaskAddNode" TaskAddNode = "TaskAddNode"
TaskSync = "TaskSync" TaskSync = "TaskSync"
@@ -65,10 +68,12 @@ const (
TaskScopeSystem = "System" TaskScopeSystem = "System"
TaskScopeScript = "ScriptLibrary" TaskScopeScript = "ScriptLibrary"
TaskScopeNodeFile = "NodeFile" TaskScopeNodeFile = "NodeFile"
TaskScopeNodeSSL = "NodeSSL"
TaskScopeAppBackup = "AppBackup" TaskScopeAppBackup = "AppBackup"
TaskScopeCluster = "Cluster" TaskScopeCluster = "Cluster"
TaskScopeAppInstall = "AppInstallTask" TaskScopeAppInstall = "AppInstallTask"
TaskScopeAI = "AI" TaskScopeAI = "AI"
TaskScopeVm = "VirtualMachine"
) )
func GetTaskName(resourceName, operate, scope string) string { func GetTaskName(resourceName, operate, scope string) string {
+359 -3
View File
@@ -74,6 +74,7 @@ const docTemplate = `{
"description": "OK", "description": "OK",
"schema": { "schema": {
"additionalProperties": { "additionalProperties": {
"format": "int64",
"type": "integer" "type": "integer"
}, },
"type": "object" "type": "object"
@@ -2883,6 +2884,44 @@ const docTemplate = `{
] ]
} }
}, },
"/ai/mcp/server/connection/test": {
"post": {
"consumes": [
"application/json"
],
"parameters": [
{
"description": "request",
"in": "body",
"name": "request",
"required": true,
"schema": {
"$ref": "#/definitions/request.McpServerConnectionTest"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/response.McpServerConnectionTestRes"
}
}
},
"security": [
{
"ApiKeyAuth": []
},
{
"Timestamp": []
}
],
"summary": "Test mcp server connection",
"tags": [
"McpServer"
]
}
},
"/ai/mcp/server/del": { "/ai/mcp/server/del": {
"post": { "post": {
"consumes": [ "consumes": [
@@ -2918,6 +2957,44 @@ const docTemplate = `{
] ]
} }
}, },
"/ai/mcp/server/detail": {
"post": {
"consumes": [
"application/json"
],
"parameters": [
{
"description": "request",
"in": "body",
"name": "request",
"required": true,
"schema": {
"$ref": "#/definitions/request.McpServerDetail"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/response.McpServerDTO"
}
}
},
"security": [
{
"ApiKeyAuth": []
},
{
"Timestamp": []
}
],
"summary": "Load mcp server detail",
"tags": [
"McpServer"
]
}
},
"/ai/mcp/server/op": { "/ai/mcp/server/op": {
"post": { "post": {
"consumes": [ "consumes": [
@@ -2953,6 +3030,47 @@ const docTemplate = `{
] ]
} }
}, },
"/ai/mcp/server/status/sync": {
"post": {
"consumes": [
"application/json"
],
"parameters": [
{
"description": "request",
"in": "body",
"name": "request",
"required": true,
"schema": {
"$ref": "#/definitions/request.McpServerStatusSync"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"items": {
"$ref": "#/definitions/response.McpServerStatusDTO"
},
"type": "array"
}
}
},
"security": [
{
"ApiKeyAuth": []
},
{
"Timestamp": []
}
],
"summary": "Sync mcp server status",
"tags": [
"McpServer"
]
}
},
"/ai/mcp/server/update": { "/ai/mcp/server/update": {
"post": { "post": {
"consumes": [ "consumes": [
@@ -27588,6 +27706,59 @@ const docTemplate = `{
} }
} }
}, },
"/websites/ssl/push": {
"post": {
"consumes": [
"application/json"
],
"parameters": [
{
"description": "request",
"in": "body",
"name": "request",
"required": true,
"schema": {
"$ref": "#/definitions/request.WebsiteSSLPush"
}
}
],
"responses": {
"200": {
"description": "OK"
}
},
"security": [
{
"ApiKeyAuth": []
},
{
"Timestamp": []
}
],
"summary": "Push ssl to nodes",
"tags": [
"Website SSL"
],
"x-panel-log": {
"BeforeFunctions": [
{
"db": "website_ssls",
"input_column": "id",
"input_value": "id",
"isList": false,
"output_column": "primary_domain",
"output_value": "domain"
}
],
"bodyKeys": [
"id"
],
"formatEN": "Push ssl to nodes [domain]",
"formatZH": "推送证书到节点 [domain]",
"paramKeys": []
}
}
},
"/websites/ssl/resolve": { "/websites/ssl/resolve": {
"post": { "post": {
"consumes": [ "consumes": [
@@ -28347,6 +28518,12 @@ const docTemplate = `{
"cpuQuota": { "cpuQuota": {
"type": "number" "type": "number"
}, },
"dashboardPassword": {
"type": "string"
},
"dashboardUsername": {
"type": "string"
},
"dockerCompose": { "dockerCompose": {
"type": "string" "type": "string"
}, },
@@ -28720,6 +28897,12 @@ const docTemplate = `{
"cpuQuota": { "cpuQuota": {
"type": "number" "type": "number"
}, },
"dashboardPassword": {
"type": "string"
},
"dashboardUsername": {
"type": "string"
},
"dockerCompose": { "dockerCompose": {
"type": "string" "type": "string"
}, },
@@ -29294,6 +29477,12 @@ const docTemplate = `{
"createdAt": { "createdAt": {
"type": "string" "type": "string"
}, },
"dashboardPassword": {
"type": "string"
},
"dashboardUsername": {
"type": "string"
},
"id": { "id": {
"type": "integer" "type": "integer"
}, },
@@ -29395,6 +29584,12 @@ const docTemplate = `{
"browserEnabled": { "browserEnabled": {
"type": "boolean" "type": "boolean"
}, },
"dashboardPassword": {
"type": "string"
},
"dashboardUsername": {
"type": "string"
},
"npmRegistry": { "npmRegistry": {
"type": "string" "type": "string"
}, },
@@ -29412,6 +29607,12 @@ const docTemplate = `{
"browserEnabled": { "browserEnabled": {
"type": "boolean" "type": "boolean"
}, },
"dashboardPassword": {
"type": "string"
},
"dashboardUsername": {
"type": "string"
},
"npmRegistry": { "npmRegistry": {
"type": "string" "type": "string"
}, },
@@ -30876,6 +31077,9 @@ const docTemplate = `{
}, },
"upgradeBackup": { "upgradeBackup": {
"type": "string" "type": "string"
},
"upgradeDeleteImage": {
"type": "string"
} }
}, },
"type": "object" "type": "object"
@@ -30886,6 +31090,7 @@ const docTemplate = `{
"enum": [ "enum": [
"UninstallDeleteImage", "UninstallDeleteImage",
"UpgradeBackup", "UpgradeBackup",
"UpgradeDeleteImage",
"UninstallDeleteBackup", "UninstallDeleteBackup",
"InstallAllowPort" "InstallAllowPort"
], ],
@@ -31531,6 +31736,9 @@ const docTemplate = `{
"fileName": { "fileName": {
"type": "string" "type": "string"
}, },
"isImmediate": {
"type": "boolean"
},
"name": { "name": {
"type": "string" "type": "string"
}, },
@@ -31713,7 +31921,8 @@ const docTemplate = `{
"restart", "restart",
"stop", "stop",
"down", "down",
"delete" "delete",
"rebuild"
], ],
"type": "string" "type": "string"
}, },
@@ -34458,6 +34667,9 @@ const docTemplate = `{
"es-es": { "es-es": {
"type": "string" "type": "string"
}, },
"fa": {
"type": "string"
},
"ja": { "ja": {
"type": "string" "type": "string"
}, },
@@ -34515,7 +34727,8 @@ const docTemplate = `{
"ms", "ms",
"pt-BR", "pt-BR",
"tr", "tr",
"es-ES" "es-ES",
"fa"
], ],
"type": "string" "type": "string"
}, },
@@ -39396,6 +39609,9 @@ const docTemplate = `{
}, },
"hostPort": { "hostPort": {
"type": "integer" "type": "integer"
},
"protocol": {
"type": "string"
} }
}, },
"type": "object" "type": "object"
@@ -40282,6 +40498,17 @@ const docTemplate = `{
], ],
"type": "object" "type": "object"
}, },
"request.McpServerConnectionTest": {
"properties": {
"id": {
"type": "integer"
}
},
"required": [
"id"
],
"type": "object"
},
"request.McpServerCreate": { "request.McpServerCreate": {
"properties": { "properties": {
"baseUrl": { "baseUrl": {
@@ -40299,6 +40526,9 @@ const docTemplate = `{
}, },
"type": "array" "type": "array"
}, },
"gatewayImage": {
"type": "string"
},
"hostIP": { "hostIP": {
"type": "string" "type": "string"
}, },
@@ -40311,12 +40541,18 @@ const docTemplate = `{
"port": { "port": {
"type": "integer" "type": "integer"
}, },
"protocolVersion": {
"type": "string"
},
"ssePath": { "ssePath": {
"type": "string" "type": "string"
}, },
"streamableHttpPath": { "streamableHttpPath": {
"type": "string" "type": "string"
}, },
"taskID": {
"type": "string"
},
"type": { "type": {
"type": "string" "type": "string"
}, },
@@ -40347,6 +40583,17 @@ const docTemplate = `{
], ],
"type": "object" "type": "object"
}, },
"request.McpServerDetail": {
"properties": {
"id": {
"type": "integer"
}
},
"required": [
"id"
],
"type": "object"
},
"request.McpServerOperate": { "request.McpServerOperate": {
"properties": { "properties": {
"id": { "id": {
@@ -40383,6 +40630,17 @@ const docTemplate = `{
], ],
"type": "object" "type": "object"
}, },
"request.McpServerStatusSync": {
"properties": {
"ids": {
"items": {
"type": "integer"
},
"type": "array"
}
},
"type": "object"
},
"request.McpServerUpdate": { "request.McpServerUpdate": {
"properties": { "properties": {
"baseUrl": { "baseUrl": {
@@ -40400,6 +40658,9 @@ const docTemplate = `{
}, },
"type": "array" "type": "array"
}, },
"gatewayImage": {
"type": "string"
},
"hostIP": { "hostIP": {
"type": "string" "type": "string"
}, },
@@ -40415,12 +40676,18 @@ const docTemplate = `{
"port": { "port": {
"type": "integer" "type": "integer"
}, },
"protocolVersion": {
"type": "string"
},
"ssePath": { "ssePath": {
"type": "string" "type": "string"
}, },
"streamableHttpPath": { "streamableHttpPath": {
"type": "string" "type": "string"
}, },
"taskID": {
"type": "string"
},
"type": { "type": {
"type": "string" "type": "string"
}, },
@@ -41281,6 +41548,9 @@ const docTemplate = `{
"source": { "source": {
"type": "string" "type": "string"
}, },
"taskID": {
"type": "string"
},
"type": { "type": {
"type": "string" "type": "string"
}, },
@@ -41298,11 +41568,17 @@ const docTemplate = `{
}, },
"request.RuntimeDelete": { "request.RuntimeDelete": {
"properties": { "properties": {
"deleteImage": {
"type": "boolean"
},
"forceDelete": { "forceDelete": {
"type": "boolean" "type": "boolean"
}, },
"id": { "id": {
"type": "integer" "type": "integer"
},
"taskID": {
"type": "string"
} }
}, },
"type": "object" "type": "object"
@@ -41691,6 +41967,9 @@ const docTemplate = `{
}, },
"request.Volume": { "request.Volume": {
"properties": { "properties": {
"mode": {
"type": "string"
},
"source": { "source": {
"type": "string" "type": "string"
}, },
@@ -41852,9 +42131,15 @@ const docTemplate = `{
], ],
"type": "string" "type": "string"
}, },
"nodes": {
"type": "string"
},
"pushDir": { "pushDir": {
"type": "boolean" "type": "boolean"
}, },
"pushNode": {
"type": "boolean"
},
"renew": { "renew": {
"type": "boolean" "type": "boolean"
}, },
@@ -42726,6 +43011,30 @@ const docTemplate = `{
}, },
"type": "object" "type": "object"
}, },
"request.WebsiteSSLPush": {
"properties": {
"id": {
"type": "integer"
},
"nodes": {
"type": "string"
},
"pushNode": {
"type": "boolean"
},
"sync": {
"type": "boolean"
},
"taskID": {
"type": "string"
}
},
"required": [
"id",
"taskID"
],
"type": "object"
},
"request.WebsiteSSLSearch": { "request.WebsiteSSLSearch": {
"properties": { "properties": {
"acmeAccountID": { "acmeAccountID": {
@@ -42745,6 +43054,7 @@ const docTemplate = `{
"orderBy": { "orderBy": {
"enum": [ "enum": [
"created_at", "created_at",
"updated_at",
"expire_date" "expire_date"
], ],
"type": "string" "type": "string"
@@ -42843,12 +43153,18 @@ const docTemplate = `{
"description": { "description": {
"type": "string" "type": "string"
}, },
"nodes": {
"type": "string"
},
"privateKey": { "privateKey": {
"type": "string" "type": "string"
}, },
"privateKeyPath": { "privateKeyPath": {
"type": "string" "type": "string"
}, },
"pushNode": {
"type": "boolean"
},
"sslID": { "sslID": {
"type": "integer" "type": "integer"
}, },
@@ -43976,6 +44292,26 @@ const docTemplate = `{
}, },
"type": "object" "type": "object"
}, },
"response.McpServerConnectionTestRes": {
"properties": {
"endpoint": {
"type": "string"
},
"message": {
"type": "string"
},
"outputTransport": {
"type": "string"
},
"protocolVersion": {
"type": "string"
},
"success": {
"type": "boolean"
}
},
"type": "object"
},
"response.McpServerDTO": { "response.McpServerDTO": {
"properties": { "properties": {
"baseUrl": { "baseUrl": {
@@ -44005,6 +44341,9 @@ const docTemplate = `{
}, },
"type": "array" "type": "array"
}, },
"gatewayImage": {
"type": "string"
},
"hostIP": { "hostIP": {
"type": "string" "type": "string"
}, },
@@ -44023,6 +44362,9 @@ const docTemplate = `{
"port": { "port": {
"type": "integer" "type": "integer"
}, },
"protocolVersion": {
"type": "string"
},
"ssePath": { "ssePath": {
"type": "string" "type": "string"
}, },
@@ -44050,6 +44392,20 @@ const docTemplate = `{
}, },
"type": "object" "type": "object"
}, },
"response.McpServerStatusDTO": {
"properties": {
"id": {
"type": "integer"
},
"message": {
"type": "string"
},
"status": {
"type": "string"
}
},
"type": "object"
},
"response.McpServersRes": { "response.McpServersRes": {
"properties": { "properties": {
"items": { "items": {
@@ -45145,4 +45501,4 @@ var SwaggerInfo = &swag.Spec{
func init() { func init() {
swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo) swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo)
} }
+358 -2
View File
@@ -70,6 +70,7 @@
"description": "OK", "description": "OK",
"schema": { "schema": {
"additionalProperties": { "additionalProperties": {
"format": "int64",
"type": "integer" "type": "integer"
}, },
"type": "object" "type": "object"
@@ -2879,6 +2880,44 @@
] ]
} }
}, },
"/ai/mcp/server/connection/test": {
"post": {
"consumes": [
"application/json"
],
"parameters": [
{
"description": "request",
"in": "body",
"name": "request",
"required": true,
"schema": {
"$ref": "#/definitions/request.McpServerConnectionTest"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/response.McpServerConnectionTestRes"
}
}
},
"security": [
{
"ApiKeyAuth": []
},
{
"Timestamp": []
}
],
"summary": "Test mcp server connection",
"tags": [
"McpServer"
]
}
},
"/ai/mcp/server/del": { "/ai/mcp/server/del": {
"post": { "post": {
"consumes": [ "consumes": [
@@ -2914,6 +2953,44 @@
] ]
} }
}, },
"/ai/mcp/server/detail": {
"post": {
"consumes": [
"application/json"
],
"parameters": [
{
"description": "request",
"in": "body",
"name": "request",
"required": true,
"schema": {
"$ref": "#/definitions/request.McpServerDetail"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/response.McpServerDTO"
}
}
},
"security": [
{
"ApiKeyAuth": []
},
{
"Timestamp": []
}
],
"summary": "Load mcp server detail",
"tags": [
"McpServer"
]
}
},
"/ai/mcp/server/op": { "/ai/mcp/server/op": {
"post": { "post": {
"consumes": [ "consumes": [
@@ -2949,6 +3026,47 @@
] ]
} }
}, },
"/ai/mcp/server/status/sync": {
"post": {
"consumes": [
"application/json"
],
"parameters": [
{
"description": "request",
"in": "body",
"name": "request",
"required": true,
"schema": {
"$ref": "#/definitions/request.McpServerStatusSync"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"items": {
"$ref": "#/definitions/response.McpServerStatusDTO"
},
"type": "array"
}
}
},
"security": [
{
"ApiKeyAuth": []
},
{
"Timestamp": []
}
],
"summary": "Sync mcp server status",
"tags": [
"McpServer"
]
}
},
"/ai/mcp/server/update": { "/ai/mcp/server/update": {
"post": { "post": {
"consumes": [ "consumes": [
@@ -27584,6 +27702,59 @@
} }
} }
}, },
"/websites/ssl/push": {
"post": {
"consumes": [
"application/json"
],
"parameters": [
{
"description": "request",
"in": "body",
"name": "request",
"required": true,
"schema": {
"$ref": "#/definitions/request.WebsiteSSLPush"
}
}
],
"responses": {
"200": {
"description": "OK"
}
},
"security": [
{
"ApiKeyAuth": []
},
{
"Timestamp": []
}
],
"summary": "Push ssl to nodes",
"tags": [
"Website SSL"
],
"x-panel-log": {
"BeforeFunctions": [
{
"db": "website_ssls",
"input_column": "id",
"input_value": "id",
"isList": false,
"output_column": "primary_domain",
"output_value": "domain"
}
],
"bodyKeys": [
"id"
],
"formatEN": "Push ssl to nodes [domain]",
"formatZH": "推送证书到节点 [domain]",
"paramKeys": []
}
}
},
"/websites/ssl/resolve": { "/websites/ssl/resolve": {
"post": { "post": {
"consumes": [ "consumes": [
@@ -28343,6 +28514,12 @@
"cpuQuota": { "cpuQuota": {
"type": "number" "type": "number"
}, },
"dashboardPassword": {
"type": "string"
},
"dashboardUsername": {
"type": "string"
},
"dockerCompose": { "dockerCompose": {
"type": "string" "type": "string"
}, },
@@ -28716,6 +28893,12 @@
"cpuQuota": { "cpuQuota": {
"type": "number" "type": "number"
}, },
"dashboardPassword": {
"type": "string"
},
"dashboardUsername": {
"type": "string"
},
"dockerCompose": { "dockerCompose": {
"type": "string" "type": "string"
}, },
@@ -29290,6 +29473,12 @@
"createdAt": { "createdAt": {
"type": "string" "type": "string"
}, },
"dashboardPassword": {
"type": "string"
},
"dashboardUsername": {
"type": "string"
},
"id": { "id": {
"type": "integer" "type": "integer"
}, },
@@ -29391,6 +29580,12 @@
"browserEnabled": { "browserEnabled": {
"type": "boolean" "type": "boolean"
}, },
"dashboardPassword": {
"type": "string"
},
"dashboardUsername": {
"type": "string"
},
"npmRegistry": { "npmRegistry": {
"type": "string" "type": "string"
}, },
@@ -29408,6 +29603,12 @@
"browserEnabled": { "browserEnabled": {
"type": "boolean" "type": "boolean"
}, },
"dashboardPassword": {
"type": "string"
},
"dashboardUsername": {
"type": "string"
},
"npmRegistry": { "npmRegistry": {
"type": "string" "type": "string"
}, },
@@ -30872,6 +31073,9 @@
}, },
"upgradeBackup": { "upgradeBackup": {
"type": "string" "type": "string"
},
"upgradeDeleteImage": {
"type": "string"
} }
}, },
"type": "object" "type": "object"
@@ -30882,6 +31086,7 @@
"enum": [ "enum": [
"UninstallDeleteImage", "UninstallDeleteImage",
"UpgradeBackup", "UpgradeBackup",
"UpgradeDeleteImage",
"UninstallDeleteBackup", "UninstallDeleteBackup",
"InstallAllowPort" "InstallAllowPort"
], ],
@@ -31527,6 +31732,9 @@
"fileName": { "fileName": {
"type": "string" "type": "string"
}, },
"isImmediate": {
"type": "boolean"
},
"name": { "name": {
"type": "string" "type": "string"
}, },
@@ -31709,7 +31917,8 @@
"restart", "restart",
"stop", "stop",
"down", "down",
"delete" "delete",
"rebuild"
], ],
"type": "string" "type": "string"
}, },
@@ -34454,6 +34663,9 @@
"es-es": { "es-es": {
"type": "string" "type": "string"
}, },
"fa": {
"type": "string"
},
"ja": { "ja": {
"type": "string" "type": "string"
}, },
@@ -34511,7 +34723,8 @@
"ms", "ms",
"pt-BR", "pt-BR",
"tr", "tr",
"es-ES" "es-ES",
"fa"
], ],
"type": "string" "type": "string"
}, },
@@ -39392,6 +39605,9 @@
}, },
"hostPort": { "hostPort": {
"type": "integer" "type": "integer"
},
"protocol": {
"type": "string"
} }
}, },
"type": "object" "type": "object"
@@ -40278,6 +40494,17 @@
], ],
"type": "object" "type": "object"
}, },
"request.McpServerConnectionTest": {
"properties": {
"id": {
"type": "integer"
}
},
"required": [
"id"
],
"type": "object"
},
"request.McpServerCreate": { "request.McpServerCreate": {
"properties": { "properties": {
"baseUrl": { "baseUrl": {
@@ -40295,6 +40522,9 @@
}, },
"type": "array" "type": "array"
}, },
"gatewayImage": {
"type": "string"
},
"hostIP": { "hostIP": {
"type": "string" "type": "string"
}, },
@@ -40307,12 +40537,18 @@
"port": { "port": {
"type": "integer" "type": "integer"
}, },
"protocolVersion": {
"type": "string"
},
"ssePath": { "ssePath": {
"type": "string" "type": "string"
}, },
"streamableHttpPath": { "streamableHttpPath": {
"type": "string" "type": "string"
}, },
"taskID": {
"type": "string"
},
"type": { "type": {
"type": "string" "type": "string"
}, },
@@ -40343,6 +40579,17 @@
], ],
"type": "object" "type": "object"
}, },
"request.McpServerDetail": {
"properties": {
"id": {
"type": "integer"
}
},
"required": [
"id"
],
"type": "object"
},
"request.McpServerOperate": { "request.McpServerOperate": {
"properties": { "properties": {
"id": { "id": {
@@ -40379,6 +40626,17 @@
], ],
"type": "object" "type": "object"
}, },
"request.McpServerStatusSync": {
"properties": {
"ids": {
"items": {
"type": "integer"
},
"type": "array"
}
},
"type": "object"
},
"request.McpServerUpdate": { "request.McpServerUpdate": {
"properties": { "properties": {
"baseUrl": { "baseUrl": {
@@ -40396,6 +40654,9 @@
}, },
"type": "array" "type": "array"
}, },
"gatewayImage": {
"type": "string"
},
"hostIP": { "hostIP": {
"type": "string" "type": "string"
}, },
@@ -40411,12 +40672,18 @@
"port": { "port": {
"type": "integer" "type": "integer"
}, },
"protocolVersion": {
"type": "string"
},
"ssePath": { "ssePath": {
"type": "string" "type": "string"
}, },
"streamableHttpPath": { "streamableHttpPath": {
"type": "string" "type": "string"
}, },
"taskID": {
"type": "string"
},
"type": { "type": {
"type": "string" "type": "string"
}, },
@@ -41277,6 +41544,9 @@
"source": { "source": {
"type": "string" "type": "string"
}, },
"taskID": {
"type": "string"
},
"type": { "type": {
"type": "string" "type": "string"
}, },
@@ -41294,11 +41564,17 @@
}, },
"request.RuntimeDelete": { "request.RuntimeDelete": {
"properties": { "properties": {
"deleteImage": {
"type": "boolean"
},
"forceDelete": { "forceDelete": {
"type": "boolean" "type": "boolean"
}, },
"id": { "id": {
"type": "integer" "type": "integer"
},
"taskID": {
"type": "string"
} }
}, },
"type": "object" "type": "object"
@@ -41687,6 +41963,9 @@
}, },
"request.Volume": { "request.Volume": {
"properties": { "properties": {
"mode": {
"type": "string"
},
"source": { "source": {
"type": "string" "type": "string"
}, },
@@ -41848,9 +42127,15 @@
], ],
"type": "string" "type": "string"
}, },
"nodes": {
"type": "string"
},
"pushDir": { "pushDir": {
"type": "boolean" "type": "boolean"
}, },
"pushNode": {
"type": "boolean"
},
"renew": { "renew": {
"type": "boolean" "type": "boolean"
}, },
@@ -42722,6 +43007,30 @@
}, },
"type": "object" "type": "object"
}, },
"request.WebsiteSSLPush": {
"properties": {
"id": {
"type": "integer"
},
"nodes": {
"type": "string"
},
"pushNode": {
"type": "boolean"
},
"sync": {
"type": "boolean"
},
"taskID": {
"type": "string"
}
},
"required": [
"id",
"taskID"
],
"type": "object"
},
"request.WebsiteSSLSearch": { "request.WebsiteSSLSearch": {
"properties": { "properties": {
"acmeAccountID": { "acmeAccountID": {
@@ -42741,6 +43050,7 @@
"orderBy": { "orderBy": {
"enum": [ "enum": [
"created_at", "created_at",
"updated_at",
"expire_date" "expire_date"
], ],
"type": "string" "type": "string"
@@ -42839,12 +43149,18 @@
"description": { "description": {
"type": "string" "type": "string"
}, },
"nodes": {
"type": "string"
},
"privateKey": { "privateKey": {
"type": "string" "type": "string"
}, },
"privateKeyPath": { "privateKeyPath": {
"type": "string" "type": "string"
}, },
"pushNode": {
"type": "boolean"
},
"sslID": { "sslID": {
"type": "integer" "type": "integer"
}, },
@@ -43972,6 +44288,26 @@
}, },
"type": "object" "type": "object"
}, },
"response.McpServerConnectionTestRes": {
"properties": {
"endpoint": {
"type": "string"
},
"message": {
"type": "string"
},
"outputTransport": {
"type": "string"
},
"protocolVersion": {
"type": "string"
},
"success": {
"type": "boolean"
}
},
"type": "object"
},
"response.McpServerDTO": { "response.McpServerDTO": {
"properties": { "properties": {
"baseUrl": { "baseUrl": {
@@ -44001,6 +44337,9 @@
}, },
"type": "array" "type": "array"
}, },
"gatewayImage": {
"type": "string"
},
"hostIP": { "hostIP": {
"type": "string" "type": "string"
}, },
@@ -44019,6 +44358,9 @@
"port": { "port": {
"type": "integer" "type": "integer"
}, },
"protocolVersion": {
"type": "string"
},
"ssePath": { "ssePath": {
"type": "string" "type": "string"
}, },
@@ -44046,6 +44388,20 @@
}, },
"type": "object" "type": "object"
}, },
"response.McpServerStatusDTO": {
"properties": {
"id": {
"type": "integer"
},
"message": {
"type": "string"
},
"status": {
"type": "string"
}
},
"type": "object"
},
"response.McpServersRes": { "response.McpServersRes": {
"properties": { "properties": {
"items": { "items": {
+358 -53
View File
@@ -1247,6 +1247,33 @@
"formatZH": "更新 AI 网关分组 [name]", "formatZH": "更新 AI 网关分组 [name]",
"formatEN": "update AI proxy group [name]" "formatEN": "update AI proxy group [name]"
}, },
"/core/enterprise/ai-proxy/model-groups/create": {
"bodyKeys": [
"name"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "创建 AI 网关模型组 [name]",
"formatEN": "create AI proxy model group [name]"
},
"/core/enterprise/ai-proxy/model-groups/delete": {
"bodyKeys": [
"id"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "删除 AI 网关模型组 [id]",
"formatEN": "delete AI proxy model group [id]"
},
"/core/enterprise/ai-proxy/model-groups/update": {
"bodyKeys": [
"name"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "更新 AI 网关模型组 [name]",
"formatEN": "update AI proxy model group [name]"
},
"/core/enterprise/ai-proxy/service/operate": { "/core/enterprise/ai-proxy/service/operate": {
"bodyKeys": [ "bodyKeys": [
"operate" "operate"
@@ -1368,13 +1395,14 @@
"/core/enterprise/skills-hub/import": { "/core/enterprise/skills-hub/import": {
"bodyKeys": [ "bodyKeys": [
"type", "type",
"version",
"repoURL", "repoURL",
"packageURL" "packageURL"
], ],
"paramKeys": [], "paramKeys": [],
"beforeFunctions": [], "beforeFunctions": [],
"formatZH": "导入 Skills Hub 技能 [type]", "formatZH": "导入 Skills Hub 技能版本 [version]",
"formatEN": "import Skills Hub skill [type]" "formatEN": "import Skills Hub skill version [version]"
}, },
"/core/enterprise/skills-hub/status": { "/core/enterprise/skills-hub/status": {
"bodyKeys": [ "bodyKeys": [
@@ -1478,11 +1506,13 @@
"formatEN": "update Skills Hub install target [name]" "formatEN": "update Skills Hub install target [name]"
}, },
"/core/enterprise/skills-hub/upload": { "/core/enterprise/skills-hub/upload": {
"bodyKeys": [], "bodyKeys": [
"version"
],
"paramKeys": [], "paramKeys": [],
"beforeFunctions": [], "beforeFunctions": [],
"formatZH": "上传 Skills Hub 技能包", "formatZH": "上传 Skills Hub 技能包版本 [version]",
"formatEN": "upload Skills Hub package" "formatEN": "upload Skills Hub package version [version]"
}, },
"/core/enterprise/users": { "/core/enterprise/users": {
"bodyKeys": [ "bodyKeys": [
@@ -1493,6 +1523,25 @@
"formatZH": "添加用户 [name]", "formatZH": "添加用户 [name]",
"formatEN": "add user [name]" "formatEN": "add user [name]"
}, },
"/core/enterprise/users/api/update": {
"bodyKeys": [
"id",
"ipWhiteList"
],
"paramKeys": [],
"beforeFunctions": [
{
"input_column": "id",
"input_value": "id",
"isList": false,
"db": "users",
"output_column": "name",
"output_value": "name"
}
],
"formatZH": "更新用户 [name] API 接口配置 =\u003e IP 白名单: [ipWhiteList]",
"formatEN": "update user [name] api config =\u003e IP White List: [ipWhiteList]"
},
"/core/enterprise/users/del": { "/core/enterprise/users/del": {
"bodyKeys": [ "bodyKeys": [
"ids" "ids"
@@ -1529,6 +1578,255 @@
"formatZH": "更新 [name]", "formatZH": "更新 [name]",
"formatEN": "update user [name]" "formatEN": "update user [name]"
}, },
"/core/enterprise/vms": {
"bodyKeys": [
"name"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "创建虚拟机 [name]",
"formatEN": "create VM [name]"
},
"/core/enterprise/vms/del": {
"bodyKeys": [
"name"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "删除虚拟机 [name]",
"formatEN": "delete VM [name]"
},
"/core/enterprise/vms/iso": {
"bodyKeys": [
"name",
"type"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "创建虚拟机镜像 [name] [type]",
"formatEN": "create VM ISO [name] [type]"
},
"/core/enterprise/vms/iso/del": {
"bodyKeys": [
"id"
],
"paramKeys": [],
"beforeFunctions": [
{
"input_column": "id",
"input_value": "id",
"isList": false,
"db": "vm_isos",
"output_column": "name",
"output_value": "name"
}
],
"formatZH": "删除虚拟机镜像 [name]",
"formatEN": "delete VM ISO [name]"
},
"/core/enterprise/vms/iso/update": {
"bodyKeys": [
"name",
"type"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "更新虚拟机镜像 [name] [type]",
"formatEN": "update VM ISO [name] [type]"
},
"/core/enterprise/vms/networks": {
"bodyKeys": [
"name",
"type"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "创建虚拟机网络 [name] [type]",
"formatEN": "create VM network [name] [type]"
},
"/core/enterprise/vms/networks/del": {
"bodyKeys": [
"id"
],
"paramKeys": [],
"beforeFunctions": [
{
"input_column": "id",
"input_value": "id",
"isList": false,
"db": "vm_networks",
"output_column": "name",
"output_value": "name"
}
],
"formatZH": "删除虚拟机网络 [name]",
"formatEN": "delete VM network [name]"
},
"/core/enterprise/vms/networks/sync": {
"bodyKeys": [],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "同步虚拟机网络",
"formatEN": "sync VM networks"
},
"/core/enterprise/vms/networks/update": {
"bodyKeys": [
"id"
],
"paramKeys": [],
"beforeFunctions": [
{
"input_column": "id",
"input_value": "id",
"isList": false,
"db": "vm_networks",
"output_column": "name",
"output_value": "name"
}
],
"formatZH": "更新虚拟机网络 [name]",
"formatEN": "update VM network [name]"
},
"/core/enterprise/vms/operate": {
"bodyKeys": [
"name",
"operate"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "操作虚拟机 [name] [operate]",
"formatEN": "operate VM [name] [operate]"
},
"/core/enterprise/vms/rename": {
"bodyKeys": [
"name",
"newName"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "重命名虚拟机 [name] 为 [newName]",
"formatEN": "rename VM [name] to [newName]"
},
"/core/enterprise/vms/snapshots": {
"bodyKeys": [
"name",
"snapshotName"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "创建虚拟机 [name] 快照 [snapshotName]",
"formatEN": "create VM [name] snapshot [snapshotName]"
},
"/core/enterprise/vms/snapshots/del": {
"bodyKeys": [
"name",
"snapshotName"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "删除虚拟机 [name] 快照 [snapshotName]",
"formatEN": "delete VM [name] snapshot [snapshotName]"
},
"/core/enterprise/vms/snapshots/recover": {
"bodyKeys": [
"name",
"snapshotName"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "恢复虚拟机 [name] 快照 [snapshotName]",
"formatEN": "recover VM [name] snapshot [snapshotName]"
},
"/core/enterprise/vms/storages": {
"bodyKeys": [
"name",
"type"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "创建虚拟机存储 [name] [type]",
"formatEN": "create VM storage [name] [type]"
},
"/core/enterprise/vms/storages/del": {
"bodyKeys": [
"id"
],
"paramKeys": [],
"beforeFunctions": [
{
"input_column": "id",
"input_value": "id",
"isList": false,
"db": "vm_storages",
"output_column": "name",
"output_value": "name"
}
],
"formatZH": "删除虚拟机存储 [name]",
"formatEN": "delete VM storage [name]"
},
"/core/enterprise/vms/storages/sync": {
"bodyKeys": [],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "同步虚拟机存储",
"formatEN": "sync VM storages"
},
"/core/enterprise/vms/storages/update": {
"bodyKeys": [
"id"
],
"paramKeys": [],
"beforeFunctions": [
{
"input_column": "id",
"input_value": "id",
"isList": false,
"db": "vm_storages",
"output_column": "name",
"output_value": "name"
}
],
"formatZH": "更新虚拟机存储 [name]",
"formatEN": "update VM storage [name]"
},
"/core/enterprise/vms/templates": {
"bodyKeys": [
"name",
"templateName"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "创建虚拟机 [name] 模板 [templateName]",
"formatEN": "create VM [name] template [templateName]"
},
"/core/enterprise/vms/templates/del": {
"bodyKeys": [
"id"
],
"paramKeys": [],
"beforeFunctions": [
{
"input_column": "id",
"input_value": "id",
"isList": false,
"db": "vm_templates",
"output_column": "name",
"output_value": "name"
}
],
"formatZH": "删除虚拟机模板 [name]",
"formatEN": "delete VM template [name]"
},
"/core/enterprise/vms/update": {
"bodyKeys": [
"name"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "更新虚拟机 [name]",
"formatEN": "update VM [name]"
},
"/core/groups": { "/core/groups": {
"bodyKeys": [ "bodyKeys": [
"name", "name",
@@ -1853,15 +2151,22 @@
}, },
"/core/xpack/exchange/file": { "/core/xpack/exchange/file": {
"bodyKeys": [ "bodyKeys": [
"source", "sourceNode",
"dest", "targetNode",
"sourcePath", "sourcePath",
"destPath" "targetPath"
], ],
"paramKeys": [], "paramKeys": [],
"beforeFunctions": [], "beforeFunctions": [],
"formatZH": "交换文件 [sourcePath] 到 [destPath]", "formatZH": "交换文件 [sourcePath] 到 [targetPath]",
"formatEN": "exchange file [sourcePath] to [destPath]" "formatEN": "exchange file [sourcePath] to [targetPath]"
},
"/core/xpack/exchange/image": {
"bodyKeys": [],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "同步节点镜像",
"formatEN": "sync images"
}, },
"/core/xpack/nodes": { "/core/xpack/nodes": {
"bodyKeys": [ "bodyKeys": [
@@ -2166,6 +2471,15 @@
"formatZH": "更新自定义应用配置 [status]", "formatZH": "更新自定义应用配置 [status]",
"formatEN": "update custom app config [status]" "formatEN": "update custom app config [status]"
}, },
"/core/xpack/settings/app/image-prefix": {
"bodyKeys": [
"imagePrefix"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "更新应用镜像前缀 [imagePrefix]",
"formatEN": "update app image prefix [imagePrefix]"
},
"/core/xpack/settings/reset": { "/core/xpack/settings/reset": {
"bodyKeys": [], "bodyKeys": [],
"paramKeys": [], "paramKeys": [],
@@ -2191,27 +2505,11 @@
"formatEN": "update xpack setting [key]" "formatEN": "update xpack setting [key]"
}, },
"/core/xpack/sync/app": { "/core/xpack/sync/app": {
"bodyKeys": [ "bodyKeys": [],
"sourceNode",
"targetNode",
"appInstallID",
"appBackupID"
],
"paramKeys": [], "paramKeys": [],
"beforeFunctions": [], "beforeFunctions": [],
"formatZH": "同步应用备份 [appInstallID] 到节点 [targetNode]", "formatZH": "同步节点应用",
"formatEN": "sync app backup [appInstallID] to node [targetNode]" "formatEN": "sync app"
},
"/core/xpack/sync/app/install": {
"bodyKeys": [
"appKey",
"version",
"nodes"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "安装应用 [appKey] [version] 到节点 [nodes]",
"formatEN": "install app [appKey] [version] to nodes [nodes]"
}, },
"/core/xpack/sync/ssl": { "/core/xpack/sync/ssl": {
"bodyKeys": [ "bodyKeys": [
@@ -2352,34 +2650,14 @@
"formatZH": "更新自定义应用配置 [status]", "formatZH": "更新自定义应用配置 [status]",
"formatEN": "update custom app config [status]" "formatEN": "update custom app config [status]"
}, },
"/custom/app/install": { "/custom/app/image-prefix": {
"bodyKeys": [ "bodyKeys": [
"name", "imagePrefix"
"appKey"
], ],
"paramKeys": [], "paramKeys": [],
"beforeFunctions": [], "beforeFunctions": [],
"formatZH": "从节点安装应用 [name]", "formatZH": "更新应用镜像前缀 [imagePrefix]",
"formatEN": "install app [name] from node" "formatEN": "update app image prefix [imagePrefix]"
},
"/custom/app/install/check": {
"bodyKeys": [
"name",
"appKey"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "检查应用安装 [name]",
"formatEN": "check app install [name]"
},
"/custom/app/push": {
"bodyKeys": [
"appBackupID"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "推送应用备份 [appBackupID] 到节点",
"formatEN": "push app backup [appBackupID] to node"
}, },
"/custom/app/sync": { "/custom/app/sync": {
"bodyKeys": [], "bodyKeys": [],
@@ -4440,6 +4718,24 @@
"formatZH": "申请证书 [domain]", "formatZH": "申请证书 [domain]",
"formatEN": "apply ssl [domain]" "formatEN": "apply ssl [domain]"
}, },
"/websites/ssl/push": {
"bodyKeys": [
"id"
],
"paramKeys": [],
"beforeFunctions": [
{
"input_column": "id",
"input_value": "id",
"isList": false,
"db": "website_ssls",
"output_column": "primary_domain",
"output_value": "domain"
}
],
"formatZH": "推送证书到节点 [domain]",
"formatEN": "Push ssl to nodes [domain]"
},
"/websites/ssl/update": { "/websites/ssl/update": {
"bodyKeys": [ "bodyKeys": [
"id" "id"
@@ -4935,6 +5231,15 @@
"formatZH": "更新[scope]频率访问限制", "formatZH": "更新[scope]频率访问限制",
"formatEN": "update [scope] CC config" "formatEN": "update [scope] CC config"
}, },
"/xpack/waf/rule/common/apply": {
"bodyKeys": [
"scope"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "应用规则 [scope] 到网站",
"formatEN": "apply rule [scope] to websites"
},
"/xpack/waf/rule/common/create": { "/xpack/waf/rule/common/create": {
"bodyKeys": [ "bodyKeys": [
"scope" "scope"
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+27 -18
View File
@@ -57,23 +57,24 @@ var WebUrlMap = map[string]struct{}{
"/apps/upgrade": {}, "/apps/upgrade": {},
"/apps/setting": {}, "/apps/setting": {},
"/ai": {}, "/ai": {},
"/ai/ai-proxy": {}, "/ai/ai-proxy": {},
"/ai/ai-proxy/model-pool": {}, "/ai/ai-proxy/model-pool": {},
"/ai/ai-proxy/api-keys": {}, "/ai/ai-proxy/api-keys": {},
"/ai/ai-proxy/groups": {}, "/ai/ai-proxy/groups": {},
"/ai/ai-proxy/usage": {}, "/ai/ai-proxy/model-groups": {},
"/ai/ai-proxy/content": {}, "/ai/ai-proxy/usage": {},
"/ai/skills-hub": {}, "/ai/ai-proxy/content": {},
"/ai/skills-hub/targets": {}, "/ai/skills-hub": {},
"/ai/benchmark": {}, "/ai/skills-hub/targets": {},
"/ai/model/account": {}, "/ai/benchmark": {},
"/ai/model/local": {}, "/ai/model/account": {},
"/ai/gpu": {}, "/ai/model/local": {},
"/ai/gpu/current": {}, "/ai/gpu": {},
"/ai/gpu/history": {}, "/ai/gpu/current": {},
"/ai/mcp": {}, "/ai/gpu/history": {},
"/ai/agents/agent": {}, "/ai/mcp": {},
"/ai/agents/agent": {},
"/containers": {}, "/containers": {},
"/containers/container/operate": {}, "/containers/container/operate": {},
@@ -182,7 +183,10 @@ var WebUrlMap = map[string]struct{}{
"/xpack/node/dashboard": {}, "/xpack/node/dashboard": {},
"/xpack/node": {}, "/xpack/node": {},
"/xpack/simple-node": {}, "/xpack/simple-node": {},
"/xpack/exchange/file": {}, "/xpack/sync/file": {},
"/xpack/sync/image": {},
"/xpack/sync/ssl": {},
"/xpack/sync/app": {},
"/xpack/app": {}, "/xpack/app": {},
"/xpack/app-upgrade": {}, "/xpack/app-upgrade": {},
@@ -204,6 +208,11 @@ var WebUrlMap = map[string]struct{}{
"/enterprise/ops-report/alert": {}, "/enterprise/ops-report/alert": {},
"/enterprise/ops-report/history": {}, "/enterprise/ops-report/history": {},
"/enterprise/ops-report/settings": {}, "/enterprise/ops-report/settings": {},
"/enterprise/vm/list": {},
"/enterprise/vm/isos": {},
"/enterprise/vm/templates": {},
"/enterprise/vm/networks": {},
"/enterprise/vm/storage-pools": {},
} }
var DynamicRoutes = []string{ var DynamicRoutes = []string{
+14 -5
View File
@@ -1,6 +1,6 @@
module github.com/1Panel-dev/1Panel/core module github.com/1Panel-dev/1Panel/core
go 1.25.7 go 1.26.1
require ( require (
github.com/1panel-dev/base64Captcha v1.3.8 github.com/1panel-dev/base64Captcha v1.3.8
@@ -16,13 +16,13 @@ require (
github.com/google/uuid v1.6.0 github.com/google/uuid v1.6.0
github.com/gorilla/websocket v1.5.3 github.com/gorilla/websocket v1.5.3
github.com/jinzhu/copier v0.4.0 github.com/jinzhu/copier v0.4.0
github.com/johnfercher/maroto/v2 v2.4.0
github.com/nicksnyder/go-i18n/v2 v2.6.1 github.com/nicksnyder/go-i18n/v2 v2.6.1
github.com/oschwald/maxminddb-golang v1.13.1 github.com/oschwald/maxminddb-golang v1.13.1
github.com/patrickmn/go-cache v2.1.0+incompatible github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/pkg/errors v0.9.1 github.com/pkg/errors v0.9.1
github.com/pkg/sftp v1.13.10 github.com/pkg/sftp v1.13.10
github.com/robfig/cron/v3 v3.0.1 github.com/robfig/cron/v3 v3.0.1
github.com/signintech/gopdf v0.36.1
github.com/sirupsen/logrus v1.9.4 github.com/sirupsen/logrus v1.9.4
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
github.com/soheilhy/cmux v0.1.5 github.com/soheilhy/cmux v0.1.5
@@ -32,22 +32,25 @@ require (
github.com/swaggo/swag v1.16.6 github.com/swaggo/swag v1.16.6
github.com/xlzd/gotp v0.1.0 github.com/xlzd/gotp v0.1.0
golang.org/x/crypto v0.53.0 golang.org/x/crypto v0.53.0
golang.org/x/net v0.55.0 golang.org/x/net v0.56.0
golang.org/x/sys v0.46.0 golang.org/x/sys v0.46.0
golang.org/x/term v0.44.0 golang.org/x/term v0.44.0
golang.org/x/text v0.38.0 golang.org/x/text v0.38.0
gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
gorm.io/gorm v1.31.1 gorm.io/gorm v1.31.2
) )
require ( require (
github.com/KyleBanks/depth v1.2.1 // indirect github.com/KyleBanks/depth v1.2.1 // indirect
github.com/boombuler/barcode v1.1.0 // indirect
github.com/bytedance/gopkg v0.1.4 // indirect github.com/bytedance/gopkg v0.1.4 // indirect
github.com/bytedance/sonic v1.15.0 // indirect github.com/bytedance/sonic v1.15.0 // indirect
github.com/bytedance/sonic/loader v0.5.1 // indirect github.com/bytedance/sonic/loader v0.5.1 // indirect
github.com/clipperhouse/uax29/v2 v2.7.0 // indirect
github.com/cloudwego/base64x v0.1.6 // indirect github.com/cloudwego/base64x v0.1.6 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect github.com/dustin/go-humanize v1.0.1 // indirect
github.com/f-amaral/go-async v0.3.0 // indirect
github.com/fxamacker/cbor/v2 v2.9.2 // indirect github.com/fxamacker/cbor/v2 v2.9.2 // indirect
github.com/gabriel-vasile/mimetype v1.4.13 // indirect github.com/gabriel-vasile/mimetype v1.4.13 // indirect
github.com/gin-contrib/sse v1.1.1 // indirect github.com/gin-contrib/sse v1.1.1 // indirect
@@ -71,20 +74,26 @@ require (
github.com/golang-jwt/jwt/v5 v5.3.1 // indirect github.com/golang-jwt/jwt/v5 v5.3.1 // indirect
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/google/go-tpm v0.9.8 // indirect github.com/google/go-tpm v0.9.8 // indirect
github.com/hhrutter/lzw v1.0.0 // indirect
github.com/hhrutter/pkcs7 v0.2.0 // indirect
github.com/hhrutter/tiff v1.0.2 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect github.com/jinzhu/now v1.1.5 // indirect
github.com/johnfercher/go-tree v1.1.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.3.0 // indirect github.com/klauspost/cpuid/v2 v2.3.0 // indirect
github.com/kr/fs v0.1.0 // indirect github.com/kr/fs v0.1.0 // indirect
github.com/leodido/go-urn v1.4.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect
github.com/mattn/go-isatty v0.0.21 // indirect github.com/mattn/go-isatty v0.0.21 // indirect
github.com/mattn/go-runewidth v0.0.21 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/ncruces/go-strftime v1.0.0 // indirect github.com/ncruces/go-strftime v1.0.0 // indirect
github.com/pdfcpu/pdfcpu v0.11.1 // indirect
github.com/pelletier/go-toml/v2 v2.3.0 // indirect github.com/pelletier/go-toml/v2 v2.3.0 // indirect
github.com/philhofer/fwd v1.2.0 // indirect github.com/philhofer/fwd v1.2.0 // indirect
github.com/phpdave11/gofpdi v1.0.14-0.20211212211723-1f10f9844311 // indirect github.com/phpdave11/gofpdf v1.4.3 // indirect
github.com/quic-go/qpack v0.6.0 // indirect github.com/quic-go/qpack v0.6.0 // indirect
github.com/quic-go/quic-go v0.59.0 // indirect github.com/quic-go/quic-go v0.59.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
+38 -8
View File
@@ -4,12 +4,17 @@ github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk
github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/boombuler/barcode v1.1.0 h1:ChaYjBR63fr4LFyGn8E8nt7dBSt3MiU3zMOZqFvVkHo=
github.com/boombuler/barcode v1.1.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/bytedance/gopkg v0.1.4 h1:oZnQwnX82KAIWb7033bEwtxvTqXcYMxDBaQxo5JJHWM= github.com/bytedance/gopkg v0.1.4 h1:oZnQwnX82KAIWb7033bEwtxvTqXcYMxDBaQxo5JJHWM=
github.com/bytedance/gopkg v0.1.4/go.mod h1:v1zWfPm21Fb+OsyXN2VAHdL6TBb2L88anLQgdyje6R4= github.com/bytedance/gopkg v0.1.4/go.mod h1:v1zWfPm21Fb+OsyXN2VAHdL6TBb2L88anLQgdyje6R4=
github.com/bytedance/sonic v1.15.0 h1:/PXeWFaR5ElNcVE84U0dOHjiMHQOwNIx3K4ymzh/uSE= github.com/bytedance/sonic v1.15.0 h1:/PXeWFaR5ElNcVE84U0dOHjiMHQOwNIx3K4ymzh/uSE=
github.com/bytedance/sonic v1.15.0/go.mod h1:tFkWrPz0/CUCLEF4ri4UkHekCIcdnkqXw9VduqpJh0k= github.com/bytedance/sonic v1.15.0/go.mod h1:tFkWrPz0/CUCLEF4ri4UkHekCIcdnkqXw9VduqpJh0k=
github.com/bytedance/sonic/loader v0.5.1 h1:Ygpfa9zwRCCKSlrp5bBP/b/Xzc3VxsAW+5NIYXrOOpI= github.com/bytedance/sonic/loader v0.5.1 h1:Ygpfa9zwRCCKSlrp5bBP/b/Xzc3VxsAW+5NIYXrOOpI=
github.com/bytedance/sonic/loader v0.5.1/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo= github.com/bytedance/sonic/loader v0.5.1/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo=
github.com/clipperhouse/uax29/v2 v2.7.0 h1:+gs4oBZ2gPfVrKPthwbMzWZDaAFPGYK72F0NJv2v7Vk=
github.com/clipperhouse/uax29/v2 v2.7.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM=
github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M= github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M=
github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU= github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
@@ -20,6 +25,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/f-amaral/go-async v0.3.0 h1:h4kLsX7aKfdWaHvV0lf+/EE3OIeCzyeDYJDb/vDZUyg=
github.com/f-amaral/go-async v0.3.0/go.mod h1:Hz5Qr6DAWpbTTUjytnrg1WIsDgS7NtOei5y8SipYS7U=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.10.1 h1:b0/UzAf9yR5rhf3RPm9gf3ehBPpf0oZKIjtpKrx59Ho= github.com/fsnotify/fsnotify v1.10.1 h1:b0/UzAf9yR5rhf3RPm9gf3ehBPpf0oZKIjtpKrx59Ho=
@@ -106,6 +113,12 @@ github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aN
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/hhrutter/lzw v1.0.0 h1:laL89Llp86W3rRs83LvKbwYRx6INE8gDn0XNb1oXtm0=
github.com/hhrutter/lzw v1.0.0/go.mod h1:2HC6DJSn/n6iAZfgM3Pg+cP1KxeWc3ezG8bBqW5+WEo=
github.com/hhrutter/pkcs7 v0.2.0 h1:i4HN2XMbGQpZRnKBLsUwO3dSckzgX142TNqY/KfXg+I=
github.com/hhrutter/pkcs7 v0.2.0/go.mod h1:aEzKz0+ZAlz7YaEMY47jDHL14hVWD6iXt0AgqgAvWgE=
github.com/hhrutter/tiff v1.0.2 h1:7H3FQQpKu/i5WaSChoD1nnJbGx4MxU5TlNqqpxw55z8=
github.com/hhrutter/tiff v1.0.2/go.mod h1:pcOeuK5loFUE7Y/WnzGw20YxUdnqjY1P0Jlcieb/cCw=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8= github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8=
@@ -114,8 +127,13 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/johnfercher/go-tree v1.1.0 h1:L0Fs5jLR1uA2e/CwfHjNdO/Lt4IGQ46QgxarAC1yeXs=
github.com/johnfercher/go-tree v1.1.0/go.mod h1:DUO6QkXIFh1K7jeGBIkLCZaeUgnkdQAsB64FDSoHswg=
github.com/johnfercher/maroto/v2 v2.4.0 h1:Nc/jA2RCZvNZESrQj41HJOgtkwmerSHd5FUbP4dRrIE=
github.com/johnfercher/maroto/v2 v2.4.0/go.mod h1:Nnxa3g4f+vzdx/u/dUgx/52HnrCOCt5QBPSdeSlkFZQ=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8= github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
@@ -128,6 +146,10 @@ github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/mattn/go-isatty v0.0.21 h1:xYae+lCNBP7QuW4PUnNG61ffM4hVIfm+zUzDuSzYLGs= github.com/mattn/go-isatty v0.0.21 h1:xYae+lCNBP7QuW4PUnNG61ffM4hVIfm+zUzDuSzYLGs=
github.com/mattn/go-isatty v0.0.21/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4= github.com/mattn/go-isatty v0.0.21/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4=
github.com/mattn/go-runewidth v0.0.21 h1:jJKAZiQH+2mIinzCJIaIG9Be1+0NR+5sz/lYEEjdM8w=
github.com/mattn/go-runewidth v0.0.21/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -141,12 +163,15 @@ github.com/oschwald/maxminddb-golang v1.13.1 h1:G3wwjdN9JmIK2o/ermkHM+98oX5fS+k5
github.com/oschwald/maxminddb-golang v1.13.1/go.mod h1:K4pgV9N/GcK694KSTmVSDTODk4IsCNThNdTmnaBZ/F8= github.com/oschwald/maxminddb-golang v1.13.1/go.mod h1:K4pgV9N/GcK694KSTmVSDTODk4IsCNThNdTmnaBZ/F8=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/pdfcpu/pdfcpu v0.11.1 h1:htHBSkGH5jMKWC6e0sihBFbcKZ8vG1M67c8/dJxhjas=
github.com/pdfcpu/pdfcpu v0.11.1/go.mod h1:pP3aGga7pRvwFWAm9WwFvo+V68DfANi9kxSQYioNYcw=
github.com/pelletier/go-toml/v2 v2.3.0 h1:k59bC/lIZREW0/iVaQR8nDHxVq8OVlIzYCOJf421CaM= github.com/pelletier/go-toml/v2 v2.3.0 h1:k59bC/lIZREW0/iVaQR8nDHxVq8OVlIzYCOJf421CaM=
github.com/pelletier/go-toml/v2 v2.3.0/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/pelletier/go-toml/v2 v2.3.0/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
github.com/philhofer/fwd v1.2.0 h1:e6DnBTl7vGY+Gz322/ASL4Gyp1FspeMvx1RNDoToZuM= github.com/philhofer/fwd v1.2.0 h1:e6DnBTl7vGY+Gz322/ASL4Gyp1FspeMvx1RNDoToZuM=
github.com/philhofer/fwd v1.2.0/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM= github.com/philhofer/fwd v1.2.0/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM=
github.com/phpdave11/gofpdi v1.0.14-0.20211212211723-1f10f9844311 h1:zyWXQ6vu27ETMpYsEMAsisQ+GqJ4e1TPvSNfdOPF0no= github.com/phpdave11/gofpdf v1.4.3 h1:M/zHvS8FO3zh9tUd2RCOPEjyuVcs281FCyF22Qlz/IA=
github.com/phpdave11/gofpdi v1.0.14-0.20211212211723-1f10f9844311/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= github.com/phpdave11/gofpdf v1.4.3/go.mod h1:MAwzoUIgD3J55u0rxIG2eu37c+XWhBtXSpPAhnQXf/o=
github.com/phpdave11/gofpdi v1.0.15/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -165,10 +190,9 @@ github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzG
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w=
github.com/sagikazarmark/locafero v0.12.0 h1:/NQhBAkUb4+fH1jivKHWusDYFjMOOKU88eegjfxfHb4= github.com/sagikazarmark/locafero v0.12.0 h1:/NQhBAkUb4+fH1jivKHWusDYFjMOOKU88eegjfxfHb4=
github.com/sagikazarmark/locafero v0.12.0/go.mod h1:sZh36u/YSZ918v0Io+U9ogLYQJ9tLLBmM4eneO6WwsI= github.com/sagikazarmark/locafero v0.12.0/go.mod h1:sZh36u/YSZ918v0Io+U9ogLYQJ9tLLBmM4eneO6WwsI=
github.com/signintech/gopdf v0.36.1 h1:cGpvEKvvqCV+ZXB9R2SQoWgouW91JpwsgoQEhLxIdp0=
github.com/signintech/gopdf v0.36.1/go.mod h1:d23eO35GpEliSrF22eJ4bsM3wVeQJTjXTHq5x5qGKjA=
github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w=
github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0= github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
@@ -190,6 +214,9 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4=
github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
@@ -225,14 +252,15 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto= golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto=
golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio= golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio=
golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.39.0 h1:skVYidAEVKgn8lZ602XO75asgXBgLj9G/FE3RbuPFww= golang.org/x/image v0.39.0 h1:skVYidAEVKgn8lZ602XO75asgXBgLj9G/FE3RbuPFww=
golang.org/x/image v0.39.0/go.mod h1:sIbmppfU+xFLPIG0FoVUTvyBMmgng1/XAMhQ2ft0hpA= golang.org/x/image v0.39.0/go.mod h1:sIbmppfU+xFLPIG0FoVUTvyBMmgng1/XAMhQ2ft0hpA=
golang.org/x/mod v0.36.0 h1:JJjpVx6myfUsUdAzZuOSTTmRE0PfZeNWzzvKrP7amb4= golang.org/x/mod v0.36.0 h1:JJjpVx6myfUsUdAzZuOSTTmRE0PfZeNWzzvKrP7amb4=
golang.org/x/mod v0.36.0/go.mod h1:moc6ELqsWcOw5Ef3xVprK5ul/MvtVvkIXLziUOICjUQ= golang.org/x/mod v0.36.0/go.mod h1:moc6ELqsWcOw5Ef3xVprK5ul/MvtVvkIXLziUOICjUQ=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8= golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o=
golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww= golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec=
golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM= golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM=
golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -261,8 +289,10 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/gorm v1.31.1 h1:7CA8FTFz/gRfgqgpeKIBcervUn3xSyPUmr6B2WXJ7kg= gorm.io/driver/sqlite v1.6.0 h1:WHRRrIiulaPiPFmDcod6prc4l2VGVWHz80KspNsxSfQ=
gorm.io/gorm v1.31.1/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs= gorm.io/driver/sqlite v1.6.0/go.mod h1:AO9V1qIQddBESngQUKWL9yoH93HIeA1X6V633rBwyT8=
gorm.io/gorm v1.31.2 h1:3o8FXNo9v9S858gil+3LlZA1LkCOzgb4g5BL64FgaCo=
gorm.io/gorm v1.31.2/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs=
modernc.org/cc/v4 v4.27.3 h1:uNCgn37E5U09mTv1XgskEVUJ8ADKpmFMPxzGJ0TSo+U= modernc.org/cc/v4 v4.27.3 h1:uNCgn37E5U09mTv1XgskEVUJ8ADKpmFMPxzGJ0TSo+U=
modernc.org/cc/v4 v4.27.3/go.mod h1:3YjcbCqhoTTHPycJDRl2WZKKFj0nwcOIPBfEZK0Hdk8= modernc.org/cc/v4 v4.27.3/go.mod h1:3YjcbCqhoTTHPycJDRl2WZKKFj0nwcOIPBfEZK0Hdk8=
modernc.org/ccgo/v4 v4.32.4 h1:L5OB8rpEX4ZsXEQwGozRfJyJSFHbbNVOoQ59DU9/KuU= modernc.org/ccgo/v4 v4.32.4 h1:L5OB8rpEX4ZsXEQwGozRfJyJSFHbbNVOoQ59DU9/KuU=
+1
View File
@@ -28,6 +28,7 @@ var langFiles = map[string]string{
"ko": "lang/ko.yaml", "ko": "lang/ko.yaml",
"tr": "lang/tr.yaml", "tr": "lang/tr.yaml",
"es-ES": "lang/es-ES.yaml", "es-ES": "lang/es-ES.yaml",
"fa": "lang/fa.yaml",
} }
func GetMsgWithMap(key string, maps map[string]interface{}) string { func GetMsgWithMap(key string, maps map[string]interface{}) string {
+158 -101
View File
@@ -1,16 +1,36 @@
# base errors
ErrInvalidParams: "Invalid request parameters: {{ .detail }}" ErrInvalidParams: "Invalid request parameters: {{ .detail }}"
ErrTokenParse: "Token generation error: {{ .detail }}" ErrTokenParse: "Token generation error: {{ .detail }}"
ErrInitialPassword: "Incorrect initial password" ErrInitialPassword: "Incorrect initial password"
ErrInternalServer: "Internal server error: {{ .detail }}" ErrInternalServer: "Internal server error: {{ .detail }}"
ErrInternalServerKey: "Internal server error:"
ErrRecordExist: "Record already exists" ErrRecordExist: "Record already exists"
ErrRecordNotFound: "Record not found" ErrRecordNotFound: "Record not found"
ErrStructTransform: "Type conversion failed: {{ .detail }}" ErrStructTransform: "Type conversion failed: {{ .detail }}"
ErrNotSupportType: "Unsupported type: {{ .name }}"
ErrDemoEnvironment: "Demo server, this operation is prohibited!"
ErrCmdTimeout: "Command execution timeout!"
ErrPortInUsed: "The {{ .name }} port is already in use!"
ErrFileNotFound: "{{ .name }} file does not exist"
ErrReqFailed: "{{.name}} request failed: {{ .err }}"
# request and entrance
ErrNoSuchHost: "Host resolution failed: {{ .err }}"
ErrHttpReqNotFound: "Requested resource not found: {{ .err }}"
ErrHttpReqFailed: "Request failed {{ .err }}"
ErrHttpReqTimeOut: "Request timed out {{ .err }}"
ErrCreateHttpClient: "Failed to create request {{ .err }}"
ErrProxy: "Request failed; check this node status: {{ .detail }}"
ErrProxySetting: "Proxy server information unavailable {{ .err }}, check and try again!"
ErrEntrance: "Security entrance information error, check and try again!"
ErrEntranceFormat: "Security entry {{ .name }} is not supported. Check and try again."
# login and security
ErrNotLogin: "User not logged in: {{ .detail }}" ErrNotLogin: "User not logged in: {{ .detail }}"
ErrSessionDataNotFound: "Session expired" ErrSessionDataNotFound: "Session expired"
ErrSessionDataFormat: "Invalid session data format" ErrSessionDataFormat: "Invalid session data format"
ErrPasswordExpired: "Password expired: {{ .detail }}" ErrPasswordExpired: "Password expired: {{ .detail }}"
ErrNotSupportType: "Unsupported type: {{ .detail }}" ErrLoginLocked: "Too many failed attempts. Login is temporarily locked for 5 minutes."
ErrProxy: "Request failed; check this node status: {{ .detail }}"
ErrApiConfigStatusInvalid: "API access disabled: {{ .detail }}" ErrApiConfigStatusInvalid: "API access disabled: {{ .detail }}"
ErrApiConfigKeyInvalid: "Invalid API key: {{ .detail }}" ErrApiConfigKeyInvalid: "Invalid API key: {{ .detail }}"
ErrApiConfigIPInvalid: "The API request IP is not on the whitelist: {{ .detail }}" ErrApiConfigIPInvalid: "The API request IP is not on the whitelist: {{ .detail }}"
@@ -22,53 +42,24 @@ ErrPasskeyLimit: "Passkey limit reached (max 5)"
ErrPasskeySession: "Passkey session expired or invalid" ErrPasskeySession: "Passkey session expired or invalid"
ErrPasskeyDuplicate: "Passkey already exists" ErrPasskeyDuplicate: "Passkey already exists"
ErrPasskeyVerify: "Passkey verification failed" ErrPasskeyVerify: "Passkey verification failed"
ErrLoginLocked: "Too many failed attempts. Login is temporarily locked for 5 minutes."
# request # user and permission
ErrNoSuchHost: "Host resolution failed: {{ .err }}" ErrNoSuchUser: "User information not found, check and try again!"
ErrHttpReqNotFound: "Requested resource not found: {{ .err }}" ErrToMaster: "This user does not have permission to perform this operation on the master node. Check and try again!"
ErrHttpReqFailed: "Request failed {{ .err }}" ErrToNode: "This user does not have permission to perform this operation on this node. Check and try again!"
ErrHttpReqTimeOut: "Request timed out {{ .err }}" ErrRBAC: "Insufficient user permissions. This operation cannot be performed. Check and try again!"
ErrCreateHttpClient: "Failed to create request {{ .err }}" ErrNoneNode: "This user has no node permissions. Contact an administrator or check and try again!"
ErrProxySetting: "Proxy server information unavailable {{ .err }}, check and try again!" ErrOnlySuperAdmin: "Only super admins can use this feature!"
ErrEntranceFormat: "Security entry {{ .name }} is not supported. Check and try again." ErrRolePresetCannotDelete: "System preset roles cannot be deleted"
ErrRolePresetCannotUpdate: "System preset roles cannot be updated"
# common ErrRoleBoundToUser: "This role is already bound to users and cannot be deleted"
ErrDemoEnvironment: "Demo server, this operation is prohibited!" ErrRolePresetCannotBind: "System preset roles cannot be assigned to users"
ErrCmdTimeout: "Command execution timeout!" ErrNodeAdminMasterForbidden: "Node Admin permissions cannot be added to the master node"
ErrEntrance: "Security entrance information error, check and try again!" ErrSuperAdminCannotDelete: "Super admin users cannot be deleted"
ErrGroupIsDefault: "Default group, unable to delete" ErrGroupIsDefault: "Default group, unable to delete"
ErrGroupIsInUse: "The group is in use and cannot be deleted." ErrGroupIsInUse: "The group is in use and cannot be deleted."
ErrAIProxyUserGroupIsDefault: "Default user group cannot be deleted."
ErrAIProxyUserGroupInUse: "The user group is in use and cannot be deleted."
ErrAIProxyUserGroupExists: "The user group name already exists."
ErrAIProxyBackendAccountExists: "This model account has already been imported into the AI Gateway account pool."
ErrAIProxyModelGroupInUse: "The model group is in use and cannot be deleted."
ErrAIProxyModelGroupExists: "The model group name already exists."
ErrAIProxySensitiveGroupInUse: "The sensitive word group is in use and cannot be deleted."
ErrAIProxySensitiveGroupExists: "The sensitive word group name already exists."
ErrLocalDelete: "Cannot delete the local node!"
ErrPortInUsed: "The {{ .name }} port is already in use!"
ErrInternalServerKey: "Internal server error:"
MasterNode: "Master Node"
# app # license
CustomAppStoreFileValid: "Application store package requires .tar.gz format"
ErrFileNotFound: "{{ .name }} file does not exist"
AppBackup: 'Application backup'
AppBackupPush: 'Transfer application backup file {{.file}} to node {{ .name }}'
ErrSourceTargetSame: 'Source node and target node cannot be the same!'
AppInstall: 'Install application {{ .name }} on node {{ .targetNode }}'
AppInstallCheck: 'Check application installation environment'
# backup
ErrBackupInUsed: "This backup account is used in scheduled tasks and cannot be deleted"
ErrBackupCheck: "Backup account connection test failed {{ .err }}"
ErrBackupLocal: "Local server backup account does not support this operation!"
ErrBackupPublic: "Detected that this backup account is not public, check and try again!"
ErrOSSConn: "Unable to get the latest version. Check server internet connectivity."
#license
LicenseCheck: 'Check if the license is available' LicenseCheck: 'Check if the license is available'
ErrLicenseInUsed: 'The license is already bound. Check and try again!' ErrLicenseInUsed: 'The license is already bound. Check and try again!'
ErrLicenseExpired: 'The license has expired. Check and try again!' ErrLicenseExpired: 'The license has expired. Check and try again!'
@@ -98,34 +89,74 @@ ErrNodeUnbind: "This node is not within the license binding range, check and ret
ErrNodeBind: "This node is already bound to a license, check and retry!" ErrNodeBind: "This node is already bound to a license, check and retry!"
ErrNodeLocalRollback: "The primary node does not support direct rollback. Run '1pctl restore' manually to roll back." ErrNodeLocalRollback: "The primary node does not support direct rollback. Run '1pctl restore' manually to roll back."
ErrIntlLicense: "The current version does not support importing international licenses yet. Stay tuned!" ErrIntlLicense: "The current version does not support importing international licenses yet. Stay tuned!"
InvalidRequestBodyType: "Invalid request body format. Ensure content matches the required format and retry."
InvalidLicenseCodeType: "Invalid license code format provided, check and try again!"
LicenseNotFoundType: "License not found, no matching record exists in the system for the provided license. Check and try again!"
LicenseRevokedType: "The requested license has been revoked and is no longer usable. Check and try again!"
LicenseExpiredType: "License expired. Renew it or re-import it in Panel Settings - License before retrying."
LicenseProductMismatchType: "The license does not match the requested product or service!"
InvalidAssigneeType: "Invalid target user or device information for license assignment. Check and try again!"
LicenseUsageNotFoundType: "No usage records found. This license has not been activated or used yet. Check and try again!"
LicenseUsageLimitExceededType: "This license is already bound to another node. Check and try again!"
# user # node and cluster
ErrNoSuchUser: "User information not found, check and try again!" MasterNode: "Master Node"
ErrToMaster: "This user does not have permission to perform this operation on the master node. Check and try again!" Node: "Node"
ErrToNode: "This user does not have permission to perform this operation on this node. Check and try again!" ErrLocalDelete: "Cannot delete the local node!"
ErrRBAC: "Insufficient user permissions. This operation cannot be performed. Check and try again!" ErrMasterDelete: "Unable to delete the master node. Delete slave nodes first."
ErrNoneNode: "This user has no node permissions. Contact an administrator or check and try again!" ClusterNameIsExist: "Cluster name already exists."
ErrOnlySuperAdmin: "Only super admins can use this feature!" AppStatusUnHealthy: "Failed to fetch application status. Check installation node status in the node list."
ErrRolePresetCannotDelete: "System preset roles cannot be deleted" MasterNodePortNotAvailable: "Node {{ .name }} port {{ .port }} connectivity check failed. Check firewall/security group settings and master node status."
ErrRolePresetCannotUpdate: "System preset roles cannot be updated" ClusterMasterNotExist: "Cluster master node is disconnected. Delete child nodes."
ErrRoleBoundToUser: "This role is already bound to users and cannot be deleted"
ErrRolePresetCannotBind: "System preset roles cannot be assigned to users"
ErrNodeAdminMasterForbidden: "Node Admin permissions cannot be added to the master node"
ErrSuperAdminCannotDelete: "Super admin users cannot be deleted"
InvalidRequestBodyType: "Invalid request body format. Ensure content matches the required format and retry." # virtual machine
InvalidLicenseCodeType: "Invalid license code format provided, check and try again!" ErrVMNotFound: "Virtual machine does not exist"
LicenseNotFoundType: "License not found, no matching record exists in the system for the provided license. Check and try again!" ErrVMAlreadyExists: "Virtual machine already exists"
LicenseRevokedType: "The requested license has been revoked and is no longer usable. Check and try again!" ErrVMStoragePathInUse: "Storage pool path is already used by [{{ .name }}]"
LicenseExpiredType: "License expired. Renew it or re-import it in Panel Settings - License before retrying." ErrVMRunning: "Virtual machine is running"
LicenseProductMismatchType: "The license does not match the requested product or service!" ErrVMLibvirtConnect: "Failed to connect to libvirt"
InvalidAssigneeType: "Invalid target user or device information for license assignment. Check and try again!" ErrVMPermission: "No permission to operate virtual machine: {{ .detail }}"
LicenseUsageNotFoundType: "No usage records found. This license has not been activated or used yet. Check and try again!" ErrVMNetworkNotFound: "Virtual machine network does not exist"
LicenseUsageLimitExceededType: "This license is already bound to another node. Check and try again!" ErrVMInvalidPath: "Invalid virtual machine path"
ErrVMInvalidInput: "Invalid virtual machine parameter"
ErrVMCommandFailed: "Virtual machine command failed: {{ .err }}"
VMSnapshotCreateTask: "Create snapshot [{{ .snapshot }}] for virtual machine [{{ .vm }}]"
VMSnapshotCreateStep: "Create virtual machine snapshot [{{ .snapshot }}]"
VMSnapshotRecoverTask: "Recover snapshot [{{ .snapshot }}] for virtual machine [{{ .vm }}]"
VMSnapshotRecoverStep: "Recover virtual machine snapshot [{{ .snapshot }}]"
VMSnapshotDeleteTask: "Delete snapshot [{{ .snapshot }}] for virtual machine [{{ .vm }}]"
VMSnapshotDeleteStep: "Delete virtual machine snapshot [{{ .snapshot }}]"
# app
CustomAppStoreFileValid: "Application store package requires .tar.gz format"
AppBackup: 'Application backup'
AppBackupPush: 'Transfer application backup file {{.file}} to node {{ .name }}'
ErrSourceTargetSame: 'Source node and target node cannot be the same!'
AppInstall: 'Install application {{ .name }} on node {{ .targetNode }}'
AppInstallCheck: 'Check application installation environment'
# backup
ErrBackupInUsed: "This backup account is used in scheduled tasks and cannot be deleted"
ErrBackupCheck: "Backup account connection test failed {{ .err }}"
ErrBackupLocal: "Local server backup account does not support this operation!"
ErrBackupPublic: "Detected that this backup account is not public, check and try again!"
ErrOSSConn: "Unable to get the latest version. Check server internet connectivity."
MvBackup: "Move data to backup directory"
# alert # alert
ErrAlertSync: "Alert information sync error, check and retry!" ErrAlertSync: "Alert information sync error, check and retry!"
# AI gateway
ErrAIProxyUserGroupIsDefault: "Default user group cannot be deleted."
ErrAIProxyUserGroupInUse: "The user group is in use and cannot be deleted."
ErrAIProxyUserGroupExists: "The user group name already exists."
ErrAIProxyBackendAccountExists: "This model account has already been imported into the AI Gateway account pool."
ErrAIProxyModelGroupInUse: "The model group is in use and cannot be deleted."
ErrAIProxyModelGroupExists: "The model group name already exists."
ErrAIProxySensitiveGroupInUse: "The sensitive word group is in use and cannot be deleted."
ErrAIProxySensitiveGroupExists: "The sensitive word group name already exists."
AIBenchmarkRun: "Run AI benchmark"
# task # task
TaskStart: "{{ .name }} task started [START]" TaskStart: "{{ .name }} task started [START]"
TaskEnd: "{{ .name }} task ended [COMPLETED]" TaskEnd: "{{ .name }} task ended [COMPLETED]"
@@ -140,6 +171,16 @@ TaskUpgrade: "Upgrade"
TaskSync: 'Sync' TaskSync: 'Sync'
TaskSyncForNode: "Sync node data" TaskSyncForNode: "Sync node data"
TaskBackup: "Backup" TaskBackup: "Backup"
TaskPush: "Push"
TaskRsync: "Sync"
SuccessStatus: "{{ .name }} succeeded"
FailedStatus: "{{ .name }} failed {{ .err }}"
Start: "Start"
SubTask: "Subtask"
Skip: "Ignore errors and continue"
Success: "Success"
# agent batch task
BatchInstallAgent: "Batch install agent" BatchInstallAgent: "Batch install agent"
DispatchAgentInstallTasks: "Dispatch agent install tasks" DispatchAgentInstallTasks: "Dispatch agent install tasks"
BatchUpgradeAgent: "Batch upgrade agent" BatchUpgradeAgent: "Batch upgrade agent"
@@ -173,21 +214,15 @@ AgentOperateStart: "Start"
AgentOperateStop: "Stop" AgentOperateStop: "Stop"
AgentOperateRestart: "Restart" AgentOperateRestart: "Restart"
AgentOperateDelete: "Delete" AgentOperateDelete: "Delete"
AIBenchmarkRun: "Run AI benchmark"
SuccessStatus: "{{ .name }} succeeded" # app and skill task
FailedStatus: "{{ .name }} failed {{ .err }}"
Start: "Start"
SubTask: "Subtask"
Skip: "Ignore errors and continue"
PushAppInstallTaskToNode: "Push app installation task to node [{{ .name }}]" PushAppInstallTaskToNode: "Push app installation task to node [{{ .name }}]"
TaskPush: "Push"
AppInstallTask: "App installation task" AppInstallTask: "App installation task"
PushAppFailed: "Failed to push app installation task" PushAppFailed: "Failed to push app installation task"
SkillHubInstallTask: "Install skill [{{ .name }}]" SkillHubInstallTask: "Install skill [{{ .name }}]"
SkillHubInstallToTarget: "Install skill to target [{{ .name }}]" SkillHubInstallToTarget: "Install skill to target [{{ .name }}]"
Success: "Success"
#script # script library
ScriptLibrary: "Script Library" ScriptLibrary: "Script Library"
RemoteScriptLibrary: "Remote Script Library" RemoteScriptLibrary: "Remote Script Library"
ScriptSyncSkip: "Script library is already up to date" ScriptSyncSkip: "Script library is already up to date"
@@ -195,7 +230,7 @@ DownloadData: "Downloading script library file data.yaml"
DownloadPackage: "Downloading script library package" DownloadPackage: "Downloading script library package"
AnalyticCompletion: "Analysis completed, now syncing to database..." AnalyticCompletion: "Analysis completed, now syncing to database..."
Node: "Node" # node sync
SyncNode: "Sync data to node {{ .name }}" SyncNode: "Sync data to node {{ .name }}"
LocalName: "'local' name is only used for system local identification" LocalName: "'local' name is only used for system local identification"
SyncPackageData: "Package sync data" SyncPackageData: "Package sync data"
@@ -211,7 +246,7 @@ SyncCustomApp: "Custom App"
SyncLanguage: "System Language" SyncLanguage: "System Language"
SyncEdition: "Region" SyncEdition: "Region"
#upgrade node # node upgrade
NodeUpgrade: "Upgrade node {{ .name }}" NodeUpgrade: "Upgrade node {{ .name }}"
UpgradeCheck: "Check for node updates" UpgradeCheck: "Check for node updates"
UpgradeCheckLocal: "Local nodes do not support batch upgrades, skipping..." UpgradeCheckLocal: "Local nodes do not support batch upgrades, skipping..."
@@ -224,12 +259,11 @@ LoadAutoUpgradeNodesFailed: "Load auto upgrade nodes failed, err: {{ .err }}"
AutoUpgradeNodes: "Auto upgrade nodes: {{ .nodes }}" AutoUpgradeNodes: "Auto upgrade nodes: {{ .nodes }}"
UpdateAutoUpgradeNodesStatusFailed: "Update status of auto upgrade nodes failed, err: {{ .err }}" UpdateAutoUpgradeNodesStatusFailed: "Update status of auto upgrade nodes failed, err: {{ .err }}"
#add node # node add
MasterData: "Master Node Data" MasterData: "Master Node Data"
LoadSftpClient: "Load SFTP Client" LoadSftpClient: "Load SFTP Client"
PackageMasterData: "Generate master node backup package" PackageMasterData: "Generate master node backup package"
UploadBackup: "Upload backup data" UploadBackup: "Upload backup data"
MvBackup: "Move data to backup directory"
TaskAddNode: "Add node" TaskAddNode: "Add node"
LoadNodeArch: "Get node architecture info" LoadNodeArch: "Get node architecture info"
LoadNodeArchDetail: "Detected master node architecture: {{ .local }}, child node architecture: {{ .node }}" LoadNodeArchDetail: "Detected master node architecture: {{ .local }}, child node architecture: {{ .node }}"
@@ -242,7 +276,35 @@ SendAgent: "Distribute node installation package"
StartService: "Start service" StartService: "Start service"
NoBackupNode: "Backup node is empty. Select one and save first" NoBackupNode: "Backup node is empty. Select one and save first"
#cmd # node file and image sync
LocalNodeIpFailed: "Failed to get master node IP. Edit the master node and add IP address and SSH authentication information."
HandlePrivateKey: "Handle node private key"
HandlePublicKey: "Handle node public key"
ExchangeFile: "Start syncing {{ .sourcePath }} from node {{ .source }} to node {{ .dest }}:{{ .destPath }}"
NodeFile: "Node file"
ImageSyncTaskName: "Image sync {{ .count }} images"
SSLSyncTaskName: "Certificate sync {{ .count }} certificates"
AppSyncTaskName: "App sync {{ .name }}"
SSLSyncToNode: "Push certificate [{{ .cert }}] to node [{{ .node }}]"
ImageSyncSave: "Save image {{ .image }}"
ImageSyncSaveTags: "Save image tags {{ .tags }}"
ImageSyncToNode: "Sync image {{ .image }} to node {{ .node }}"
ImageSyncLoad: "Load image {{ .image }} on node {{ .node }}"
ImageSyncClean: "Clean temporary files for image {{ .image }}"
ImageSyncNoTag: "Image {{ .image }} has no tag and will be saved by image ID"
ImageSyncFrontendTagsIgnored: "No tags were found for image {{ .image }} on the source node. Frontend tags were ignored."
ImageSyncHandlePrivateKey: "Handle image sync node private key"
ImageSyncHandlePublicKey: "Handle image sync node public key"
ImageSyncTransfer: "Start transferring image temporary file: {{ .source }}:{{ .sourcePath }} -> {{ .dest }}:{{ .destPath }}"
# command line
SudoHelper: "Use {{ .cmd }} or switch to root user"
UsernameNeed: "Enterprise edition must specify --username"
DBConnErr: "Error: Failed to initialize database connection, {{ .err }}"
SystemVersion: "version: "
SystemMode: "mode: "
# command line - app
AppVersion: "App version" AppVersion: "App version"
AppCommands: "App related commands" AppCommands: "App related commands"
AppInit: "Initialize app" AppInit: "Initialize app"
@@ -254,12 +316,14 @@ AppMissVersion: "App version missing, use -v to specify"
AppVersionExist: "Version already exists!" AppVersionExist: "Version already exists!"
AppCreateSuccessful: "Creation successful!" AppCreateSuccessful: "Creation successful!"
AppWriteErr: "File {{ .name }} write failed {{ .err }}" AppWriteErr: "File {{ .name }} write failed {{ .err }}"
SudoHelper: "Use {{ .cmd }} or switch to root user"
UsernameNeed: "Enterprise edition must specify --username" # command line - listen IP
ListenIPCommands: "Switch listening ip" ListenIPCommands: "Switch listening ip"
ListenIPv4: "Listen on IPv4" ListenIPv4: "Listen on IPv4"
ListenIPv6: "Listen on IPv6" ListenIPv6: "Listen on IPv6"
ListenChangeSuccessful: "Switch successful! Now listening on {{ .value }}" ListenChangeSuccessful: "Switch successful! Now listening on {{ .value }}"
# command line - reset
ResetCommands: "Reset system info" ResetCommands: "Reset system info"
ResetMFA: "Cancel 1Panel two-factor authentication" ResetMFA: "Cancel 1Panel two-factor authentication"
ResetHttps: "Cancel 1Panel https login" ResetHttps: "Cancel 1Panel https login"
@@ -267,12 +331,19 @@ ResetEntrance: "Cancel 1Panel secure entrance"
ResetIPs: "Cancel 1Panel authorized ip restrictions" ResetIPs: "Cancel 1Panel authorized ip restrictions"
ResetDomain: "Cancel 1Panel domain binding" ResetDomain: "Cancel 1Panel domain binding"
ResetPasskey: "Clear 1Panel passkeys" ResetPasskey: "Clear 1Panel passkeys"
# command line - user
UserList: "Get 1Panel user list" UserList: "Get 1Panel user list"
UserTableName: "Name" UserTableName: "Name"
UserTableMFAStatus: "MFA Status" UserTableMFAStatus: "MFA Status"
UserTableSuperAdmin: "Super Admin" UserTableSuperAdmin: "Super Admin"
UserTableCreatedAt: "Created At" UserTableCreatedAt: "Created At"
UserEmptyList: "No users found" UserEmptyList: "No users found"
UserInfo: "Get panel information"
UserInfoAddr: "Panel address: "
UserInfoPassHelp: "Tip: To change the password, you can execute the command: "
# command line - restore
RestoreCommands: "Roll back 1Panel service and data" RestoreCommands: "Roll back 1Panel service and data"
RestoreNoSuchFile: "No rollback files found" RestoreNoSuchFile: "No rollback files found"
RestoreStep1: "(1/5) Starting rollback of 1Panel service and data from {{ .name }} directory..." RestoreStep1: "(1/5) Starting rollback of 1Panel service and data from {{ .name }} directory..."
@@ -281,6 +352,8 @@ RestoreStep3: "(3/5) 1Panel script rollback completed"
RestoreStep4: "(4/5) 1Panel service rollback completed" RestoreStep4: "(4/5) 1Panel service rollback completed"
RestoreStep5: "(5/5) 1Panel data rollback completed" RestoreStep5: "(5/5) 1Panel data rollback completed"
RestoreSuccessful: "Rollback completed. Reverted to {{ .version }}. Restarting service..." RestoreSuccessful: "Rollback completed. Reverted to {{ .version }}. Restarting service..."
# command line - update
UpdateCommands: "Update panel info" UpdateCommands: "Update panel info"
UpdateUser: "Update user information" UpdateUser: "Update user information"
UpdatePassword: "Update user password" UpdatePassword: "Update user password"
@@ -307,28 +380,12 @@ UpdatePortResult: "Panel Port: {{ .name }}"
UpdatePortFirewallAdd: "Failed to add firewall port rule, {{ .err }}, manually add the {{ .name }} port to the firewall rules." UpdatePortFirewallAdd: "Failed to add firewall port rule, {{ .err }}, manually add the {{ .name }} port to the firewall rules."
UpdatePortFirewallDel: "Error: Failed to delete firewall port, {{ .err }}" UpdatePortFirewallDel: "Error: Failed to delete firewall port, {{ .err }}"
UpdatePortFirewallReload: "Failed to reload the firewall, {{ .err }}, manually reload the firewall." UpdatePortFirewallReload: "Failed to reload the firewall, {{ .err }}, manually reload the firewall."
UserInfo: "Get panel information"
UserInfoAddr: "Panel address: "
UserInfoPassHelp: "Tip: To change the password, you can execute the command: "
DBConnErr: "Error: Failed to initialize database connection, {{ .err }}"
SystemVersion: "version: "
SystemMode: "mode: "
#mobile app # mobile app
ErrVerifyToken: 'Token verification failed. Reset and scan again.' ErrVerifyToken: 'Token verification failed. Reset and scan again.'
ErrInvalidToken: 'Invalid token. Reset and scan again.' ErrInvalidToken: 'Invalid token. Reset and scan again.'
ErrExpiredToken: 'Token expired. Reset and scan again.' ErrExpiredToken: 'Token expired. Reset and scan again.'
#cluster # command export
ErrMasterDelete: "Unable to delete the master node. Delete slave nodes first."
ClusterNameIsExist: "Cluster name already exists."
AppStatusUnHealthy: "Failed to fetch application status. Check installation node status in the node list."
MasterNodePortNotAvailable: "Node {{ .name }} port {{ .port }} connectivity check failed. Check firewall/security group settings and master node status."
ClusterMasterNotExist: "Cluster master node is disconnected. Delete child nodes."
#ssl
ErrReqFailed: "{{.name}} request failed: {{ .err }}"
#command
Name: "Name" Name: "Name"
Command: "Command" Command: "Command"
+162 -99
View File
@@ -1,73 +1,65 @@
# errores básicos
ErrInvalidParams: 'Solicitud inválida: {{ .detail }}' ErrInvalidParams: 'Solicitud inválida: {{ .detail }}'
ErrTokenParse: 'Token inválido: {{ .detail }}' ErrTokenParse: 'Token inválido: {{ .detail }}'
ErrInitialPassword: 'Contraseña original incorrecta' ErrInitialPassword: 'Contraseña original incorrecta'
ErrInternalServer: 'Error interno: {{ .detail }}' ErrInternalServer: 'Error interno: {{ .detail }}'
ErrInternalServerKey: "Error interno del servidor:"
ErrRecordExist: 'Registro ya existe' ErrRecordExist: 'Registro ya existe'
ErrRecordNotFound: 'Registro no encontrado' ErrRecordNotFound: 'Registro no encontrado'
ErrStructTransform: 'Error de conversión: {{ .err }}' ErrStructTransform: 'Error de conversión: {{ .err }}'
ErrNotLogin: 'No has iniciado sesión: {{ .detail }}'
ErrSessionDataNotFound: "La sesión actual ha caducado"
ErrSessionDataFormat: "El formato de los datos de la sesión actual es anómalo"
ErrPasswordExpired: 'Contraseña expirada: {{ .detail }}'
ErrNotSupportType: 'Tipo no soportado: {{ .name }}' ErrNotSupportType: 'Tipo no soportado: {{ .name }}'
ErrProxy: 'Solicitud fallida: {{ .detail }}' ErrDemoEnvironment: 'No disponible en demo'
ErrApiConfigStatusInvalid: 'API desactivada: {{ .detail }}' ErrCmdTimeout: 'Comando agotó tiempo'
ErrApiConfigKeyInvalid: 'Clave API inválida: {{ .detail }}' ErrPortInUsed: "El puerto {{ .name }} ya está en uso"
ErrApiConfigIPInvalid: 'IP no permitida: {{ .detail }}' ErrFileNotFound: "El archivo {{ .name }} no existe"
ErrApiConfigDisable: 'API no permitida: {{ .detail }}' ErrReqFailed: "{{.name}} petición fallida: {{ .err }}"
ErrApiConfigKeyTimeInvalid: 'Timestamp inválido: {{ .detail }}'
ErrLoginLocked: "Demasiados intentos fallidos. El inicio de sesión se ha bloqueado temporalmente durante 5 minutos."
PushAppInstallTaskToNode: "Enviar tarea de instalación de aplicación al nodo [{{ .name }}]"
TaskPush: "Enviar"
AppInstallTask: "Tarea de instalación de aplicación"
PushAppFailed: "Error al enviar tarea de instalación de aplicación"
Success: "Éxito"
# request # solicitud y entrada de seguridad
ErrNoSuchHost: "No se pudo encontrar el servidor solicitado {{ .err }}" ErrNoSuchHost: "No se pudo encontrar el servidor solicitado {{ .err }}"
ErrHttpReqNotFound: "No se pudo encontrar el recurso solicitado {{ .err }}" ErrHttpReqNotFound: "No se pudo encontrar el recurso solicitado {{ .err }}"
ErrHttpReqFailed: "Solicitud fallida {{ .err }}" ErrHttpReqFailed: "Solicitud fallida {{ .err }}"
ErrHttpReqTimeOut: "La solicitud ha expirado {{ .err }}" ErrHttpReqTimeOut: "La solicitud ha expirado {{ .err }}"
ErrCreateHttpClient: "Error al crear la solicitud {{ .err }}" ErrCreateHttpClient: "Error al crear la solicitud {{ .err }}"
ErrProxy: 'Solicitud fallida: {{ .detail }}'
ErrProxySetting: "Información del servidor proxy no disponible {{ .err }}, compruebe e inténtelo de nuevo" ErrProxySetting: "Información del servidor proxy no disponible {{ .err }}, compruebe e inténtelo de nuevo"
ErrEntrance: "Error en la información de entrada de seguridad, por favor revise e intente de nuevo"
ErrEntranceFormat: "La entrada de seguridad {{ .name }} no está actualmente soportada. Por favor verifique e inténtelo de nuevo" ErrEntranceFormat: "La entrada de seguridad {{ .name }} no está actualmente soportada. Por favor verifique e inténtelo de nuevo"
# common # inicio de sesión y seguridad
ErrDemoEnvironment: 'No disponible en demo' ErrNotLogin: 'No has iniciado sesión: {{ .detail }}'
ErrCmdTimeout: 'Comando agotó tiempo' ErrSessionDataNotFound: "La sesión actual ha caducado"
ErrEntrance: "Error en la información de entrada de seguridad, por favor revise e intente de nuevo" ErrSessionDataFormat: "El formato de los datos de la sesión actual es anómalo"
ErrPasswordExpired: 'Contraseña expirada: {{ .detail }}'
ErrLoginLocked: "Demasiados intentos fallidos. El inicio de sesión se ha bloqueado temporalmente durante 5 minutos."
ErrApiConfigStatusInvalid: 'API desactivada: {{ .detail }}'
ErrApiConfigKeyInvalid: 'Clave API inválida: {{ .detail }}'
ErrApiConfigIPInvalid: 'IP no permitida: {{ .detail }}'
ErrApiConfigDisable: 'API no permitida: {{ .detail }}'
ErrApiConfigKeyTimeInvalid: 'Timestamp inválido: {{ .detail }}'
ErrPasskeyDisabled: "Passkey requiere que HTTPS esté habilitado"
ErrPasskeyNotConfigured: "No hay Passkey configurado"
ErrPasskeyLimit: "Límite de Passkey alcanzado (máximo 5)"
ErrPasskeySession: "La sesión de Passkey ha expirado o no es válida"
ErrPasskeyDuplicate: "Passkey ya existe"
ErrPasskeyVerify: "Error al verificar Passkey"
# usuario y permisos
ErrNoSuchUser: "No se encontró la información del usuario. Verifique e intente de nuevo."
ErrToMaster: "Este usuario no tiene permiso para realizar esta operación en el nodo principal. Verifique e intente de nuevo."
ErrToNode: "Este usuario no tiene permiso para realizar esta operación en este nodo. Verifique e intente de nuevo."
ErrRBAC: "Permisos de usuario insuficientes. No se puede realizar esta operación. Verifique e intente de nuevo."
ErrNoneNode: "Este usuario no tiene permisos sobre ningún nodo. Contacte al administrador o verifique e intente de nuevo."
ErrOnlySuperAdmin: "Solo los superadministradores pueden usar esta función."
ErrRolePresetCannotDelete: "No se pueden eliminar los roles predefinidos del sistema"
ErrRolePresetCannotUpdate: "No se pueden actualizar los roles predefinidos del sistema"
ErrRoleBoundToUser: "Este rol ya está vinculado a usuarios y no se puede eliminar"
ErrRolePresetCannotBind: "Los roles predefinidos del sistema no se pueden asignar a usuarios"
ErrNodeAdminMasterForbidden: "No se pueden agregar permisos de administrador de nodo al nodo principal"
ErrSuperAdminCannotDelete: "No se pueden eliminar usuarios superadministradores"
ErrGroupIsDefault: "Grupo predeterminado, no se puede eliminar" ErrGroupIsDefault: "Grupo predeterminado, no se puede eliminar"
ErrGroupIsInUse: "El grupo está en uso y no se puede eliminar." ErrGroupIsInUse: "El grupo está en uso y no se puede eliminar."
ErrAIProxyUserGroupIsDefault: "No se puede eliminar el grupo de usuarios predeterminado."
ErrAIProxyUserGroupInUse: "El grupo de usuarios está en uso y no se puede eliminar."
ErrAIProxyUserGroupExists: "El nombre del grupo de usuarios ya existe."
ErrAIProxyBackendAccountExists: "Esta cuenta de modelo ya se importó al grupo de cuentas de AI Gateway."
ErrAIProxyModelGroupInUse: "El grupo de modelos está en uso y no se puede eliminar."
ErrAIProxyModelGroupExists: "El nombre del grupo de modelos ya existe."
ErrAIProxySensitiveGroupInUse: "El grupo de palabras sensibles está en uso y no se puede eliminar."
ErrAIProxySensitiveGroupExists: "El nombre del grupo de palabras sensibles ya existe."
ErrLocalDelete: "No se puede eliminar el nodo local"
ErrPortInUsed: "El puerto {{ .name }} ya está en uso"
ErrInternalServerKey: "Error interno del servidor:"
MasterNode: "Nodo Maestro"
# app # licencia
CustomAppStoreFileValid: "El paquete de la tienda de aplicaciones debe tener formato .tar.gz"
ErrFileNotFound: "El archivo {{ .name }} no existe"
AppBackup: 'Copia de seguridad de aplicación'
AppBackupPush: 'Transferir archivo de copia de seguridad de aplicación {{.file}} al nodo {{ .name }}'
ErrSourceTargetSame: 'El nodo de origen y el nodo de destino no pueden ser el mismo'
AppInstall: 'Instalar aplicación {{ .name }} en nodo {{ .targetNode }}'
AppInstallCheck: 'Verificar entorno de instalación de aplicación'
# backup
ErrBackupInUsed: 'Cuenta de respaldo en uso por tarea programada'
ErrBackupCheck: 'Conexión de respaldo falló: {{ .err }}'
ErrBackupLocal: "La cuenta de respaldo del servidor local no admite esta operación"
ErrBackupPublic: "Se detectó que esta cuenta de respaldo no es pública, verifique e intente de nuevo"
ErrOSSConn: "No se pudo obtener la última versión, por favor revise la conectividad de red externa del servidor."
#license
LicenseCheck: 'Comprobar si la licencia está disponible' LicenseCheck: 'Comprobar si la licencia está disponible'
ErrLicenseInUsed: 'La licencia ya está vinculada. Verifique e intente de nuevo' ErrLicenseInUsed: 'La licencia ya está vinculada. Verifique e intente de nuevo'
ErrLicenseExpired: 'La licencia ha expirado. Verifique e intente de nuevo' ErrLicenseExpired: 'La licencia ha expirado. Verifique e intente de nuevo'
@@ -79,7 +71,6 @@ ErrLicenseSync: "Sincronización de licencia fallida, no se detectó informació
ErrLicenseExist: "Este registro de licencia ya existe. Puede ir directamente a la página de licencia para la vinculación del nodo." ErrLicenseExist: "Este registro de licencia ya existe. Puede ir directamente a la página de licencia para la vinculación del nodo."
ErrXpackNotFound: "Esta sección requiere la edición Business. Importa una licencia en Configuración del panel > Licencia." ErrXpackNotFound: "Esta sección requiere la edición Business. Importa una licencia en Configuración del panel > Licencia."
ErrXpackExceptional: "Esta sección requiere la edición Business. Sincroniza el estado de la licencia en Configuración del panel > Licencia." ErrXpackExceptional: "Esta sección requiere la edición Business. Sincroniza el estado de la licencia en Configuración del panel > Licencia."
ErrXpackOutOfDate: "La licencia actual ha expirado, importe nuevamente la licencia en Panel > Ajustes > Licencia"
ErrXpackLost: "La licencia alcanzó el límite de reintentos. Ve a Configuración del panel > Licencia y ejecuta una sincronización manual." ErrXpackLost: "La licencia alcanzó el límite de reintentos. Ve a Configuración del panel > Licencia y ejecuta una sincronización manual."
ErrEnterpriseLicenseRequired: "La licencia de la edición Enterprise no se ha importado. Importa primero una licencia." ErrEnterpriseLicenseRequired: "La licencia de la edición Enterprise no se ha importado. Importa primero una licencia."
ErrDeviceLost: "Faltan archivos necesarios para la verificación de licencia, verifique e intente de nuevo" ErrDeviceLost: "Faltan archivos necesarios para la verificación de licencia, verifique e intente de nuevo"
@@ -98,21 +89,6 @@ ErrNodeUnbind: "Este nodo no está dentro del rango de vinculación de la licenc
ErrNodeBind: "Este nodo ya está vinculado a una licencia, verifique e intente de nuevo" ErrNodeBind: "Este nodo ya está vinculado a una licencia, verifique e intente de nuevo"
ErrNodeLocalRollback: "El nodo principal no admite la reversión directa. Ejecuta manualmente '1pctl restore' para revertir." ErrNodeLocalRollback: "El nodo principal no admite la reversión directa. Ejecuta manualmente '1pctl restore' para revertir."
ErrIntlLicense: "La versión actual aún no admite importar licencias de la edición internacional. Próximamente" ErrIntlLicense: "La versión actual aún no admite importar licencias de la edición internacional. Próximamente"
# user
ErrNoSuchUser: "No se encontró la información del usuario. Verifique e intente de nuevo."
ErrToMaster: "Este usuario no tiene permiso para realizar esta operación en el nodo principal. Verifique e intente de nuevo."
ErrToNode: "Este usuario no tiene permiso para realizar esta operación en este nodo. Verifique e intente de nuevo."
ErrRBAC: "Permisos de usuario insuficientes. No se puede realizar esta operación. Verifique e intente de nuevo."
ErrNoneNode: "Este usuario no tiene permisos sobre ningún nodo. Contacte al administrador o verifique e intente de nuevo."
ErrOnlySuperAdmin: "Solo los superadministradores pueden usar esta función."
ErrRolePresetCannotDelete: "No se pueden eliminar los roles predefinidos del sistema"
ErrRolePresetCannotUpdate: "No se pueden actualizar los roles predefinidos del sistema"
ErrRoleBoundToUser: "Este rol ya está vinculado a usuarios y no se puede eliminar"
ErrRolePresetCannotBind: "Los roles predefinidos del sistema no se pueden asignar a usuarios"
ErrNodeAdminMasterForbidden: "No se pueden agregar permisos de administrador de nodo al nodo principal"
ErrSuperAdminCannotDelete: "No se pueden eliminar usuarios superadministradores"
InvalidRequestBodyType: "Formato del cuerpo de la solicitud no válido, por favor revisa y asegúrate de que el contenido cumpla con el formato requerido antes de reintentar." InvalidRequestBodyType: "Formato del cuerpo de la solicitud no válido, por favor revisa y asegúrate de que el contenido cumpla con el formato requerido antes de reintentar."
InvalidLicenseCodeType: "Formato de código de licencia no válido, por favor revisa e inténtalo de nuevo." InvalidLicenseCodeType: "Formato de código de licencia no válido, por favor revisa e inténtalo de nuevo."
LicenseNotFoundType: "Licencia no encontrada, no existe ningún registro coincidente en el sistema para la licencia proporcionada. Por favor revisa e inténtalo de nuevo." LicenseNotFoundType: "Licencia no encontrada, no existe ningún registro coincidente en el sistema para la licencia proporcionada. Por favor revisa e inténtalo de nuevo."
@@ -123,10 +99,65 @@ InvalidAssigneeType: "Información de usuario o dispositivo de destino no válid
LicenseUsageNotFoundType: "No se encontraron registros de uso. Esta licencia no ha sido activada o utilizada aún. Por favor revisa e inténtalo de nuevo." LicenseUsageNotFoundType: "No se encontraron registros de uso. Esta licencia no ha sido activada o utilizada aún. Por favor revisa e inténtalo de nuevo."
LicenseUsageLimitExceededType: "Esta licencia ya está vinculada a otro nodo. Por favor revisa e inténtalo de nuevo." LicenseUsageLimitExceededType: "Esta licencia ya está vinculada a otro nodo. Por favor revisa e inténtalo de nuevo."
# alert # nodo y clúster
MasterNode: "Nodo Maestro"
Node: "Nodo"
ErrLocalDelete: "No se puede eliminar el nodo local"
ErrMasterDelete: "No se puede eliminar el nodo principal, elimine primero los nodos secundarios."
ClusterNameIsExist: "El nombre del clúster ya existe."
AppStatusUnHealthy: "Adquisición anormal del estado de la aplicación, revise el estado del nodo en la lista de nodos."
MasterNodePortNotAvailable: "Verificación de conectividad del puerto {{ .port }} del nodo {{ .name }} fallida, verifique la configuración del firewall/grupo de seguridad y el estado del nodo principal."
ClusterMasterNotExist: "El nodo principal del clúster está desconectado, elimine los nodos secundarios."
# máquina virtual
ErrVMNotFound: "La máquina virtual no existe"
ErrVMAlreadyExists: "La máquina virtual ya existe"
ErrVMStoragePathInUse: "La ruta del pool de almacenamiento ya está usada por [{{ .name }}]"
ErrVMRunning: "La máquina virtual está en ejecución"
ErrVMLibvirtConnect: "Error al conectar con libvirt: {{ .detail }}"
ErrVMPermission: "Sin permiso para operar la máquina virtual: {{ .detail }}"
ErrVMNetworkNotFound: "La red de la máquina virtual no existe: {{ .detail }}"
ErrVMInvalidPath: "Ruta de máquina virtual no válida: {{ .detail }}"
ErrVMInvalidInput: "Parámetro de máquina virtual no válido: {{ .detail }}"
ErrVMCommandFailed: "Error al ejecutar el comando de la máquina virtual: {{ .err }}"
VMSnapshotCreateTask: "Create snapshot [{{ .snapshot }}] for virtual machine [{{ .vm }}]"
VMSnapshotCreateStep: "Create virtual machine snapshot [{{ .snapshot }}]"
VMSnapshotRecoverTask: "Recover snapshot [{{ .snapshot }}] for virtual machine [{{ .vm }}]"
VMSnapshotRecoverStep: "Recover virtual machine snapshot [{{ .snapshot }}]"
VMSnapshotDeleteTask: "Delete snapshot [{{ .snapshot }}] for virtual machine [{{ .vm }}]"
VMSnapshotDeleteStep: "Delete virtual machine snapshot [{{ .snapshot }}]"
# aplicación
CustomAppStoreFileValid: "El paquete de la tienda de aplicaciones debe tener formato .tar.gz"
AppBackup: 'Copia de seguridad de aplicación'
AppBackupPush: 'Transferir archivo de copia de seguridad de aplicación {{.file}} al nodo {{ .name }}'
ErrSourceTargetSame: 'El nodo de origen y el nodo de destino no pueden ser el mismo'
AppInstall: 'Instalar aplicación {{ .name }} en nodo {{ .targetNode }}'
AppInstallCheck: 'Verificar entorno de instalación de aplicación'
# copia de seguridad
ErrBackupInUsed: 'Cuenta de respaldo en uso por tarea programada'
ErrBackupCheck: 'Conexión de respaldo falló: {{ .err }}'
ErrBackupLocal: "La cuenta de respaldo del servidor local no admite esta operación"
ErrBackupPublic: "Se detectó que esta cuenta de respaldo no es pública, verifique e intente de nuevo"
ErrOSSConn: "No se pudo obtener la última versión, por favor revise la conectividad de red externa del servidor."
MvBackup: "Mover datos al directorio de respaldos"
# alerta
ErrAlertSync: "Error al sincronizar la información de alertas, verifique e intente de nuevo" ErrAlertSync: "Error al sincronizar la información de alertas, verifique e intente de nuevo"
# task # puerta de enlace de IA
ErrAIProxyUserGroupIsDefault: "No se puede eliminar el grupo de usuarios predeterminado."
ErrAIProxyUserGroupInUse: "El grupo de usuarios está en uso y no se puede eliminar."
ErrAIProxyUserGroupExists: "El nombre del grupo de usuarios ya existe."
ErrAIProxyBackendAccountExists: "Esta cuenta de modelo ya se importó al grupo de cuentas de AI Gateway."
ErrAIProxyModelGroupInUse: "El grupo de modelos está en uso y no se puede eliminar."
ErrAIProxyModelGroupExists: "El nombre del grupo de modelos ya existe."
ErrAIProxySensitiveGroupInUse: "El grupo de palabras sensibles está en uso y no se puede eliminar."
ErrAIProxySensitiveGroupExists: "El nombre del grupo de palabras sensibles ya existe."
AIBenchmarkRun: "Ejecutar prueba de referencia de IA"
# tarea
TaskStart: "Tarea {{ .name }} iniciada [INICIO]" TaskStart: "Tarea {{ .name }} iniciada [INICIO]"
TaskEnd: "Tarea {{ .name }} finalizada [COMPLETADA]" TaskEnd: "Tarea {{ .name }} finalizada [COMPLETADA]"
TaskFailed: "Tarea {{ .name }} fallida" TaskFailed: "Tarea {{ .name }} fallida"
@@ -140,6 +171,16 @@ TaskUpgrade: "Actualizar"
TaskSync: 'Sincronizar' TaskSync: 'Sincronizar'
TaskSyncForNode: "Sincronizar Datos del Nodo" TaskSyncForNode: "Sincronizar Datos del Nodo"
TaskBackup: "Respaldar" TaskBackup: "Respaldar"
TaskPush: "Enviar"
TaskRsync: "Sync"
SuccessStatus: "{{ .name }} correcta"
FailedStatus: "{{ .name }} fallida {{ .err }}"
Start: "Iniciar"
SubTask: "Subtarea"
Skip: "Omitir errores y continuar..."
Success: "Éxito"
# tarea por lotes de agentes
BatchInstallAgent: "Instalación masiva de agentes" BatchInstallAgent: "Instalación masiva de agentes"
DispatchAgentInstallTasks: "Enviar tareas de instalación de agentes" DispatchAgentInstallTasks: "Enviar tareas de instalación de agentes"
BatchUpgradeAgent: "Actualización masiva de agentes" BatchUpgradeAgent: "Actualización masiva de agentes"
@@ -173,15 +214,15 @@ AgentOperateStart: "Iniciar"
AgentOperateStop: "Detener" AgentOperateStop: "Detener"
AgentOperateRestart: "Reiniciar" AgentOperateRestart: "Reiniciar"
AgentOperateDelete: "Eliminar" AgentOperateDelete: "Eliminar"
SuccessStatus: "{{ .name }} correcta"
FailedStatus: "{{ .name }} fallida {{ .err }}" # tarea de aplicación y habilidad
Start: "Iniciar" PushAppInstallTaskToNode: "Enviar tarea de instalación de aplicación al nodo [{{ .name }}]"
SubTask: "Subtarea" AppInstallTask: "Tarea de instalación de aplicación"
Skip: "Omitir errores y continuar..." PushAppFailed: "Error al enviar tarea de instalación de aplicación"
SkillHubInstallTask: "Instalar skill [{{ .name }}]" SkillHubInstallTask: "Instalar skill [{{ .name }}]"
SkillHubInstallToTarget: "Instalar skill en destino [{{ .name }}]" SkillHubInstallToTarget: "Instalar skill en destino [{{ .name }}]"
#script # biblioteca de scripts
ScriptLibrary: "Biblioteca de scripts" ScriptLibrary: "Biblioteca de scripts"
RemoteScriptLibrary: "Biblioteca de Scripts Remota" RemoteScriptLibrary: "Biblioteca de Scripts Remota"
ScriptSyncSkip: "La biblioteca de scripts ya está en la última versión" ScriptSyncSkip: "La biblioteca de scripts ya está en la última versión"
@@ -189,7 +230,7 @@ DownloadData: "Descargando archivo de datos de la biblioteca de scripts data.yam
DownloadPackage: "Descargando paquete de la biblioteca de scripts" DownloadPackage: "Descargando paquete de la biblioteca de scripts"
AnalyticCompletion: "Análisis completado, sincronizando con la base de datos..." AnalyticCompletion: "Análisis completado, sincronizando con la base de datos..."
Node: "Nodo" # sincronización de nodos
SyncNode: "Sincronizar datos del nodo" SyncNode: "Sincronizar datos del nodo"
LocalName: "El nombre 'local' solo se utiliza para la identificación local del sistema" LocalName: "El nombre 'local' solo se utiliza para la identificación local del sistema"
SyncPackageData: "Sincronizar datos del paquete [{{ .detail }}]" SyncPackageData: "Sincronizar datos del paquete [{{ .detail }}]"
@@ -205,7 +246,7 @@ SyncCustomApp: "Aplicación personalizada"
SyncLanguage: "Idioma del sistema" SyncLanguage: "Idioma del sistema"
SyncEdition: "Región" SyncEdition: "Región"
#upgrade node # actualización de nodos
NodeUpgrade: "Actualizar nodo {{ .name }}" NodeUpgrade: "Actualizar nodo {{ .name }}"
UpgradeCheck: "Comprobar actualizaciones de nodos" UpgradeCheck: "Comprobar actualizaciones de nodos"
UpgradeCheckLocal: "Los nodos locales no admiten actualizaciones en lote, omitiendo..." UpgradeCheckLocal: "Los nodos locales no admiten actualizaciones en lote, omitiendo..."
@@ -218,12 +259,11 @@ LoadAutoUpgradeNodesFailed: "Error al cargar nodos de actualización automática
AutoUpgradeNodes: "Nodos de actualización automática: {{ .nodes }}" AutoUpgradeNodes: "Nodos de actualización automática: {{ .nodes }}"
UpdateAutoUpgradeNodesStatusFailed: "Error al actualizar el estado de los nodos de actualización automática, error: {{ .err }}" UpdateAutoUpgradeNodesStatusFailed: "Error al actualizar el estado de los nodos de actualización automática, error: {{ .err }}"
#add node # agregar nodo
MasterData: "Datos del nodo principal" MasterData: "Datos del nodo principal"
LoadSftpClient: "Cargar cliente SFTP" LoadSftpClient: "Cargar cliente SFTP"
PackageMasterData: "Generar paquete de respaldo del nodo principal" PackageMasterData: "Generar paquete de respaldo del nodo principal"
UploadBackup: "Subir datos de respaldo" UploadBackup: "Subir datos de respaldo"
MvBackup: "Mover datos al directorio de respaldos"
TaskAddNode: "Agregar nodo" TaskAddNode: "Agregar nodo"
LoadNodeArch: "Obtener información de arquitectura del nodo" LoadNodeArch: "Obtener información de arquitectura del nodo"
LoadNodeArchDetail: "Arquitectura detectada - principal: {{ .local }}, nodo secundario: {{ .node }}" LoadNodeArchDetail: "Arquitectura detectada - principal: {{ .local }}, nodo secundario: {{ .node }}"
@@ -236,7 +276,35 @@ SendAgent: "Distribuir paquete de instalación del nodo"
StartService: "Iniciar servicio" StartService: "Iniciar servicio"
NoBackupNode: "Actualmente no hay nodo de respaldo. Seleccione uno para guardar e intente de nuevo." NoBackupNode: "Actualmente no hay nodo de respaldo. Seleccione uno para guardar e intente de nuevo."
#cmd # sincronización de archivos e imágenes de nodo
LocalNodeIpFailed: "Failed to get master node IP. Edit the master node and add IP address and SSH authentication information."
HandlePrivateKey: "Handle node private key"
HandlePublicKey: "Handle node public key"
ExchangeFile: "Start syncing {{ .sourcePath }} from node {{ .source }} to node {{ .dest }}:{{ .destPath }}"
NodeFile: "Node file"
ImageSyncTaskName: "Image sync {{ .count }} images"
SSLSyncTaskName: "Certificate sync {{ .count }} certificates"
AppSyncTaskName: "App sync {{ .name }}"
SSLSyncToNode: "Push certificate [{{ .cert }}] to node [{{ .node }}]"
ImageSyncSave: "Save image {{ .image }}"
ImageSyncSaveTags: "Save image tags {{ .tags }}"
ImageSyncToNode: "Sync image {{ .image }} to node {{ .node }}"
ImageSyncLoad: "Load image {{ .image }} on node {{ .node }}"
ImageSyncClean: "Clean temporary files for image {{ .image }}"
ImageSyncNoTag: "Image {{ .image }} has no tag and will be saved by image ID"
ImageSyncFrontendTagsIgnored: "No tags were found for image {{ .image }} on the source node. Frontend tags were ignored."
ImageSyncHandlePrivateKey: "Handle image sync node private key"
ImageSyncHandlePublicKey: "Handle image sync node public key"
ImageSyncTransfer: "Start transferring image temporary file: {{ .source }}:{{ .sourcePath }} -> {{ .dest }}:{{ .destPath }}"
# línea de comandos
SudoHelper: "Por favor use {{ .cmd }} o cambie al usuario root"
UsernameNeed: "La edición Enterprise debe especificar --username"
DBConnErr: "Error: Fallo al inicializar la conexión a la base de datos, {{ .err }}"
SystemVersion: "versión: "
SystemMode: "modo: "
# línea de comandos - aplicación
AppVersion: "Versión de la aplicación" AppVersion: "Versión de la aplicación"
AppCommands: "Comandos relacionados con la app" AppCommands: "Comandos relacionados con la app"
AppInit: "Inicializar aplicación" AppInit: "Inicializar aplicación"
@@ -248,12 +316,14 @@ AppMissVersion: "Falta la versión de la app, use -v para especificar"
AppVersionExist: "La versión ya existe" AppVersionExist: "La versión ya existe"
AppCreateSuccessful: "Creación finalizada con éxito" AppCreateSuccessful: "Creación finalizada con éxito"
AppWriteErr: "Error al escribir el archivo {{ .name }} {{ .err }}" AppWriteErr: "Error al escribir el archivo {{ .name }} {{ .err }}"
SudoHelper: "Por favor use {{ .cmd }} o cambie al usuario root"
UsernameNeed: "La edición Enterprise debe especificar --username" # línea de comandos - IP de escucha
ListenIPCommands: "Cambiar ip de escucha" ListenIPCommands: "Cambiar ip de escucha"
ListenIPv4: "Escuchar en IPv4" ListenIPv4: "Escuchar en IPv4"
ListenIPv6: "Escuchar en IPv6" ListenIPv6: "Escuchar en IPv6"
ListenChangeSuccessful: "Cambio exitoso Ahora escuchando en {{ .value }}" ListenChangeSuccessful: "Cambio exitoso Ahora escuchando en {{ .value }}"
# línea de comandos - restablecer
ResetCommands: "Restablecer información del sistema" ResetCommands: "Restablecer información del sistema"
ResetMFA: "Cancelar autenticación de dos factores de 1Panel" ResetMFA: "Cancelar autenticación de dos factores de 1Panel"
ResetHttps: "Cancelar inicio de sesión https de 1Panel" ResetHttps: "Cancelar inicio de sesión https de 1Panel"
@@ -261,12 +331,19 @@ ResetEntrance: "Cancelar entrada segura de 1Panel"
ResetIPs: "Cancelar restricciones de IP autorizadas de 1Panel" ResetIPs: "Cancelar restricciones de IP autorizadas de 1Panel"
ResetDomain: "Cancelar vinculación de dominio de 1Panel" ResetDomain: "Cancelar vinculación de dominio de 1Panel"
ResetPasskey: "Eliminar passkeys de 1Panel" ResetPasskey: "Eliminar passkeys de 1Panel"
# línea de comandos - usuario
UserList: "Obtener la lista de usuarios de 1Panel" UserList: "Obtener la lista de usuarios de 1Panel"
UserTableName: "Nombre" UserTableName: "Nombre"
UserTableMFAStatus: "Estado MFA" UserTableMFAStatus: "Estado MFA"
UserTableSuperAdmin: "Superadministrador" UserTableSuperAdmin: "Superadministrador"
UserTableCreatedAt: "Creado en" UserTableCreatedAt: "Creado en"
UserEmptyList: "No se encontraron usuarios" UserEmptyList: "No se encontraron usuarios"
UserInfo: "Obtener información del panel"
UserInfoAddr: "Dirección del panel: "
UserInfoPassHelp: "Consejo: para cambiar la contraseña, ejecute el comando: "
# línea de comandos - restaurar
RestoreCommands: "Revertir el servicio y los datos de 1Panel" RestoreCommands: "Revertir el servicio y los datos de 1Panel"
RestoreNoSuchFile: "No se encontraron archivos de reversión" RestoreNoSuchFile: "No se encontraron archivos de reversión"
RestoreStep1: "(1/5) Iniciando la reversión del servicio y los datos de 1Panel desde el directorio {{ .name }}..." RestoreStep1: "(1/5) Iniciando la reversión del servicio y los datos de 1Panel desde el directorio {{ .name }}..."
@@ -275,6 +352,8 @@ RestoreStep3: "(3/5) Reversión del script de 1Panel completada"
RestoreStep4: "(4/5) Reversión del servicio de 1Panel completada" RestoreStep4: "(4/5) Reversión del servicio de 1Panel completada"
RestoreStep5: "(5/5) Reversión de los datos de 1Panel completada" RestoreStep5: "(5/5) Reversión de los datos de 1Panel completada"
RestoreSuccessful: "Reversión completada. Se volvió a {{ .version }}. Reiniciando el servicio..." RestoreSuccessful: "Reversión completada. Se volvió a {{ .version }}. Reiniciando el servicio..."
# línea de comandos - actualizar
UpdateCommands: "Actualizar información del panel" UpdateCommands: "Actualizar información del panel"
UpdateUser: "Actualizar información del usuario" UpdateUser: "Actualizar información del usuario"
UpdatePassword: "Actualizar contraseña del usuario" UpdatePassword: "Actualizar contraseña del usuario"
@@ -301,28 +380,12 @@ UpdatePortResult: "Puerto del panel: {{ .name }}"
UpdatePortFirewallAdd: "Fallo al agregar la regla de puerto al firewall, {{ .err }}, agregue manualmente el puerto {{ .name }} al firewall." UpdatePortFirewallAdd: "Fallo al agregar la regla de puerto al firewall, {{ .err }}, agregue manualmente el puerto {{ .name }} al firewall."
UpdatePortFirewallDel: "Error: Fallo al eliminar el puerto del firewall, {{ .err }}" UpdatePortFirewallDel: "Error: Fallo al eliminar el puerto del firewall, {{ .err }}"
UpdatePortFirewallReload: "Fallo al recargar el firewall, {{ .err }}, recargue el firewall manualmente." UpdatePortFirewallReload: "Fallo al recargar el firewall, {{ .err }}, recargue el firewall manualmente."
UserInfo: "Obtener información del panel"
UserInfoAddr: "Dirección del panel: "
UserInfoPassHelp: "Consejo: para cambiar la contraseña, ejecute el comando: "
DBConnErr: "Error: Fallo al inicializar la conexión a la base de datos, {{ .err }}"
SystemVersion: "versión: "
SystemMode: "modo: "
#mobile app # aplicación móvil
ErrVerifyToken: 'Error al verificar el token, por favor restablezca y escanee de nuevo.' ErrVerifyToken: 'Error al verificar el token, por favor restablezca y escanee de nuevo.'
ErrInvalidToken: 'Token inválido, por favor restablezca y escanee de nuevo.' ErrInvalidToken: 'Token inválido, por favor restablezca y escanee de nuevo.'
ErrExpiredToken: 'El token ha expirado, por favor restablezca y escanee de nuevo.' ErrExpiredToken: 'El token ha expirado, por favor restablezca y escanee de nuevo.'
#cluster # exportación de comandos
ErrMasterDelete: "No se puede eliminar el nodo principal, elimine primero los nodos secundarios."
ClusterNameIsExist: "El nombre del clúster ya existe."
AppStatusUnHealthy: "Adquisición anormal del estado de la aplicación, revise el estado del nodo en la lista de nodos."
MasterNodePortNotAvailable: "Verificación de conectividad del puerto {{ .port }} del nodo {{ .name }} fallida, verifique la configuración del firewall/grupo de seguridad y el estado del nodo principal."
ClusterMasterNotExist: "El nodo principal del clúster está desconectado, elimine los nodos secundarios."
#ssl
ErrReqFailed: "{{.name}} petición fallida: {{ .err }}"
#command
Name: "Nombre" Name: "Nombre"
Command: "Comando" Command: "Comando"
+391
View File
@@ -0,0 +1,391 @@
# خطاهای پایه
ErrInvalidParams: "پارامترهای درخواست نامعتبر: {{ .detail }}"
ErrTokenParse: "خطا در تولید توکن: {{ .detail }}"
ErrInitialPassword: "رمز عبور اولیه اشتباه است"
ErrInternalServer: "خطای داخلی سرور: {{ .detail }}"
ErrInternalServerKey: "خطای داخلی سرور:"
ErrRecordExist: "رکورد از قبل وجود دارد"
ErrRecordNotFound: "رکورد یافت نشد"
ErrStructTransform: "تبدیل نوع ناموفق بود: {{ .detail }}"
ErrNotSupportType: "نوع پشتیبانی نمی‌شود: {{ .name }}"
ErrDemoEnvironment: "سرور آزمایشی، این عملیات ممنوع است!"
ErrCmdTimeout: "زمان اجرای دستور به پایان رسید!"
ErrPortInUsed: "پورت {{ .name }} قبلاً در حال استفاده است!"
ErrFileNotFound: "فایل {{ .name }} وجود ندارد"
ErrReqFailed: "درخواست {{.name}} ناموفق بود: {{ .err }}"
# درخواست و ورودی امنیتی
ErrNoSuchHost: "تفکیک میزبان ناموفق بود: {{ .err }}"
ErrHttpReqNotFound: "منبع درخواستی یافت نشد: {{ .err }}"
ErrHttpReqFailed: "درخواست ناموفق بود {{ .err }}"
ErrHttpReqTimeOut: "زمان درخواست به پایان رسید {{ .err }}"
ErrCreateHttpClient: "ایجاد درخواست ناموفق بود {{ .err }}"
ErrProxy: "درخواست ناموفق بود؛ وضعیت این گره را بررسی کنید: {{ .detail }}"
ErrProxySetting: "اطلاعات سرور پروکسی در دسترس نیست {{ .err }}، بررسی و دوباره تلاش کنید!"
ErrEntrance: "خطا در اطلاعات ورودی امنیتی، بررسی و دوباره تلاش کنید!"
ErrEntranceFormat: "ورودی امنیتی {{ .name }} پشتیبانی نمی‌شود. بررسی و دوباره تلاش کنید."
# ورود و امنیت
ErrNotLogin: "کاربر وارد نشده است: {{ .detail }}"
ErrSessionDataNotFound: "جلسه منقضی شده است"
ErrSessionDataFormat: "فرمت داده جلسه نامعتبر است"
ErrPasswordExpired: "رمز عبور منقضی شده است: {{ .detail }}"
ErrLoginLocked: "تعداد تلاش‌های ناموفق زیاد است. ورود به مدت ۵ دقیقه به طور موقت قفل شده است."
ErrApiConfigStatusInvalid: "دسترسی API غیرفعال است: {{ .detail }}"
ErrApiConfigKeyInvalid: "کلید API نامعتبر است: {{ .detail }}"
ErrApiConfigIPInvalid: "IP درخواست API در لیست سفید نیست: {{ .detail }}"
ErrApiConfigDisable: "این رابط فراخوانی API را ممنوع می‌کند: {{ .detail }}"
ErrApiConfigKeyTimeInvalid: "مهر زمانی API نامعتبر است: {{ .detail }}"
ErrPasskeyDisabled: "کلید عبور نیاز به فعال بودن HTTPS دارد"
ErrPasskeyNotConfigured: "هیچ کلید عبوری پیکربندی نشده است"
ErrPasskeyLimit: "محدودیت کلید عبور رسیده است (حداکثر ۵)"
ErrPasskeySession: "جلسه کلید عبور منقضی یا نامعتبر است"
ErrPasskeyDuplicate: "کلید عبور از قبل وجود دارد"
ErrPasskeyVerify: "تأیید کلید عبور ناموفق بود"
# کاربر و مجوزها
ErrNoSuchUser: "اطلاعات کاربر یافت نشد، بررسی و دوباره تلاش کنید!"
ErrToMaster: "این کاربر مجوز انجام این عملیات روی گره اصلی را ندارد. بررسی و دوباره تلاش کنید!"
ErrToNode: "این کاربر مجوز انجام این عملیات روی این گره را ندارد. بررسی و دوباره تلاش کنید!"
ErrRBAC: "مجوزهای کاربر ناکافی است. این عملیات قابل انجام نیست. بررسی و دوباره تلاش کنید!"
ErrNoneNode: "این کاربر هیچ مجوز گره‌ای ندارد. با مدیر تماس بگیرید یا بررسی و دوباره تلاش کنید!"
ErrOnlySuperAdmin: "فقط مدیران کل می‌توانند از این ویژگی استفاده کنند!"
ErrRolePresetCannotDelete: "نقش‌های از پیش تعیین شده سیستم قابل حذف نیستند"
ErrRolePresetCannotUpdate: "نقش‌های از پیش تعیین شده سیستم قابل به‌روزرسانی نیستند"
ErrRoleBoundToUser: "این نقش قبلاً به کاربران متصل است و قابل حذف نیست"
ErrRolePresetCannotBind: "نقش‌های از پیش تعیین شده سیستم قابل انتساب به کاربران نیستند"
ErrNodeAdminMasterForbidden: "مجوزهای مدیر گره نمی‌توانند به گره اصلی اضافه شوند"
ErrSuperAdminCannotDelete: "کاربران مدیر کل قابل حذف نیستند"
ErrGroupIsDefault: "گروه پیش‌فرض، قابل حذف نیست"
ErrGroupIsInUse: "گروه در حال استفاده است و قابل حذف نیست."
# مجوز
LicenseCheck: 'بررسی در دسترس بودن مجوز'
ErrLicenseInUsed: 'مجوز قبلاً متصل شده است. بررسی و دوباره تلاش کنید!'
ErrLicenseExpired: 'مجوز منقضی شده است. بررسی و دوباره تلاش کنید!'
ErrLicense: "خطا در فرمت مجوز، بررسی و دوباره تلاش کنید!"
ErrLicenseCheck: "تأیید مجوز ناموفق بود، بررسی و دوباره تلاش کنید!"
ErrXpackVersion: "تأیید مجوز ناموفق بود، این مجوز محدودیت نسخه دارد، قابل واردات نیست، بررسی و دوباره تلاش کنید!"
ErrLicenseSave: "ذخیره اطلاعات مجوز ناموفق بود، خطا {{ .err }}، دوباره تلاش کنید!"
ErrLicenseSync: "همگام‌سازی مجوز ناموفق بود، هیچ اطلاعات مجوزی در پایگاه داده شناسایی نشد!"
ErrLicenseExist: "این رکورد مجوز از قبل وجود دارد. می‌توانید مستقیماً به صفحه مجوز برای اتصال گره بروید."
ErrXpackNotFound: "این بخش نیاز به نسخه تجاری دارد. در تنظیمات پنل > مجوز یک مجوز وارد کنید."
ErrXpackExceptional: "این بخش نیاز به نسخه تجاری دارد. وضعیت مجوز را در تنظیمات پنل > مجوز همگام‌سازی کنید."
ErrXpackLost: "محدودیت تلاش مجدد مجوز رسیده است. به تنظیمات پنل > مجوز بروید و همگام‌سازی دستی را اجرا کنید."
ErrEnterpriseLicenseRequired: "مجوز نسخه سازمانی وارد نشده است. ابتدا یک مجوز وارد کنید."
ErrDeviceLost: "فایل‌های مورد نیاز برای تأیید مجوز وجود ندارند، بررسی و دوباره تلاش کنید!"
ErrDeviceErr: "محیط فعلی با محیط واردات مجوز مطابقت ندارد. مجوز را ویرایش کرده و دوباره وارد کنید."
ErrXpackTimeout: "زمان درخواست به پایان رسید، ممکن است اتصال شبکه ناپایدار باشد، بعداً دوباره تلاش کنید!"
ErrUnbindMaster: "گره‌هایی در مدیریت گره وجود دارند. ابتدا گره‌ها را حذف کنید، سپس مجوز فعلی را قطع اتصال کنید."
ErrFreeNodeLimit: "تعداد گره‌های قابل افزودن به حد مجاز رسیده است. خرید کرده و دوباره تلاش کنید."
ErrNodeBound: "این مجوز به گره دیگری متصل است، بررسی و دوباره تلاش کنید!"
ErrNodeBoundDelete: "این مجوز متصل است و از عملیات حذف پشتیبانی نمی‌کند. بررسی و دوباره تلاش کنید!"
ErrNodeBoundLimit: "گره رایگان فعلی به حد مجاز رسیده است، بررسی و دوباره تلاش کنید!"
ErrLicenseFree: "گره‌های رایگان فقط زمانی در دسترس هستند که مجوز به درستی به یک گره متصل باشد. تأیید کرده و دوباره تلاش کنید."
ErrLicenseUnbind: "گره‌های نسخه انجمن هنوز به این مجوز متصل هستند. آنها را در تنظیمات پنل > مجوز قطع اتصال کرده و دوباره تلاش کنید."
ErrLicenseBindCount: "تعداد گره‌های رایگان مجوز جدید کمتر از تعداد گره‌های نسخه انجمن متصل فعلی است. بررسی و دوباره تلاش کنید."
ErrNoSuchNode: "اطلاعات گره یافت نشد، بررسی و دوباره تلاش کنید!"
ErrNodeUnbind: "این گره در محدوده اتصال مجوز نیست، بررسی و دوباره تلاش کنید!"
ErrNodeBind: "این گره قبلاً به یک مجوز متصل است، بررسی و دوباره تلاش کنید!"
ErrNodeLocalRollback: "گره اصلی از بازگشت مستقیم پشتیبانی نمی‌کند. برای بازگشت به صورت دستی '1pctl restore' را اجرا کنید."
ErrIntlLicense: "نسخه فعلی از واردات مجوزهای بین‌المللی پشتیبانی نمی‌کند. منتظر به‌روزرسانی‌های بعدی باشید!"
InvalidRequestBodyType: "فرمت بدنه درخواست نامعتبر است. اطمینان حاصل کنید که محتوا با فرمت مورد نیاز مطابقت دارد و دوباره تلاش کنید."
InvalidLicenseCodeType: "فرمت کد مجوز ارائه شده نامعتبر است، بررسی و دوباره تلاش کنید!"
LicenseNotFoundType: "مجوز یافت نشد، هیچ رکورد منطبقی در سیستم برای مجوز ارائه شده وجود ندارد. بررسی و دوباره تلاش کنید!"
LicenseRevokedType: "مجوز درخواستی باطل شده است و دیگر قابل استفاده نیست. بررسی و دوباره تلاش کنید!"
LicenseExpiredType: "مجوز منقضی شده است. آن را تمدید کنید یا دوباره در تنظیمات پنل - مجوز وارد کنید و سپس دوباره تلاش کنید."
LicenseProductMismatchType: "مجوز با محصول یا سرویس درخواستی مطابقت ندارد!"
InvalidAssigneeType: "اطلاعات کاربر یا دستگاه هدف برای انتساب مجوز نامعتبر است. بررسی و دوباره تلاش کنید!"
LicenseUsageNotFoundType: "هیچ رکورد استفاده‌ای یافت نشد. این مجوز هنوز فعال یا استفاده نشده است. بررسی و دوباره تلاش کنید!"
LicenseUsageLimitExceededType: "این مجوز قبلاً به گره دیگری متصل است. بررسی و دوباره تلاش کنید!"
# گره و خوشه
MasterNode: "گره اصلی"
Node: "گره"
ErrLocalDelete: "گره محلی قابل حذف نیست!"
ErrMasterDelete: "گره اصلی قابل حذف نیست. ابتدا گره‌های برده را حذف کنید."
ClusterNameIsExist: "نام خوشه از قبل وجود دارد."
AppStatusUnHealthy: "دریافت وضعیت برنامه ناموفق بود. وضعیت گره نصب را در لیست گره‌ها بررسی کنید."
MasterNodePortNotAvailable: "بررسی اتصال پورت {{ .port }} گره {{ .name }} ناموفق بود. تنظیمات دیواره آتش/گروه امنیتی و وضعیت گره اصلی را بررسی کنید."
ClusterMasterNotExist: "گره اصلی خوشه قطع شده است. گره‌های زیرین را حذف کنید."
# ماشین مجازی
ErrVMNotFound: "ماشین مجازی وجود ندارد"
ErrVMAlreadyExists: "ماشین مجازی از قبل وجود دارد"
ErrVMStoragePathInUse: "مسیر استخر ذخیره‌سازی قبلاً توسط [{{ .name }}] استفاده شده است"
ErrVMRunning: "ماشین مجازی در حال اجرا است"
ErrVMLibvirtConnect: "اتصال به libvirt ناموفق بود: {{ .detail }}"
ErrVMPermission: "مجوز عملیات ماشین مجازی وجود ندارد: {{ .detail }}"
ErrVMNetworkNotFound: "شبکه ماشین مجازی وجود ندارد: {{ .detail }}"
ErrVMInvalidPath: "مسیر ماشین مجازی نامعتبر است: {{ .detail }}"
ErrVMInvalidInput: "پارامتر ماشین مجازی نامعتبر است: {{ .detail }}"
ErrVMCommandFailed: "اجرای دستور ماشین مجازی ناموفق بود: {{ .err }}"
VMSnapshotCreateTask: "ایجاد اسنپ‌شات [{{ .snapshot }}] برای ماشین مجازی [{{ .vm }}]"
VMSnapshotCreateStep: "ایجاد اسنپ‌شات ماشین مجازی [{{ .snapshot }}]"
VMSnapshotRecoverTask: "بازیابی اسنپ‌شات [{{ .snapshot }}] برای ماشین مجازی [{{ .vm }}]"
VMSnapshotRecoverStep: "بازیابی اسنپ‌شات ماشین مجازی [{{ .snapshot }}]"
VMSnapshotDeleteTask: "حذف اسنپ‌شات [{{ .snapshot }}] برای ماشین مجازی [{{ .vm }}]"
VMSnapshotDeleteStep: "حذف اسنپ‌شات ماشین مجازی [{{ .snapshot }}]"
# برنامه
CustomAppStoreFileValid: "بسته فروشگاه برنامه باید با فرمت .tar.gz باشد"
AppBackup: 'پشتیبان‌گیری از برنامه'
AppBackupPush: 'انتقال فایل پشتیبان برنامه {{.file}} به گره {{ .name }}'
ErrSourceTargetSame: 'گره منبع و گره هدف نمی‌توانند یکسان باشند!'
AppInstall: 'نصب برنامه {{ .name }} روی گره {{ .targetNode }}'
AppInstallCheck: 'بررسی محیط نصب برنامه'
# پشتیبان‌گیری
ErrBackupInUsed: "این حساب پشتیبان در وظایف زمان‌بندی استفاده می‌شود و قابل حذف نیست"
ErrBackupCheck: "تست اتصال حساب پشتیبان ناموفق بود {{ .err }}"
ErrBackupLocal: "حساب پشتیبان سرور محلی از این عملیات پشتیبانی نمی‌کند!"
ErrBackupPublic: "تشخیص داده شد که این حساب پشتیبان عمومی نیست، بررسی و دوباره تلاش کنید!"
ErrOSSConn: "امکان دریافت آخرین نسخه وجود ندارد. اتصال اینترنت سرور را بررسی کنید."
MvBackup: "انتقال داده‌ها به دایرکتوری پشتیبان"
# هشدار
ErrAlertSync: "خطا در همگام‌سازی اطلاعات هشدار، بررسی و دوباره تلاش کنید!"
# دروازه هوش مصنوعی
ErrAIProxyUserGroupIsDefault: "گروه کاربری پیش‌فرض قابل حذف نیست."
ErrAIProxyUserGroupInUse: "گروه کاربری در حال استفاده است و قابل حذف نیست."
ErrAIProxyUserGroupExists: "نام گروه کاربری از قبل وجود دارد."
ErrAIProxyBackendAccountExists: "این حساب مدل قبلاً به مجموعه حساب‌های دروازه AI وارد شده است."
ErrAIProxyModelGroupInUse: "گروه مدل در حال استفاده است و قابل حذف نیست."
ErrAIProxyModelGroupExists: "نام گروه مدل از قبل وجود دارد."
ErrAIProxySensitiveGroupInUse: "گروه کلمات حساس در حال استفاده است و قابل حذف نیست."
ErrAIProxySensitiveGroupExists: "نام گروه کلمات حساس از قبل وجود دارد."
AIBenchmarkRun: "اجرای معیار سنجش هوش مصنوعی"
# وظیفه
TaskStart: "وظیفه {{ .name }} شروع شد [شروع]"
TaskEnd: "وظیفه {{ .name }} پایان یافت [تکمیل شد]"
TaskFailed: "وظیفه {{ .name }} ناموفق بود"
TaskTimeout: "زمان وظیفه {{ .name }} به پایان رسید"
TaskSuccess: "وظیفه {{ .name }} با موفقیت انجام شد"
TaskRetry: "تلاش مجدد {{ .name }}"
SubTaskSuccess: "{{ .name }} با موفقیت انجام شد"
SubTaskFailed: "{{ .name }} ناموفق بود: {{ .err }}"
TaskInstall: "نصب"
TaskUpgrade: "ارتقاء"
TaskSync: 'همگام‌سازی'
TaskSyncForNode: "همگام‌سازی داده‌های گره"
TaskBackup: "پشتیبان‌گیری"
TaskPush: "ارسال"
TaskRsync: "همگام‌سازی"
SuccessStatus: "{{ .name }} با موفقیت انجام شد"
FailedStatus: "{{ .name }} ناموفق بود {{ .err }}"
Start: "شروع"
SubTask: "وظیفه فرعی"
Skip: "نادیده گرفتن خطاها و ادامه"
Success: "موفق"
# وظیفه دسته‌ای عامل
BatchInstallAgent: "نصب دسته‌ای عامل"
DispatchAgentInstallTasks: "ارسال وظایف نصب عامل"
BatchUpgradeAgent: "ارتقاء دسته‌ای عامل"
DispatchAgentUpgradeTasks: "ارسال وظایف ارتقاء عامل"
BatchAgentInstallDispatchFailed: "گره {{ .node }} در ارسال وظیفه نصب {{ .agentType }} ناموفق بود پیام: {{ .err }}"
BatchAgentInstallSubmitted: "گره {{ .node }} وظیفه نصب {{ .agentType }} را با موفقیت ارسال کرد!"
BatchAgentUpgradeDispatchFailed: "گره {{ .node }} در ارسال وظیفه ارتقاء {{ .agentType }} ناموفق بود پیام: {{ .err }}"
BatchAgentUpgradeAlreadyLatest: "گره {{ .node }} {{ .agent }} از قبل در نسخه هدف است، رد شد"
BatchAgentUpgradeSubmitted: "گره {{ .node }} وظیفه ارتقاء {{ .agent }} را با موفقیت ارسال کرد!"
BatchAgentUpgradeFailed: "گره {{ .node }} در ارسال وظیفه ارتقاء {{ .agent }} ناموفق بود پیام: {{ .err }}"
BatchInstallAgentSkill: "توزیع دسته‌ای مهارت"
DispatchAgentSkillInstallTasks: "ارسال وظایف نصب مهارت"
BatchAgentSkillDispatchFailed: "گره {{ .node }} در ارسال {{ .skill }} به {{ .target }} ناموفق بود پیام: {{ .err }}"
BatchAgentNoAgentsFound: "گره {{ .node }} هیچ عامل {{ .agentType }} پیدا نکرد، رد شد"
BatchAgentSkillSkipped: "گره {{ .node }} {{ .agent }} رد شد پیام: {{ .msg }}"
BatchAgentSkillInstallSubmitted: "گره {{ .node }} وظیفه نصب {{ .skill }} را به {{ .agent }} با موفقیت ارسال کرد!"
BatchAgentSkillInstallFailed: "گره {{ .node }} در ارسال وظیفه نصب {{ .skill }} به {{ .agent }} ناموفق بود پیام: {{ .err }}"
BatchAgentOperateDispatchFailed: "گره {{ .node }} در ارسال وظیفه {{ .operate }} {{ .agentType }} ناموفق بود پیام: {{ .err }}"
BatchAgentOperateSkipped: "گره {{ .node }} {{ .agent }} رد شد پیام: {{ .msg }}"
BatchAgentOperateSubmitted: "گره {{ .node }} وظیفه {{ .operate }} {{ .agent }} را با موفقیت ارسال کرد!"
BatchAgentOperateFailed: "گره {{ .node }} در ارسال وظیفه {{ .operate }} {{ .agent }} ناموفق بود پیام: {{ .err }}"
BatchStartAgent: "شروع دسته‌ای عامل"
DispatchAgentStartTasks: "ارسال وظایف شروع عامل"
BatchStopAgent: "توقف دسته‌ای عامل"
DispatchAgentStopTasks: "ارسال وظایف توقف عامل"
BatchRestartAgent: "راه‌اندازی مجدد دسته‌ای عامل"
DispatchAgentRestartTasks: "ارسال وظایف راه‌اندازی مجدد عامل"
BatchDeleteAgent: "حذف دسته‌ای عامل"
DispatchAgentDeleteTasks: "ارسال وظایف حذف عامل"
AgentOperateStart: "شروع"
AgentOperateStop: "توقف"
AgentOperateRestart: "راه‌اندازی مجدد"
AgentOperateDelete: "حذف"
# وظیفه برنامه و مهارت
PushAppInstallTaskToNode: "ارسال وظیفه نصب برنامه به گره [{{ .name }}]"
AppInstallTask: "وظیفه نصب برنامه"
PushAppFailed: "ارسال وظیفه نصب برنامه ناموفق بود"
SkillHubInstallTask: "نصب مهارت [{{ .name }}]"
SkillHubInstallToTarget: "نصب مهارت به هدف [{{ .name }}]"
# کتابخانه اسکریپت
ScriptLibrary: "کتابخانه اسکریپت"
RemoteScriptLibrary: "کتابخانه اسکریپت از راه دور"
ScriptSyncSkip: "کتابخانه اسکریپت از قبل به‌روز است"
DownloadData: "دانلود فایل داده‌های کتابخانه اسکریپت data.yaml"
DownloadPackage: "دانلود بسته کتابخانه اسکریپت"
AnalyticCompletion: "تحلیل کامل شد، در حال همگام‌سازی با پایگاه داده..."
# همگام‌سازی گره
SyncNode: "همگام‌سازی داده‌ها با گره {{ .name }}"
LocalName: "نام 'local' فقط برای شناسایی محلی سیستم استفاده می‌شود"
SyncPackageData: "همگام‌سازی داده‌های بسته"
SyncPackageEncrypt: "رمزگذاری بسته داده"
SyncRequest: "درخواست API همگام‌سازی گره"
SyncFailedRetry: "زمان همگام‌سازی داده‌های گره به پایان رسید (تلاش {{ .index }})، در حال تلاش مجدد..."
SyncFailed: "همگام‌سازی ناموفق بود، به صورت دستی در لیست گره‌ها همگام‌سازی کنید!"
SyncSystemProxy: "تنظیمات پراکسی سیستم"
SyncScripts: "کتابخانه اسکریپت"
SyncBackupAccounts: "حساب‌های پشتیبان"
SyncAlertSetting: "تنظیمات هشدار"
SyncCustomApp: "برنامه سفارشی"
SyncLanguage: "زبان سیستم"
SyncEdition: "منطقه"
# ارتقای گره
NodeUpgrade: "ارتقاء گره {{ .name }}"
UpgradeCheck: "بررسی به‌روزرسانی گره"
UpgradeCheckLocal: "گره‌های محلی از ارتقاء دسته‌ای پشتیبانی نمی‌کنند، رد شد..."
UpgradeCheckLatest: "گره از قبل آخرین نسخه است، رد شد..."
NewSSHClient: "در حال راه‌اندازی اتصال SSH"
BackupBeforeUpgrade: "پشتیبان‌گیری از داده‌ها قبل از ارتقاء"
UploadUpgradeFile: "توزیع فایل‌های ارتقاء"
RestartAfterUpgrade: "شروع سرویس پس از ارتقاء"
LoadAutoUpgradeNodesFailed: "بارگذاری گره‌های ارتقاء خودکار ناموفق بود، خطا: {{ .err }}"
AutoUpgradeNodes: "گره‌های ارتقاء خودکار: {{ .nodes }}"
UpdateAutoUpgradeNodesStatusFailed: "به‌روزرسانی وضعیت گره‌های ارتقاء خودکار ناموفق بود، خطا: {{ .err }}"
# افزودن گره
MasterData: "داده‌های گره اصلی"
LoadSftpClient: "بارگذاری کلاینت SFTP"
PackageMasterData: "تولید بسته پشتیبان گره اصلی"
UploadBackup: "بارگذاری داده‌های پشتیبان"
TaskAddNode: "افزودن گره"
LoadNodeArch: "دریافت اطلاعات معماری گره"
LoadNodeArchDetail: "معماری گره اصلی شناسایی شد: {{ .local }}، معماری گره زیرین: {{ .node }}"
LoadNodeUpgradeDetail: "استفاده از دایرکتوری نصب تاریخی نسخه v1: {{ .baseDir }}، پورت شنود سرویس: {{ .port }}"
SyncAgentBaseInfo: "همگام‌سازی اطلاعات پایه گره"
GenerateSSLInfo: "تولید اطلاعات SSL گره"
ConnInfoNotMatch: "اطلاعات اتصال مطابقت ندارد"
MakeAgentPackage: "تولید بسته نصب گره"
SendAgent: "توزیع بسته نصب گره"
StartService: "شروع سرویس"
NoBackupNode: "گره پشتیبان خالی است. ابتدا یکی را انتخاب کرده و ذخیره کنید"
# همگام‌سازی فایل و تصویر گره
LocalNodeIpFailed: "دریافت IP گره اصلی ناموفق بود. گره اصلی را ویرایش کرده و آدرس IP و اطلاعات احراز هویت SSH را اضافه کنید."
HandlePrivateKey: "مدیریت کلید خصوصی گره"
HandlePublicKey: "مدیریت کلید عمومی گره"
ExchangeFile: "شروع همگام‌سازی {{ .sourcePath }} از گره {{ .source }} به گره {{ .dest }}:{{ .destPath }}"
NodeFile: "فایل گره"
ImageSyncTaskName: "Image sync {{ .count }} images"
SSLSyncTaskName: "Certificate sync {{ .count }} certificates"
AppSyncTaskName: "App sync {{ .name }}"
SSLSyncToNode: "Push certificate [{{ .cert }}] to node [{{ .node }}]"
ImageSyncSave: "ذخیره تصویر {{ .image }}"
ImageSyncSaveTags: "ذخیره برچسب‌های تصویر {{ .tags }}"
ImageSyncToNode: "همگام‌سازی تصویر {{ .image }} به گره {{ .node }}"
ImageSyncLoad: "بارگذاری تصویر {{ .image }} روی گره {{ .node }}"
ImageSyncClean: "پاک‌سازی فایل‌های موقت تصویر {{ .image }}"
ImageSyncNoTag: "تصویر {{ .image }} هیچ برچسبی ندارد و با شناسه تصویر ذخیره می‌شود"
ImageSyncFrontendTagsIgnored: "هیچ برچسبی برای تصویر {{ .image }} در گره منبع یافت نشد. برچسب‌های فرانت‌اند نادیده گرفته شدند."
ImageSyncHandlePrivateKey: "مدیریت کلید خصوصی گره همگام‌سازی تصویر"
ImageSyncHandlePublicKey: "مدیریت کلید عمومی گره همگام‌سازی تصویر"
ImageSyncTransfer: "شروع انتقال فایل موقت تصویر: {{ .source }}:{{ .sourcePath }} -> {{ .dest }}:{{ .destPath }}"
# خط فرمان
SudoHelper: "از {{ .cmd }} استفاده کنید یا به کاربر root تغییر دهید"
UsernameNeed: "نسخه سازمانی باید --username را مشخص کند"
DBConnErr: "خطا: راه‌اندازی اتصال پایگاه داده ناموفق بود، {{ .err }}"
SystemVersion: "نسخه: "
SystemMode: "حالت: "
# خط فرمان - برنامه
AppVersion: "نسخه برنامه"
AppCommands: "دستورات مرتبط با برنامه"
AppInit: "راه‌اندازی برنامه"
AppKeyVal: "کلید برنامه (فقط انگلیسی پشتیبانی می‌شود)"
AppCreateFileErr: "ایجاد فایل {{ .name }} ناموفق بود {{ .err }}"
AppCreateDirErr: "ایجاد پوشه {{ .name }} ناموفق بود {{ .err }}"
AppMissKey: "کلید برنامه وجود ندارد، از -k برای مشخص کردن استفاده کنید"
AppMissVersion: "نسخه برنامه وجود ندارد، از -v برای مشخص کردن استفاده کنید"
AppVersionExist: "نسخه از قبل وجود دارد!"
AppCreateSuccessful: "ایجاد با موفقیت انجام شد!"
AppWriteErr: "نوشتن فایل {{ .name }} ناموفق بود {{ .err }}"
# خط فرمان - IP شنود
ListenIPCommands: "تغییر IP شنود"
ListenIPv4: "شنود روی IPv4"
ListenIPv6: "شنود روی IPv6"
ListenChangeSuccessful: "تغییر با موفقیت انجام شد! در حال شنود روی {{ .value }}"
# خط فرمان - بازنشانی
ResetCommands: "بازنشانی اطلاعات سیستم"
ResetMFA: "لغو احراز هویت دو مرحله‌ای 1Panel"
ResetHttps: "لغو ورود https 1Panel"
ResetEntrance: "لغو ورودی امنیتی 1Panel"
ResetIPs: "لغو محدودیت‌های IP مجاز 1Panel"
ResetDomain: "لغو اتصال دامنه 1Panel"
ResetPasskey: "پاک‌سازی کلیدهای عبور 1Panel"
# خط فرمان - کاربر
UserList: "دریافت لیست کاربران 1Panel"
UserTableName: "نام"
UserTableMFAStatus: "وضعیت MFA"
UserTableSuperAdmin: "مدیر کل"
UserTableCreatedAt: "تاریخ ایجاد"
UserEmptyList: "هیچ کاربری یافت نشد"
UserInfo: "دریافت اطلاعات پنل"
UserInfoAddr: "آدرس پنل: "
UserInfoPassHelp: "نکته: برای تغییر رمز عبور، می‌توانید دستور را اجرا کنید: "
# خط فرمان - بازیابی
RestoreCommands: "بازگشت سرویس و داده‌های 1Panel"
RestoreNoSuchFile: "هیچ فایل بازگشتی یافت نشد"
RestoreStep1: "(۱/۵) شروع بازگشت سرویس و داده‌های 1Panel از دایرکتوری {{ .name }}..."
RestoreStep2: "(۲/۵) بازگشت باینری 1Panel تکمیل شد"
RestoreStep3: "(۳/۵) بازگشت اسکریپت 1Panel تکمیل شد"
RestoreStep4: "(۴/۵) بازگشت سرویس 1Panel تکمیل شد"
RestoreStep5: "(۵/۵) بازگشت داده‌های 1Panel تکمیل شد"
RestoreSuccessful: "بازگشت تکمیل شد. به نسخه {{ .version }} بازگردانده شد. در حال راه‌اندازی مجدد سرویس..."
# خط فرمان - به‌روزرسانی
UpdateCommands: "به‌روزرسانی اطلاعات پنل"
UpdateUser: "به‌روزرسانی اطلاعات کاربر"
UpdatePassword: "به‌روزرسانی رمز عبور کاربر"
UpdatePort: "به‌روزرسانی پورت پنل"
UpdateUserNull: "خطا: کاربر خالی است!"
UpdateUserBlank: "خطا: کاربر شامل فاصله است!"
UpdateUserFormat: "خطا: فرمت کاربر نامعتبر است! فقط انگلیسی، چینی، اعداد و _ با طول ۳-۳۰ پشتیبانی می‌شود"
UpdateUserErr: "خطا: به‌روزرسانی کاربر ناموفق بود، {{ .err }}"
UpdateSuccessful: "به‌روزرسانی با موفقیت انجام شد!"
UpdateUserResult: "کاربر: {{ .name }}"
UpdatePasswordRead: "خطا: خواندن اطلاعات رمز عبور کاربر ناموفق بود، {{ .err }}"
UpdatePasswordNull: "خطا: رمز عبور کاربر خالی است!"
UpdateUPasswordBlank: "خطا: رمز عبور کاربر شامل فاصله است!"
UpdatePasswordFormat: "خطا: رمز عبور کاربر فقط از حروف، اعداد و کاراکترهای ویژه (!@#$%*_,.?) با طول ۸-۳۰ پشتیبانی می‌کند."
UpdatePasswordLen: "خطا: رمز عبور بیشتر از ۶ کاراکتر وارد کنید"
UpdatePasswordRe: "تکرار رمز عبور:"
UpdatePasswordErr: "خطا: به‌روزرسانی رمز عبور کاربر ناموفق بود، {{ .err }}"
UpdatePasswordSame: "خطا: دو رمز عبور مطابقت ندارند، بررسی و دوباره تلاش کنید!"
UpdatePasswordResult: "رمز عبور کاربر: {{ .name }}"
UpdatePortFormat: "خطا: شماره پورت ورودی باید بین ۱ تا ۶۵۵۳۵ باشد!"
UpdatePortUsed: "خطا: شماره پورت قبلاً در حال استفاده است، بررسی و دوباره تلاش کنید!"
UpdatePortErr: "خطا: به‌روزرسانی پورت پنل ناموفق بود، {{ .err }}"
UpdatePortResult: "پورت پنل: {{ .name }}"
UpdatePortFirewallAdd: "افزودن قانون پورت دیواره آتش ناموفق بود، {{ .err }}، پورت {{ .name }} را به صورت دستی به قوانین دیواره آتش اضافه کنید."
UpdatePortFirewallDel: "خطا: حذف پورت دیواره آتش ناموفق بود، {{ .err }}"
UpdatePortFirewallReload: "بارگذاری مجدد دیواره آتش ناموفق بود، {{ .err }}، دیواره آتش را به صورت دستی بارگذاری مجدد کنید."
# برنامه موبایل
ErrVerifyToken: 'تأیید توکن ناموفق بود. بازنشانی کرده و دوباره اسکن کنید.'
ErrInvalidToken: 'توکن نامعتبر است. بازنشانی کرده و دوباره اسکن کنید.'
ErrExpiredToken: 'توکن منقضی شده است. بازنشانی کرده و دوباره اسکن کنید.'
# خروجی فرمان
Name: "نام"
Command: "دستور"
+159 -96
View File
@@ -1,69 +1,65 @@
# 基本エラー
ErrInvalidParams: '不正なリクエスト: {{ .detail }}' ErrInvalidParams: '不正なリクエスト: {{ .detail }}'
ErrTokenParse: 'トークンエラー: {{ .detail }}' ErrTokenParse: 'トークンエラー: {{ .detail }}'
ErrInitialPassword: '元のパスワードが違います' ErrInitialPassword: '元のパスワードが違います'
ErrInternalServer: '内部エラー: {{ .detail }}' ErrInternalServer: '内部エラー: {{ .detail }}'
ErrInternalServerKey: "サーバー内部エラー: "
ErrRecordExist: 'レコードが既に存在します' ErrRecordExist: 'レコードが既に存在します'
ErrRecordNotFound: 'レコードが見つかりません' ErrRecordNotFound: 'レコードが見つかりません'
ErrStructTransform: '型変換エラー: {{ .err }}' ErrStructTransform: '型変換エラー: {{ .err }}'
ErrNotLogin: 'ログインしていません: {{ .detail }}'
ErrSessionDataNotFound: "現在のセッションは期限切れです!"
ErrSessionDataFormat: "現在のセッションデータ形式が異常です!"
ErrPasswordExpired: 'パスワード期限切れ: {{ .detail }}'
ErrNotSupportType: '未対応のタイプ: {{ .name }}' ErrNotSupportType: '未対応のタイプ: {{ .name }}'
ErrProxy: 'リクエストに失敗しました: {{ .detail }}' ErrDemoEnvironment: 'デモ環境では利用できません'
ErrApiConfigStatusInvalid: 'API利用不可: {{ .detail }}' ErrCmdTimeout: 'コマンドがタイムアウトしました'
ErrApiConfigKeyInvalid: 'APIキーが無効です: {{ .detail }}' ErrPortInUsed: "{{ .name }} ポートはすでに使用されています!"
ErrApiConfigIPInvalid: 'IPが許可されていません: {{ .detail }}' ErrFileNotFound: "{{ .name }} ファイルが存在しません"
ErrApiConfigDisable: 'APIは無効です: {{ .detail }}' ErrReqFailed: "{{.name}} リクエスト失敗: {{ .err }}"
ErrApiConfigKeyTimeInvalid: 'タイムスタンプが無効です: {{ .detail }}'
ErrLoginLocked: "失敗回数が多すぎます。ログインは 5 分間一時的にロックされています。"
# request # リクエストとセキュリティ入口
ErrNoSuchHost: "要求されたサーバーが見つかりません {{ .err }}" ErrNoSuchHost: "要求されたサーバーが見つかりません {{ .err }}"
ErrHttpReqNotFound: "要求されたリソースが見つかりません {{ .err }}" ErrHttpReqNotFound: "要求されたリソースが見つかりません {{ .err }}"
ErrHttpReqFailed: "リクエスト失敗 {{ .err }}" ErrHttpReqFailed: "リクエスト失敗 {{ .err }}"
ErrHttpReqTimeOut: "リクエストタイムアウト {{ .err }}" ErrHttpReqTimeOut: "リクエストタイムアウト {{ .err }}"
ErrCreateHttpClient: "リクエストの作成に失敗しました {{ .err }}" ErrCreateHttpClient: "リクエストの作成に失敗しました {{ .err }}"
ErrProxy: 'リクエストに失敗しました: {{ .detail }}'
ErrProxySetting: "プロキシサーバー情報が利用できません {{ .err }}、確認して再試行してください!" ErrProxySetting: "プロキシサーバー情報が利用できません {{ .err }}、確認して再試行してください!"
ErrEntrance: "セキュリティ情報エラー、再確認してください!"
ErrEntranceFormat: "セキュリティエントランス {{ .name }} は現在サポートされていません。確認して再試行してください!" ErrEntranceFormat: "セキュリティエントランス {{ .name }} は現在サポートされていません。確認して再試行してください!"
# common # ログインとセキュリティ
ErrDemoEnvironment: 'デモ環境では利用できません' ErrNotLogin: 'ログインしていません: {{ .detail }}'
ErrCmdTimeout: 'コマンドがタイムアウトしました' ErrSessionDataNotFound: "現在のセッションは期限切れです!"
ErrEntrance: "セキュリティ情報エラー、再確認してください!" ErrSessionDataFormat: "現在のセッションデータ形式が異常です!"
ErrPasswordExpired: 'パスワード期限切れ: {{ .detail }}'
ErrLoginLocked: "失敗回数が多すぎます。ログインは 5 分間一時的にロックされています。"
ErrApiConfigStatusInvalid: 'API利用不可: {{ .detail }}'
ErrApiConfigKeyInvalid: 'APIキーが無効です: {{ .detail }}'
ErrApiConfigIPInvalid: 'IPが許可されていません: {{ .detail }}'
ErrApiConfigDisable: 'APIは無効です: {{ .detail }}'
ErrApiConfigKeyTimeInvalid: 'タイムスタンプが無効です: {{ .detail }}'
ErrPasskeyDisabled: "Passkeyを使用するにはHTTPSを有効にする必要があります"
ErrPasskeyNotConfigured: "Passkeyが設定されていません"
ErrPasskeyLimit: "Passkeyの上限に達しました(最大5個)"
ErrPasskeySession: "Passkeyセッションの有効期限が切れているか無効です"
ErrPasskeyDuplicate: "Passkeyは既に存在します"
ErrPasskeyVerify: "Passkeyの検証に失敗しました"
# ユーザーと権限
ErrNoSuchUser: "ユーザー情報が見つかりません。確認して再試行してください!"
ErrToMaster: "このユーザーにはマスターノードでこの操作を実行する権限がありません。確認して再試行してください!"
ErrToNode: "このユーザーにはこのノードでこの操作を実行する権限がありません。確認して再試行してください!"
ErrRBAC: "ユーザー権限が不足しているため、この操作を実行できません。確認して再試行してください!"
ErrNoneNode: "このユーザーにはノード権限がありません。管理者に連絡するか、確認して再試行してください!"
ErrOnlySuperAdmin: "この機能はスーパー管理者のみ使用できます!"
ErrRolePresetCannotDelete: "システム既定ロールは削除できません"
ErrRolePresetCannotUpdate: "システム既定ロールは更新できません"
ErrRoleBoundToUser: "このロールはすでにユーザーに紐付いているため削除できません"
ErrRolePresetCannotBind: "システム既定ロールはユーザーに割り当てできません"
ErrNodeAdminMasterForbidden: "マスターノードにノード管理者権限を追加することはできません"
ErrSuperAdminCannotDelete: "スーパー管理者ユーザーは削除できません"
ErrGroupIsDefault: "デフォルトグループの削除はできません" ErrGroupIsDefault: "デフォルトグループの削除はできません"
ErrGroupIsInUse: "グループは使用中のため、削除できません。" ErrGroupIsInUse: "グループは使用中のため、削除できません。"
ErrAIProxyUserGroupIsDefault: "デフォルトユーザーグループは削除できません"
ErrAIProxyUserGroupInUse: "ユーザーグループは使用中のため、削除できません。"
ErrAIProxyUserGroupExists: "ユーザーグループ名は既に存在します。"
ErrAIProxyBackendAccountExists: "このモデルアカウントは既に AI ゲートウェイのアカウントプールにインポートされています。"
ErrAIProxyModelGroupInUse: "モデルグループは使用中のため、削除できません。"
ErrAIProxyModelGroupExists: "モデルグループ名は既に存在します。"
ErrAIProxySensitiveGroupInUse: "センシティブワードグループは使用中のため削除できません。"
ErrAIProxySensitiveGroupExists: "センシティブワードグループ名は既に存在します。"
ErrLocalDelete: "ローカルノードは削除できません!"
ErrPortInUsed: "{{ .name }} ポートはすでに使用されています!"
ErrInternalServerKey: "サーバー内部エラー: "
MasterNode: "マスターノード"
# app # ライセンス
CustomAppStoreFileValid: "アプリストアパッケージは .tar.gz 形式である必要があります"
ErrFileNotFound: "{{ .name }} ファイルが存在しません"
AppBackup: 'アプリケーションバックアップ'
AppBackupPush: 'アプリケーションバックアップファイル {{.file}} をノード {{ .name }} に転送'
ErrSourceTargetSame: 'ソースノードとターゲットノードは同じにできません!'
AppInstall: 'ノード {{ .targetNode }} にアプリケーション {{ .name }} をインストール'
AppInstallCheck: 'アプリケーションインストール環境を確認'
# backup
ErrBackupInUsed: 'バックアップアカウントがスケジュールで使用中'
ErrBackupCheck: '接続テストに失敗しました: {{ .err }}'
ErrBackupLocal: "ローカルサーバーバックアップアカウントはこの操作をサポートしていません!"
ErrBackupPublic: "このバックアップアカウントが公開されていないと検出されました。再確認してください!"
ErrOSSConn: "最新バージョンを取得できません。外部ネットワーク接続を確認してください。"
#license
LicenseCheck: 'ライセンスが利用可能か確認する' LicenseCheck: 'ライセンスが利用可能か確認する'
ErrLicenseInUsed: 'このライセンスは既に紐付けられています。確認して再試行してください!' ErrLicenseInUsed: 'このライセンスは既に紐付けられています。確認して再試行してください!'
ErrLicenseExpired: 'このライセンスは期限切れです。確認して再試行してください!' ErrLicenseExpired: 'このライセンスは期限切れです。確認して再試行してください!'
@@ -93,21 +89,6 @@ ErrNodeUnbind: "そのノードはライセンスのバインド範囲内では
ErrNodeBind: "そのノードはライセンスにバインドされています、確認して再試行してください" ErrNodeBind: "そのノードはライセンスにバインドされています、確認して再試行してください"
ErrNodeLocalRollback: "マスターノードでは直接ロールバックできません。'1pctl restore' を手動で実行してロールバックしてください" ErrNodeLocalRollback: "マスターノードでは直接ロールバックできません。'1pctl restore' を手動で実行してロールバックしてください"
ErrIntlLicense: "現在のバージョンでは国際版ライセンスのインポートはまだサポートされていません。しばらくお待ちください!" ErrIntlLicense: "現在のバージョンでは国際版ライセンスのインポートはまだサポートされていません。しばらくお待ちください!"
# user
ErrNoSuchUser: "ユーザー情報が見つかりません。確認して再試行してください!"
ErrToMaster: "このユーザーにはマスターノードでこの操作を実行する権限がありません。確認して再試行してください!"
ErrToNode: "このユーザーにはこのノードでこの操作を実行する権限がありません。確認して再試行してください!"
ErrRBAC: "ユーザー権限が不足しているため、この操作を実行できません。確認して再試行してください!"
ErrNoneNode: "このユーザーにはノード権限がありません。管理者に連絡するか、確認して再試行してください!"
ErrOnlySuperAdmin: "この機能はスーパー管理者のみ使用できます!"
ErrRolePresetCannotDelete: "システム既定ロールは削除できません"
ErrRolePresetCannotUpdate: "システム既定ロールは更新できません"
ErrRoleBoundToUser: "このロールはすでにユーザーに紐付いているため削除できません"
ErrRolePresetCannotBind: "システム既定ロールはユーザーに割り当てできません"
ErrNodeAdminMasterForbidden: "マスターノードにノード管理者権限を追加することはできません"
ErrSuperAdminCannotDelete: "スーパー管理者ユーザーは削除できません"
InvalidRequestBodyType: "リクエストボディの形式が無効です。内容が要求された形式に準拠しているか確認してから再試行してください!" InvalidRequestBodyType: "リクエストボディの形式が無効です。内容が要求された形式に準拠しているか確認してから再試行してください!"
InvalidLicenseCodeType: "提供されたライセンスコードの形式が無効です。確認してから再試行してください!" InvalidLicenseCodeType: "提供されたライセンスコードの形式が無効です。確認してから再試行してください!"
LicenseNotFoundType: "ライセンスが見つかりません。提供されたライセンスに一致する記録がシステム内に存在しません。確認してから再試行してください!" LicenseNotFoundType: "ライセンスが見つかりません。提供されたライセンスに一致する記録がシステム内に存在しません。確認してから再試行してください!"
@@ -118,10 +99,65 @@ InvalidAssigneeType: "ライセンス割り当ての対象ユーザーまたは
LicenseUsageNotFoundType: "使用記録がありません。このライセンスはまだ有効化または使用されていません。確認してから再試行してください!" LicenseUsageNotFoundType: "使用記録がありません。このライセンスはまだ有効化または使用されていません。確認してから再試行してください!"
LicenseUsageLimitExceededType: "このライセンスは既に他のノードにバインドされています。確認してから再試行してください!" LicenseUsageLimitExceededType: "このライセンスは既に他のノードにバインドされています。確認してから再試行してください!"
# alert # ノードとクラスター
MasterNode: "マスターノード"
Node: "ノード"
ErrLocalDelete: "ローカルノードは削除できません!"
ErrMasterDelete: "マスターノードを削除できません。スレーブノードを先に削除してください。"
ClusterNameIsExist: "クラスタ名は既に存在します。"
AppStatusUnHealthy: "アプリケーションのステータス取得が異常です。ノードリストでインストールノードのステータスを確認してください。"
MasterNodePortNotAvailable: "ノード {{ .name }} のポート {{ .port }} の接続性検証が失敗しました。ファイアウォール/セキュリティグループの設定とマスターノードのステータスを確認してください。"
ClusterMasterNotExist: "クラスタのマスターノードが切断されています。子ノードを削除してください。"
# 仮想マシン
ErrVMNotFound: "仮想マシンが存在しません"
ErrVMAlreadyExists: "仮想マシンは既に存在します"
ErrVMStoragePathInUse: "ストレージプールのパスは既に [{{ .name }}] で使用されています"
ErrVMRunning: "仮想マシンは実行中です"
ErrVMLibvirtConnect: "libvirt への接続に失敗しました: {{ .detail }}"
ErrVMPermission: "仮想マシンを操作する権限がありません: {{ .detail }}"
ErrVMNetworkNotFound: "仮想マシンネットワークが存在しません: {{ .detail }}"
ErrVMInvalidPath: "仮想マシンのパスが無効です: {{ .detail }}"
ErrVMInvalidInput: "仮想マシンのパラメータが無効です: {{ .detail }}"
ErrVMCommandFailed: "仮想マシンコマンドの実行に失敗しました: {{ .err }}"
VMSnapshotCreateTask: "Create snapshot [{{ .snapshot }}] for virtual machine [{{ .vm }}]"
VMSnapshotCreateStep: "Create virtual machine snapshot [{{ .snapshot }}]"
VMSnapshotRecoverTask: "Recover snapshot [{{ .snapshot }}] for virtual machine [{{ .vm }}]"
VMSnapshotRecoverStep: "Recover virtual machine snapshot [{{ .snapshot }}]"
VMSnapshotDeleteTask: "Delete snapshot [{{ .snapshot }}] for virtual machine [{{ .vm }}]"
VMSnapshotDeleteStep: "Delete virtual machine snapshot [{{ .snapshot }}]"
# アプリ
CustomAppStoreFileValid: "アプリストアパッケージは .tar.gz 形式である必要があります"
AppBackup: 'アプリケーションバックアップ'
AppBackupPush: 'アプリケーションバックアップファイル {{.file}} をノード {{ .name }} に転送'
ErrSourceTargetSame: 'ソースノードとターゲットノードは同じにできません!'
AppInstall: 'ノード {{ .targetNode }} にアプリケーション {{ .name }} をインストール'
AppInstallCheck: 'アプリケーションインストール環境を確認'
# バックアップ
ErrBackupInUsed: 'バックアップアカウントがスケジュールで使用中'
ErrBackupCheck: '接続テストに失敗しました: {{ .err }}'
ErrBackupLocal: "ローカルサーバーバックアップアカウントはこの操作をサポートしていません!"
ErrBackupPublic: "このバックアップアカウントが公開されていないと検出されました。再確認してください!"
ErrOSSConn: "最新バージョンを取得できません。外部ネットワーク接続を確認してください。"
MvBackup: "データをバックアップディレクトリに移動"
# アラート
ErrAlertSync: "アラート情報の同期エラーです。後で再試行してください!" ErrAlertSync: "アラート情報の同期エラーです。後で再試行してください!"
#task # AIゲートウェイ
ErrAIProxyUserGroupIsDefault: "デフォルトユーザーグループは削除できません"
ErrAIProxyUserGroupInUse: "ユーザーグループは使用中のため、削除できません。"
ErrAIProxyUserGroupExists: "ユーザーグループ名は既に存在します。"
ErrAIProxyBackendAccountExists: "このモデルアカウントは既に AI ゲートウェイのアカウントプールにインポートされています。"
ErrAIProxyModelGroupInUse: "モデルグループは使用中のため、削除できません。"
ErrAIProxyModelGroupExists: "モデルグループ名は既に存在します。"
ErrAIProxySensitiveGroupInUse: "センシティブワードグループは使用中のため削除できません。"
ErrAIProxySensitiveGroupExists: "センシティブワードグループ名は既に存在します。"
AIBenchmarkRun: "AIベンチマークを実行"
# タスク
TaskStart: "{{ .name }} タスク開始 [START]" TaskStart: "{{ .name }} タスク開始 [START]"
TaskEnd: "{{ .name }} タスク終了 [COMPLETED]" TaskEnd: "{{ .name }} タスク終了 [COMPLETED]"
TaskFailed: "{{ .name }} タスク失敗" TaskFailed: "{{ .name }} タスク失敗"
@@ -135,6 +171,16 @@ TaskUpgrade: "アップグレード"
TaskSync: '同期' TaskSync: '同期'
TaskSyncForNode: "ノードデータを同期" TaskSyncForNode: "ノードデータを同期"
TaskBackup: "バックアップ" TaskBackup: "バックアップ"
TaskPush: "送信"
TaskRsync: "Sync"
SuccessStatus: "{{ .name }} 成功"
FailedStatus: "{{ .name }} 失敗 {{ .err }}"
Start: "開始"
SubTask: "サブタスク"
Skip: "エラーを無視して続行..."
Success: "成功"
# エージェント一括タスク
BatchInstallAgent: "エージェントの一括インストール" BatchInstallAgent: "エージェントの一括インストール"
DispatchAgentInstallTasks: "エージェントインストールタスクを配信" DispatchAgentInstallTasks: "エージェントインストールタスクを配信"
BatchUpgradeAgent: "エージェントの一括アップグレード" BatchUpgradeAgent: "エージェントの一括アップグレード"
@@ -168,20 +214,15 @@ AgentOperateStart: "開始"
AgentOperateStop: "停止" AgentOperateStop: "停止"
AgentOperateRestart: "再起動" AgentOperateRestart: "再起動"
AgentOperateDelete: "削除" AgentOperateDelete: "削除"
SuccessStatus: "{{ .name }} 成功"
FailedStatus: "{{ .name }} 失敗 {{ .err }}" # アプリとスキルのタスク
Start: "開始"
SubTask: "サブタスク"
Skip: "エラーを無視して続行..."
PushAppInstallTaskToNode: "ノード [{{ .name }}] にアプリインストールタスクを送信" PushAppInstallTaskToNode: "ノード [{{ .name }}] にアプリインストールタスクを送信"
TaskPush: "送信"
AppInstallTask: "アプリインストールタスク" AppInstallTask: "アプリインストールタスク"
PushAppFailed: "アプリインストールタスクの送信に失敗しました" PushAppFailed: "アプリインストールタスクの送信に失敗しました"
SkillHubInstallTask: "スキルをインストール [{{ .name }}]" SkillHubInstallTask: "スキルをインストール [{{ .name }}]"
SkillHubInstallToTarget: "ターゲットにスキルをインストール [{{ .name }}]" SkillHubInstallToTarget: "ターゲットにスキルをインストール [{{ .name }}]"
Success: "成功"
#script # スクリプトライブラリ
ScriptLibrary: "スクリプトライブラリ" ScriptLibrary: "スクリプトライブラリ"
RemoteScriptLibrary: "リモートスクリプトライブラリ" RemoteScriptLibrary: "リモートスクリプトライブラリ"
ScriptSyncSkip: "現在のスクリプトライブラリは最新バージョンです!" ScriptSyncSkip: "現在のスクリプトライブラリは最新バージョンです!"
@@ -189,7 +230,7 @@ DownloadData: "スクリプトライブラリファイル data.yaml をダウン
DownloadPackage: "スクリプトライブラリパッケージをダウンロード中" DownloadPackage: "スクリプトライブラリパッケージをダウンロード中"
AnalyticCompletion: "解析が完了しました、データベースに同期しています..." AnalyticCompletion: "解析が完了しました、データベースに同期しています..."
Node: "ノード" # ノード同期
SyncNode: "データをノード {{ .name }} に同期" SyncNode: "データをノード {{ .name }} に同期"
LocalName: "'local'名称はシステムのローカル識別のみに使用されます" LocalName: "'local'名称はシステムのローカル識別のみに使用されます"
SyncPackageData: "同期データのパッケージ化" SyncPackageData: "同期データのパッケージ化"
@@ -205,7 +246,7 @@ SyncCustomApp: "カスタムアプリ"
SyncLanguage: "システム言語" SyncLanguage: "システム言語"
SyncEdition: "実行リージョン" SyncEdition: "実行リージョン"
#upgrade node # ノードアップグレード
NodeUpgrade: "{{ .name }} ノードのアップグレード" NodeUpgrade: "{{ .name }} ノードのアップグレード"
UpgradeCheck: "ノードの更新を確認" UpgradeCheck: "ノードの更新を確認"
UpgradeCheckLocal: "ローカルノードは一括アップグレードをサポートしていないため、スキップします..." UpgradeCheckLocal: "ローカルノードは一括アップグレードをサポートしていないため、スキップします..."
@@ -218,12 +259,11 @@ LoadAutoUpgradeNodesFailed: "自動アップグレードノードの読み込み
AutoUpgradeNodes: "自動アップグレードノード: {{ .nodes }}" AutoUpgradeNodes: "自動アップグレードノード: {{ .nodes }}"
UpdateAutoUpgradeNodesStatusFailed: "自動アップグレードノードのステータス更新に失敗しました、エラー: {{ .err }}" UpdateAutoUpgradeNodesStatusFailed: "自動アップグレードノードのステータス更新に失敗しました、エラー: {{ .err }}"
#add node # ノード追加
MasterData: "マスターノードデータ" MasterData: "マスターノードデータ"
LoadSftpClient: "SFTPクライアントの取得" LoadSftpClient: "SFTPクライアントの取得"
PackageMasterData: "マスターノードのバックアップパッケージを生成" PackageMasterData: "マスターノードのバックアップパッケージを生成"
UploadBackup: "バックアップデータをアップロード" UploadBackup: "バックアップデータをアップロード"
MvBackup: "データをバックアップディレクトリに移動"
TaskAddNode: "ノードを追加" TaskAddNode: "ノードを追加"
LoadNodeArch: "ノードアーキテクチャ情報を取得" LoadNodeArch: "ノードアーキテクチャ情報を取得"
LoadNodeArchDetail: "検出されたマスターノードアーキテクチャ: {{ .local }}, 子ノードアーキテクチャ: {{ .node }}" LoadNodeArchDetail: "検出されたマスターノードアーキテクチャ: {{ .local }}, 子ノードアーキテクチャ: {{ .node }}"
@@ -236,7 +276,35 @@ SendAgent: "ノードインストールパッケージを送信"
StartService: "サービスを開始" StartService: "サービスを開始"
NoBackupNode: "現在バックアップノードが空です。保存するバックアップノードを選択して再試行してください!" NoBackupNode: "現在バックアップノードが空です。保存するバックアップノードを選択して再試行してください!"
#cmd # ノードファイルとイメージ同期
LocalNodeIpFailed: "Failed to get master node IP. Edit the master node and add IP address and SSH authentication information."
HandlePrivateKey: "Handle node private key"
HandlePublicKey: "Handle node public key"
ExchangeFile: "Start syncing {{ .sourcePath }} from node {{ .source }} to node {{ .dest }}:{{ .destPath }}"
NodeFile: "Node file"
ImageSyncTaskName: "Image sync {{ .count }} images"
SSLSyncTaskName: "Certificate sync {{ .count }} certificates"
AppSyncTaskName: "App sync {{ .name }}"
SSLSyncToNode: "Push certificate [{{ .cert }}] to node [{{ .node }}]"
ImageSyncSave: "Save image {{ .image }}"
ImageSyncSaveTags: "Save image tags {{ .tags }}"
ImageSyncToNode: "Sync image {{ .image }} to node {{ .node }}"
ImageSyncLoad: "Load image {{ .image }} on node {{ .node }}"
ImageSyncClean: "Clean temporary files for image {{ .image }}"
ImageSyncNoTag: "Image {{ .image }} has no tag and will be saved by image ID"
ImageSyncFrontendTagsIgnored: "No tags were found for image {{ .image }} on the source node. Frontend tags were ignored."
ImageSyncHandlePrivateKey: "Handle image sync node private key"
ImageSyncHandlePublicKey: "Handle image sync node public key"
ImageSyncTransfer: "Start transferring image temporary file: {{ .source }}:{{ .sourcePath }} -> {{ .dest }}:{{ .destPath }}"
# コマンドライン
SudoHelper: "{{.cmd}}を使用するか、ルートユーザーに切り替えてください"
UsernameNeed: "Enterprise版では --username を指定する必要があります"
DBConnErr: "エラー: データベース接続の初期化に失敗しました、{{ .err }}"
SystemVersion: "バージョン: "
SystemMode: "モード: "
# コマンドライン - アプリ
AppVersion: "アプリバージョン" AppVersion: "アプリバージョン"
AppCommands: "アプリ関連のコマンド" AppCommands: "アプリ関連のコマンド"
AppInit: "アプリを初期化します" AppInit: "アプリを初期化します"
@@ -248,12 +316,14 @@ AppMissVersion: "アプリバージョンがありません、-vを使用して
AppVersionExist: "バージョンはすでに存在します!" AppVersionExist: "バージョンはすでに存在します!"
AppCreateSuccessful: "創造は成功しました!" AppCreateSuccessful: "創造は成功しました!"
AppWriteErr: "file {{ .name }} write failed {{ .err }}" AppWriteErr: "file {{ .name }} write failed {{ .err }}"
SudoHelper: "{{.cmd}}を使用するか、ルートユーザーに切り替えてください"
UsernameNeed: "Enterprise版では --username を指定する必要があります" # コマンドライン - 監視IP
ListenIPCommands: "リスニングIPを切り替えます" ListenIPCommands: "リスニングIPを切り替えます"
ListenIPv4: "IPv4で聞いてください" ListenIPv4: "IPv4で聞いてください"
ListenIPv6: "IPv6で聞く" ListenIPv6: "IPv6で聞く"
ListenChangeSuccessful: "切り替え成功!{{.Value}}で聞いています" ListenChangeSuccessful: "切り替え成功!{{.Value}}で聞いています"
# コマンドライン - リセット
ResetCommands: "システム情報をリセットします" ResetCommands: "システム情報をリセットします"
ResetMFA: "1パネルの2要素認証をキャンセルします" ResetMFA: "1パネルの2要素認証をキャンセルします"
ResetHttps: "1Panel HTTPSログインをキャンセルします" ResetHttps: "1Panel HTTPSログインをキャンセルします"
@@ -261,12 +331,19 @@ ResetEntrance: "1パネルの安全な入り口をキャンセルします"
ResetIPs: "1パネル認定IP制限をキャンセルします" ResetIPs: "1パネル認定IP制限をキャンセルします"
ResetDomain: "1パネルドメインバインディングをキャンセルします" ResetDomain: "1パネルドメインバインディングをキャンセルします"
ResetPasskey: "1Panel のパスキーをクリアします" ResetPasskey: "1Panel のパスキーをクリアします"
# コマンドライン - ユーザー
UserList: "1Panel ユーザー一覧を取得します" UserList: "1Panel ユーザー一覧を取得します"
UserTableName: "名前" UserTableName: "名前"
UserTableMFAStatus: "MFA ステータス" UserTableMFAStatus: "MFA ステータス"
UserTableSuperAdmin: "スーパー管理者" UserTableSuperAdmin: "スーパー管理者"
UserTableCreatedAt: "作成日時" UserTableCreatedAt: "作成日時"
UserEmptyList: "ユーザーが見つかりません" UserEmptyList: "ユーザーが見つかりません"
UserInfo: "パネル情報を取得します"
UserInfoAddr: "パネルアドレス: "
UserInfoPassHelp: "ヒント: パスワードを変更するには、コマンドを実行できます。"
# コマンドライン - 復元
RestoreCommands: "1Panel のサービスとデータをロールバック" RestoreCommands: "1Panel のサービスとデータをロールバック"
RestoreNoSuchFile: "ロールバックに使えるファイルが見つかりません" RestoreNoSuchFile: "ロールバックに使えるファイルが見つかりません"
RestoreStep1: "(1/5){{ .name }} ディレクトリから 1Panel のサービスとデータのロールバックを開始しています..." RestoreStep1: "(1/5){{ .name }} ディレクトリから 1Panel のサービスとデータのロールバックを開始しています..."
@@ -275,6 +352,8 @@ RestoreStep3: "(3/5)1Panel スクリプトのロールバックが完了し
RestoreStep4: "(4/5)1Panel サービスのロールバックが完了しました" RestoreStep4: "(4/5)1Panel サービスのロールバックが完了しました"
RestoreStep5: "(5/5)1Panel データのロールバックが完了しました" RestoreStep5: "(5/5)1Panel データのロールバックが完了しました"
RestoreSuccessful: "ロールバックが完了しました。{{ .version }} に戻し、サービスを再起動しています..." RestoreSuccessful: "ロールバックが完了しました。{{ .version }} に戻し、サービスを再起動しています..."
# コマンドライン - 更新
UpdateCommands: "パネル情報を更新します" UpdateCommands: "パネル情報を更新します"
UpdateUser: "ユーザー情報を更新します" UpdateUser: "ユーザー情報を更新します"
UpdatePassword: "ユーザーパスワードを更新します" UpdatePassword: "ユーザーパスワードを更新します"
@@ -301,28 +380,12 @@ UpdatePortResult: "パネルポート: {{ .name }}"
UpdatePortFirewallAdd: "ファイアウォールポートルールの追加に失敗した{{ .err }}、ファイアウォールルールに{{ .name }}ポートを手動で追加してください。" UpdatePortFirewallAdd: "ファイアウォールポートルールの追加に失敗した{{ .err }}、ファイアウォールルールに{{ .name }}ポートを手動で追加してください。"
UpdatePortFirewallDel: "エラー: ファイアウォールポートの削除に失敗しました、{{ .err }}" UpdatePortFirewallDel: "エラー: ファイアウォールポートの削除に失敗しました、{{ .err }}"
UpdatePortFirewallReload: "ファイアウォールのリロードに失敗しました{{ .err }}、ファイアウォールを手動でリロードしてください。" UpdatePortFirewallReload: "ファイアウォールのリロードに失敗しました{{ .err }}、ファイアウォールを手動でリロードしてください。"
UserInfo: "パネル情報を取得します"
UserInfoAddr: "パネルアドレス: "
UserInfoPassHelp: "ヒント: パスワードを変更するには、コマンドを実行できます。"
DBConnErr: "エラー: データベース接続の初期化に失敗しました、{{ .err }}"
SystemVersion: "バージョン: "
SystemMode: "モード: "
#mobile app # モバイルアプリ
ErrVerifyToken: 'トークンの検証エラーです。リセット後、再度QRコードをスキャンしてください。' ErrVerifyToken: 'トークンの検証エラーです。リセット後、再度QRコードをスキャンしてください。'
ErrInvalidToken: '無効なトークンです。リセット後、再度QRコードをスキャンしてください。' ErrInvalidToken: '無効なトークンです。リセット後、再度QRコードをスキャンしてください。'
ErrExpiredToken: 'トークンの有効期限が切れました。リセット後、再度QRコードをスキャンしてください。' ErrExpiredToken: 'トークンの有効期限が切れました。リセット後、再度QRコードをスキャンしてください。'
#cluster # コマンドエクスポート
ErrMasterDelete: "マスターノードを削除できません。スレーブノードを先に削除してください。"
ClusterNameIsExist: "クラスタ名は既に存在します。"
AppStatusUnHealthy: "アプリケーションのステータス取得が異常です。ノードリストでインストールノードのステータスを確認してください。"
MasterNodePortNotAvailable: "ノード {{ .name }} のポート {{ .port }} の接続性検証が失敗しました。ファイアウォール/セキュリティグループの設定とマスターノードのステータスを確認してください。"
ClusterMasterNotExist: "クラスタのマスターノードが切断されています。子ノードを削除してください。"
#ssl
ErrReqFailed: "{{.name}} リクエスト失敗: {{ .err }}"
#command
Name: "名前" Name: "名前"
Command: "コマンド" Command: "コマンド"
+159 -95
View File
@@ -1,68 +1,65 @@
# 기본 오류
ErrInvalidParams: '잘못된 요청: {{ .detail }}' ErrInvalidParams: '잘못된 요청: {{ .detail }}'
ErrTokenParse: '토큰 오류: {{ .detail }}' ErrTokenParse: '토큰 오류: {{ .detail }}'
ErrInitialPassword: '원래 비밀번호가 틀립니다' ErrInitialPassword: '원래 비밀번호가 틀립니다'
ErrInternalServer: '서버 오류: {{ .detail }}' ErrInternalServer: '서버 오류: {{ .detail }}'
ErrInternalServerKey: "서버 내부 오류:"
ErrRecordExist: '레코드가 이미 있습니다' ErrRecordExist: '레코드가 이미 있습니다'
ErrRecordNotFound: '레코드를 찾을 수 없습니다' ErrRecordNotFound: '레코드를 찾을 수 없습니다'
ErrStructTransform: '형 변환 실패: {{ .err }}' ErrStructTransform: '형 변환 실패: {{ .err }}'
ErrNotLogin: '로그인하지 않음: {{ .detail }}'
ErrSessionDataNotFound: "현재 세션이 만료되었습니다"
ErrSessionDataFormat: "현재 세션 데이터 형식이 비정상입니다"
ErrPasswordExpired: '비밀번호 만료: {{ .detail }}'
ErrNotSupportType: '지원하지 않는 타입: {{ .name }}' ErrNotSupportType: '지원하지 않는 타입: {{ .name }}'
ErrProxy: '요청 실패: {{ .detail }}' ErrDemoEnvironment: '데모 환경에서는 불가'
ErrApiConfigStatusInvalid: 'API 사용 중지: {{ .detail }}' ErrCmdTimeout: '명령이 시간 초과했습니다'
ErrApiConfigKeyInvalid: 'API 키가 잘못됨: {{ .detail }}' ErrPortInUsed: "{{ .name }} 포트가 이미 사용 중입니다"
ErrApiConfigIPInvalid: 'IP 허용되지 않음: {{ .detail }}' ErrFileNotFound: "{{ .name }} 파일이 존재하지 않습니다"
ErrApiConfigDisable: 'API 접근 금지: {{ .detail }}' ErrReqFailed: "{{.name}} 요청 실패: {{ .err }}"
ErrApiConfigKeyTimeInvalid: '타임스탬프 오류: {{ .detail }}'
ErrLoginLocked: "실패한 시도가 너무 많습니다. 로그인이 5분 동안 일시적으로 잠겼습니다."
# request # 요청 및 보안 입구
ErrNoSuchHost: "요청한 서버를 찾을 수 없습니다 {{ .err }}" ErrNoSuchHost: "요청한 서버를 찾을 수 없습니다 {{ .err }}"
ErrHttpReqNotFound: "요청한 리소스를 찾을 수 없습니다 {{ .err }}" ErrHttpReqNotFound: "요청한 리소스를 찾을 수 없습니다 {{ .err }}"
ErrHttpReqFailed: "요청 실패 {{ .err }}" ErrHttpReqFailed: "요청 실패 {{ .err }}"
ErrHttpReqTimeOut: "요청 시간이 초과되었습니다 {{ .err }}" ErrHttpReqTimeOut: "요청 시간이 초과되었습니다 {{ .err }}"
ErrCreateHttpClient: "요청 생성 실패 {{ .err }}" ErrCreateHttpClient: "요청 생성 실패 {{ .err }}"
ErrProxy: '요청 실패: {{ .detail }}'
ErrProxySetting: "프록시 서버 정보를 사용할 수 없음 {{ .err }}, 확인 후 다시 시도하세요" ErrProxySetting: "프록시 서버 정보를 사용할 수 없음 {{ .err }}, 확인 후 다시 시도하세요"
ErrEntrance: "보안 정보 오류입니다. 확인 후 다시 시도하십시오"
ErrEntranceFormat: "보안 입구 {{ .name }}은(는) 현재 지원되지 않습니다. 확인 후 다시 시도해 주세요" ErrEntranceFormat: "보안 입구 {{ .name }}은(는) 현재 지원되지 않습니다. 확인 후 다시 시도해 주세요"
# common # 로그인 및 보안
ErrDemoEnvironment: '데모 환경에서는 불가' ErrNotLogin: '로그인하지 않음: {{ .detail }}'
ErrCmdTimeout: '명령이 시간 초과했습니다' ErrSessionDataNotFound: "현재 세션이 만료되었습니다"
ErrEntrance: "보안 정보 오류입니다. 확인 후 다시 시도하십시오" ErrSessionDataFormat: "현재 세션 데이터 형식이 비정상입니다"
ErrPasswordExpired: '비밀번호 만료: {{ .detail }}'
ErrLoginLocked: "실패한 시도가 너무 많습니다. 로그인이 5분 동안 일시적으로 잠겼습니다."
ErrApiConfigStatusInvalid: 'API 사용 중지: {{ .detail }}'
ErrApiConfigKeyInvalid: 'API 키가 잘못됨: {{ .detail }}'
ErrApiConfigIPInvalid: 'IP 허용되지 않음: {{ .detail }}'
ErrApiConfigDisable: 'API 접근 금지: {{ .detail }}'
ErrApiConfigKeyTimeInvalid: '타임스탬프 오류: {{ .detail }}'
ErrPasskeyDisabled: "Passkey를 사용하려면 HTTPS를 활성화해야 합니다"
ErrPasskeyNotConfigured: "Passkey가 구성되지 않았습니다"
ErrPasskeyLimit: "Passkey 개수가 한도에 도달했습니다(최대 5개)"
ErrPasskeySession: "Passkey 세션이 만료되었거나 유효하지 않습니다"
ErrPasskeyDuplicate: "Passkey가 이미 존재합니다"
ErrPasskeyVerify: "Passkey 검증에 실패했습니다"
# 사용자 및 권한
ErrNoSuchUser: "사용자 정보를 찾을 수 없습니다. 확인 후 다시 시도하세요"
ErrToMaster: "이 사용자는 마스터 노드에서 이 작업을 수행할 권한이 없습니다. 확인 후 다시 시도하세요"
ErrToNode: "이 사용자는 이 노드에서 이 작업을 수행할 권한이 없습니다. 확인 후 다시 시도하세요"
ErrRBAC: "사용자 권한이 부족하여 이 작업을 수행할 수 없습니다. 확인 후 다시 시도하세요"
ErrNoneNode: "이 사용자에게는 노드 권한이 없습니다. 관리자에게 문의하거나 확인 후 다시 시도하세요"
ErrOnlySuperAdmin: "슈퍼 관리자만 이 기능을 사용할 수 있습니다"
ErrRolePresetCannotDelete: "시스템 기본 역할은 삭제할 수 없습니다"
ErrRolePresetCannotUpdate: "시스템 기본 역할은 수정할 수 없습니다"
ErrRoleBoundToUser: "이 역할은 이미 사용자에게 연결되어 있어 삭제할 수 없습니다"
ErrRolePresetCannotBind: "시스템 기본 역할은 사용자에게 할당할 수 없습니다"
ErrNodeAdminMasterForbidden: "마스터 노드에는 노드 관리자 권한을 추가할 수 없습니다"
ErrSuperAdminCannotDelete: "슈퍼 관리자 사용자는 삭제할 수 없습니다"
ErrGroupIsDefault: "기본 그룹은 삭제할 수 없습니다" ErrGroupIsDefault: "기본 그룹은 삭제할 수 없습니다"
ErrGroupIsInUse: "그룹이 사용 중이므로 삭제할 수 없습니다." ErrGroupIsInUse: "그룹이 사용 중이므로 삭제할 수 없습니다."
ErrAIProxyUserGroupIsDefault: "기본 사용자 그룹은 삭제할 수 없습니다"
ErrAIProxyUserGroupInUse: "사용자 그룹이 사용 중이므로 삭제할 수 없습니다."
ErrAIProxyUserGroupExists: "사용자 그룹 이름이 이미 존재합니다."
ErrAIProxyBackendAccountExists: "이 모델 계정은 이미 AI 게이트웨이 계정 풀에 가져왔습니다."
ErrAIProxyModelGroupInUse: "모델 그룹이 사용 중이므로 삭제할 수 없습니다."
ErrAIProxyModelGroupExists: "모델 그룹 이름이 이미 존재합니다."
ErrAIProxySensitiveGroupInUse: "민감 단어 그룹이 사용 중이므로 삭제할 수 없습니다."
ErrAIProxySensitiveGroupExists: "민감 단어 그룹 이름이 이미 존재합니다."
ErrLocalDelete: "로컬 노드는 삭제할 수 없습니다"
ErrPortInUsed: "{{ .name }} 포트가 이미 사용 중입니다"
ErrInternalServerKey: "서버 내부 오류:"
MasterNode: "마스터 노드"
# app # 라이선스
CustomAppStoreFileValid: "앱 스토어 패키지는 .tar.gz 형식이어야 합니다"
ErrFileNotFound: "{{ .name }} 파일이 존재하지 않습니다"
AppBackup: '애플리케이션 백업'
AppBackupPush: '애플리케이션 백업 파일 {{.file}}을(를) 노드 {{ .name }}(으)로 전송'
ErrSourceTargetSame: '소스 노드와 대상 노드는 동일할 수 없습니다'
AppInstall: '노드 {{ .targetNode }}에 애플리케이션 {{ .name }} 설치'
AppInstallCheck: '애플리케이션 설치 환경 확인'
# backup
ErrBackupInUsed: '백업 계정이 예약에 사용 중'
ErrBackupCheck: '연결 테스트 실패: {{ .err }}'
ErrBackupLocal: "로컬 서버 백업 계정은 이 작업을 지원하지 않습니다"
ErrBackupPublic: "이 백업 계정이 공개된 것으로 감지되지 않았습니다. 다시 확인하십시오"
ErrOSSConn: "최신 버전을 가져올 수 없습니다. 외부 네트워크 연결을 확인하십시오."
#license
LicenseCheck: '라이선스 사용 가능 여부 확인' LicenseCheck: '라이선스 사용 가능 여부 확인'
ErrLicenseInUsed: '해당 라이선스가 이미 연결되었습니다. 확인 후 다시 시도하세요' ErrLicenseInUsed: '해당 라이선스가 이미 연결되었습니다. 확인 후 다시 시도하세요'
ErrLicenseExpired: '해당 라이선스가 만료되었습니다. 확인 후 다시 시도하세요' ErrLicenseExpired: '해당 라이선스가 만료되었습니다. 확인 후 다시 시도하세요'
@@ -92,21 +89,6 @@ ErrNodeUnbind: "이 노드가 라이선스 바인딩 범위에 있지 않음을
ErrNodeBind: "이 노드가 이미 라이선스에 바인딩되어 있음을 감지하였습니다. 다시 확인하고 시도해 주세요" ErrNodeBind: "이 노드가 이미 라이선스에 바인딩되어 있음을 감지하였습니다. 다시 확인하고 시도해 주세요"
ErrNodeLocalRollback: "마스터 노드는 직접 롤백을 지원하지 않습니다. '1pctl restore'를 수동으로 실행해 롤백하세요" ErrNodeLocalRollback: "마스터 노드는 직접 롤백을 지원하지 않습니다. '1pctl restore'를 수동으로 실행해 롤백하세요"
ErrIntlLicense: "현재 버전에서는 국제판 라이선스 가져오기를 아직 지원하지 않습니다. 곧 제공될 예정입니다" ErrIntlLicense: "현재 버전에서는 국제판 라이선스 가져오기를 아직 지원하지 않습니다. 곧 제공될 예정입니다"
# user
ErrNoSuchUser: "사용자 정보를 찾을 수 없습니다. 확인 후 다시 시도하세요"
ErrToMaster: "이 사용자는 마스터 노드에서 이 작업을 수행할 권한이 없습니다. 확인 후 다시 시도하세요"
ErrToNode: "이 사용자는 이 노드에서 이 작업을 수행할 권한이 없습니다. 확인 후 다시 시도하세요"
ErrRBAC: "사용자 권한이 부족하여 이 작업을 수행할 수 없습니다. 확인 후 다시 시도하세요"
ErrNoneNode: "이 사용자에게는 노드 권한이 없습니다. 관리자에게 문의하거나 확인 후 다시 시도하세요"
ErrOnlySuperAdmin: "슈퍼 관리자만 이 기능을 사용할 수 있습니다"
ErrRolePresetCannotDelete: "시스템 기본 역할은 삭제할 수 없습니다"
ErrRolePresetCannotUpdate: "시스템 기본 역할은 수정할 수 없습니다"
ErrRoleBoundToUser: "이 역할은 이미 사용자에게 연결되어 있어 삭제할 수 없습니다"
ErrRolePresetCannotBind: "시스템 기본 역할은 사용자에게 할당할 수 없습니다"
ErrNodeAdminMasterForbidden: "마스터 노드에는 노드 관리자 권한을 추가할 수 없습니다"
ErrSuperAdminCannotDelete: "슈퍼 관리자 사용자는 삭제할 수 없습니다"
InvalidRequestBodyType: "요청 본문 형식이 잘못되었습니다. 내용이 형식 요구 사항을 충족하는지 확인한 후 다시 시도하세요" InvalidRequestBodyType: "요청 본문 형식이 잘못되었습니다. 내용이 형식 요구 사항을 충족하는지 확인한 후 다시 시도하세요"
InvalidLicenseCodeType: "제공된 라이선스 코드 형식이 잘못되었습니다. 확인 후 다시 시도하세요" InvalidLicenseCodeType: "제공된 라이선스 코드 형식이 잘못되었습니다. 확인 후 다시 시도하세요"
LicenseNotFoundType: "라이선스가 존재하지 않습니다. 시스템에서 제공된 라이선스와 일치하는 기록을 찾을 수 없습니다. 확인 후 다시 시도하세요" LicenseNotFoundType: "라이선스가 존재하지 않습니다. 시스템에서 제공된 라이선스와 일치하는 기록을 찾을 수 없습니다. 확인 후 다시 시도하세요"
@@ -117,10 +99,65 @@ InvalidAssigneeType: "라이선스 할당 대상 사용자 또는 장치 정보
LicenseUsageNotFoundType: "사용 기록이 없습니다. 이 라이선스는 아직 활성화되거나 사용되지 않았습니다. 확인 후 다시 시도하세요" LicenseUsageNotFoundType: "사용 기록이 없습니다. 이 라이선스는 아직 활성화되거나 사용되지 않았습니다. 확인 후 다시 시도하세요"
LicenseUsageLimitExceededType: "이 라이선스는 이미 다른 노드에 연결되었습니다. 확인 후 다시 시도하세요" LicenseUsageLimitExceededType: "이 라이선스는 이미 다른 노드에 연결되었습니다. 확인 후 다시 시도하세요"
# alert # 노드 및 클러스터
MasterNode: "마스터 노드"
Node: "노드"
ErrLocalDelete: "로컬 노드는 삭제할 수 없습니다"
ErrMasterDelete: "마스터 노드를 삭제할 수 없습니다. 슬레이브 노드를 먼저 삭제하세요."
ClusterNameIsExist: "클러스터 이름이 이미 존재합니다."
AppStatusUnHealthy: "애플리케이션 상태 획득이 비정상입니다. 노드 목록에서 설치 노드 상태를 확인하세요."
MasterNodePortNotAvailable: "노드 {{ .name }} 포트 {{ .port }} 연결성 검증에 실패했습니다. 방화벽/보안 그룹 설정 및 마스터 노드 상태를 확인하세요."
ClusterMasterNotExist: "클러스터의 마스터 노드가 연결이 끊어졌습니다. 자식 노드를 삭제하세요."
# 가상 머신
ErrVMNotFound: "가상 머신이 존재하지 않습니다"
ErrVMAlreadyExists: "가상 머신이 이미 존재합니다"
ErrVMStoragePathInUse: "스토리지 풀 경로가 이미 [{{ .name }}]에서 사용 중입니다"
ErrVMRunning: "가상 머신이 실행 중입니다"
ErrVMLibvirtConnect: "libvirt 연결 실패: {{ .detail }}"
ErrVMPermission: "가상 머신 작업 권한이 없습니다: {{ .detail }}"
ErrVMNetworkNotFound: "가상 머신 네트워크가 존재하지 않습니다: {{ .detail }}"
ErrVMInvalidPath: "가상 머신 경로가 유효하지 않습니다: {{ .detail }}"
ErrVMInvalidInput: "가상 머신 매개변수가 유효하지 않습니다: {{ .detail }}"
ErrVMCommandFailed: "가상 머신 명령 실행 실패: {{ .err }}"
VMSnapshotCreateTask: "Create snapshot [{{ .snapshot }}] for virtual machine [{{ .vm }}]"
VMSnapshotCreateStep: "Create virtual machine snapshot [{{ .snapshot }}]"
VMSnapshotRecoverTask: "Recover snapshot [{{ .snapshot }}] for virtual machine [{{ .vm }}]"
VMSnapshotRecoverStep: "Recover virtual machine snapshot [{{ .snapshot }}]"
VMSnapshotDeleteTask: "Delete snapshot [{{ .snapshot }}] for virtual machine [{{ .vm }}]"
VMSnapshotDeleteStep: "Delete virtual machine snapshot [{{ .snapshot }}]"
# 앱
CustomAppStoreFileValid: "앱 스토어 패키지는 .tar.gz 형식이어야 합니다"
AppBackup: '애플리케이션 백업'
AppBackupPush: '애플리케이션 백업 파일 {{.file}}을(를) 노드 {{ .name }}(으)로 전송'
ErrSourceTargetSame: '소스 노드와 대상 노드는 동일할 수 없습니다'
AppInstall: '노드 {{ .targetNode }}에 애플리케이션 {{ .name }} 설치'
AppInstallCheck: '애플리케이션 설치 환경 확인'
# 백업
ErrBackupInUsed: '백업 계정이 예약에 사용 중'
ErrBackupCheck: '연결 테스트 실패: {{ .err }}'
ErrBackupLocal: "로컬 서버 백업 계정은 이 작업을 지원하지 않습니다"
ErrBackupPublic: "이 백업 계정이 공개된 것으로 감지되지 않았습니다. 다시 확인하십시오"
ErrOSSConn: "최신 버전을 가져올 수 없습니다. 외부 네트워크 연결을 확인하십시오."
MvBackup: "데이터를 백업 디렉터리로 이동"
# 알림
ErrAlertSync: "경고 정보 동기화 오류, 다시 확인하고 시도해 주세요" ErrAlertSync: "경고 정보 동기화 오류, 다시 확인하고 시도해 주세요"
#task # AI 게이트웨이
ErrAIProxyUserGroupIsDefault: "기본 사용자 그룹은 삭제할 수 없습니다"
ErrAIProxyUserGroupInUse: "사용자 그룹이 사용 중이므로 삭제할 수 없습니다."
ErrAIProxyUserGroupExists: "사용자 그룹 이름이 이미 존재합니다."
ErrAIProxyBackendAccountExists: "이 모델 계정은 이미 AI 게이트웨이 계정 풀에 가져왔습니다."
ErrAIProxyModelGroupInUse: "모델 그룹이 사용 중이므로 삭제할 수 없습니다."
ErrAIProxyModelGroupExists: "모델 그룹 이름이 이미 존재합니다."
ErrAIProxySensitiveGroupInUse: "민감 단어 그룹이 사용 중이므로 삭제할 수 없습니다."
ErrAIProxySensitiveGroupExists: "민감 단어 그룹 이름이 이미 존재합니다."
AIBenchmarkRun: "AI 벤치마크 실행"
# 작업
TaskStart: "{{ .name }} 작업 시작 [START]" TaskStart: "{{ .name }} 작업 시작 [START]"
TaskEnd: "{{ .name }} 작업 종료 [COMPLETED]" TaskEnd: "{{ .name }} 작업 종료 [COMPLETED]"
TaskFailed: "{{ .name }} 작업 실패" TaskFailed: "{{ .name }} 작업 실패"
@@ -134,6 +171,16 @@ TaskUpgrade: "업그레이드"
TaskSync: '동기화' TaskSync: '동기화'
TaskSyncForNode: "노드 데이터 동기화" TaskSyncForNode: "노드 데이터 동기화"
TaskBackup: "백업" TaskBackup: "백업"
TaskPush: "전송"
TaskRsync: "Sync"
SuccessStatus: "{{ .name }} 성공"
FailedStatus: "{{ .name }} 실패 {{ .err }}"
Start: "시작"
SubTask: "서브 작업"
Skip: "오류 무시하고 계속..."
Success: "성공"
# 에이전트 일괄 작업
BatchInstallAgent: "에이전트 일괄 설치" BatchInstallAgent: "에이전트 일괄 설치"
DispatchAgentInstallTasks: "에이전트 설치 작업 배포" DispatchAgentInstallTasks: "에이전트 설치 작업 배포"
BatchUpgradeAgent: "에이전트 일괄 업그레이드" BatchUpgradeAgent: "에이전트 일괄 업그레이드"
@@ -167,20 +214,15 @@ AgentOperateStart: "시작"
AgentOperateStop: "중지" AgentOperateStop: "중지"
AgentOperateRestart: "재시작" AgentOperateRestart: "재시작"
AgentOperateDelete: "삭제" AgentOperateDelete: "삭제"
SuccessStatus: "{{ .name }} 성공"
FailedStatus: "{{ .name }} 실패 {{ .err }}" # 앱 및 스킬 작업
Start: "시작"
SubTask: "서브 작업"
Skip: "오류 무시하고 계속..."
PushAppInstallTaskToNode: "노드 [{{ .name }}]로 앱 설치 작업 전송" PushAppInstallTaskToNode: "노드 [{{ .name }}]로 앱 설치 작업 전송"
TaskPush: "전송"
AppInstallTask: "앱 설치 작업" AppInstallTask: "앱 설치 작업"
PushAppFailed: "앱 설치 작업 전송 실패" PushAppFailed: "앱 설치 작업 전송 실패"
SkillHubInstallTask: "스킬 설치 [{{ .name }}]" SkillHubInstallTask: "스킬 설치 [{{ .name }}]"
SkillHubInstallToTarget: "대상에 스킬 설치 [{{ .name }}]" SkillHubInstallToTarget: "대상에 스킬 설치 [{{ .name }}]"
Success: "성공"
#script # 스크립트 라이브러리
ScriptLibrary: "스크립트 라이브러리" ScriptLibrary: "스크립트 라이브러리"
RemoteScriptLibrary: "원격 스크립트 라이브러리" RemoteScriptLibrary: "원격 스크립트 라이브러리"
ScriptSyncSkip: "현재 스크립트 라이브러리가 이미 최신 버전입니다" ScriptSyncSkip: "현재 스크립트 라이브러리가 이미 최신 버전입니다"
@@ -188,7 +230,7 @@ DownloadData: "스크립트 라이브러리 파일 data.yaml 다운로드 중"
DownloadPackage: "스크립트 라이브러리 패키지 다운로드 중" DownloadPackage: "스크립트 라이브러리 패키지 다운로드 중"
AnalyticCompletion: "분석 완료, 데이터베이스에 동기화 중..." AnalyticCompletion: "분석 완료, 데이터베이스에 동기화 중..."
Node: "노드" # 노드 동기화
SyncNode: "데이터를 노드 {{ .name }}(으)로 동기화" SyncNode: "데이터를 노드 {{ .name }}(으)로 동기화"
LocalName: "'local' 이름은 시스템 로컬 식별 전용으로 사용됩니다" LocalName: "'local' 이름은 시스템 로컬 식별 전용으로 사용됩니다"
SyncPackageData: "동기화 데이터 패키징" SyncPackageData: "동기화 데이터 패키징"
@@ -204,7 +246,7 @@ SyncCustomApp: "사용자 정의 앱"
SyncLanguage: "시스템 언어" SyncLanguage: "시스템 언어"
SyncEdition: "운영 지역" SyncEdition: "운영 지역"
#upgrade node # 노드 업그레이드
NodeUpgrade: "{{ .name }} 노드 업그레이드" NodeUpgrade: "{{ .name }} 노드 업그레이드"
UpgradeCheck: "노드 업데이트 확인" UpgradeCheck: "노드 업데이트 확인"
UpgradeCheckLocal: "로컬 노드는 일괄 업그레이드를 지원하지 않으므로 건너뜁니다..." UpgradeCheckLocal: "로컬 노드는 일괄 업그레이드를 지원하지 않으므로 건너뜁니다..."
@@ -217,12 +259,11 @@ LoadAutoUpgradeNodesFailed: "자동 업그레이드 노드 로드 실패, 오류
AutoUpgradeNodes: "자동 업그레이드 노드: {{ .nodes }}" AutoUpgradeNodes: "자동 업그레이드 노드: {{ .nodes }}"
UpdateAutoUpgradeNodesStatusFailed: "자동 업그레이드 노드 상태 업데이트 실패, 오류: {{ .err }}" UpdateAutoUpgradeNodesStatusFailed: "자동 업그레이드 노드 상태 업데이트 실패, 오류: {{ .err }}"
#add node # 노드 추가
MasterData: "마스터 노드 데이터" MasterData: "마스터 노드 데이터"
LoadSftpClient: "SFTP 클라이언트 가져오기" LoadSftpClient: "SFTP 클라이언트 가져오기"
PackageMasterData: "마스터 노드 백업 패키지 생성" PackageMasterData: "마스터 노드 백업 패키지 생성"
UploadBackup: "백업 데이터 업로드" UploadBackup: "백업 데이터 업로드"
MvBackup: "데이터를 백업 디렉터리로 이동"
TaskAddNode: "노드 추가" TaskAddNode: "노드 추가"
LoadNodeArch: "노드 아키텍처 정보 가져오기" LoadNodeArch: "노드 아키텍처 정보 가져오기"
LoadNodeArchDetail: "감지된 마스터 노드 아키텍처: {{ .local }}, 자식 노드 아키텍처: {{ .node }}" LoadNodeArchDetail: "감지된 마스터 노드 아키텍처: {{ .local }}, 자식 노드 아키텍처: {{ .node }}"
@@ -235,7 +276,35 @@ SendAgent: "노드 설치 패키지 배포"
StartService: "서비스 시작" StartService: "서비스 시작"
NoBackupNode: "현재 백업 노드가 비어 있습니다. 저장할 백업 노드를 선택한 후 다시 시도하십시오" NoBackupNode: "현재 백업 노드가 비어 있습니다. 저장할 백업 노드를 선택한 후 다시 시도하십시오"
# CMD # 노드 파일 및 이미지 동기화
LocalNodeIpFailed: "Failed to get master node IP. Edit the master node and add IP address and SSH authentication information."
HandlePrivateKey: "Handle node private key"
HandlePublicKey: "Handle node public key"
ExchangeFile: "Start syncing {{ .sourcePath }} from node {{ .source }} to node {{ .dest }}:{{ .destPath }}"
NodeFile: "Node file"
ImageSyncTaskName: "Image sync {{ .count }} images"
SSLSyncTaskName: "Certificate sync {{ .count }} certificates"
AppSyncTaskName: "App sync {{ .name }}"
SSLSyncToNode: "Push certificate [{{ .cert }}] to node [{{ .node }}]"
ImageSyncSave: "Save image {{ .image }}"
ImageSyncSaveTags: "Save image tags {{ .tags }}"
ImageSyncToNode: "Sync image {{ .image }} to node {{ .node }}"
ImageSyncLoad: "Load image {{ .image }} on node {{ .node }}"
ImageSyncClean: "Clean temporary files for image {{ .image }}"
ImageSyncNoTag: "Image {{ .image }} has no tag and will be saved by image ID"
ImageSyncFrontendTagsIgnored: "No tags were found for image {{ .image }} on the source node. Frontend tags were ignored."
ImageSyncHandlePrivateKey: "Handle image sync node private key"
ImageSyncHandlePublicKey: "Handle image sync node public key"
ImageSyncTransfer: "Start transferring image temporary file: {{ .source }}:{{ .sourcePath }} -> {{ .dest }}:{{ .destPath }}"
# 명령줄
SudoHelper: "{{ .cmd }} 명령을 사용하거나 root 사용자로 전환하세요."
UsernameNeed: "Enterprise 버전은 --username을 지정해야 합니다"
DBConnErr: "오류: 데이터베이스 연결 초기화 실패 {{ .err }}"
SystemVersion: "버전: "
SystemMode: "모드: "
# 명령줄 - 앱
AppVersion: "앱 버전" AppVersion: "앱 버전"
AppCommands: "앱 관련 명령어" AppCommands: "앱 관련 명령어"
AppInit: "앱 초기화" AppInit: "앱 초기화"
@@ -247,12 +316,14 @@ AppMissVersion: "앱 버전이 없습니다. -v 옵션으로 지정하세요."
AppVersionExist: "버전이 이미 존재합니다" AppVersionExist: "버전이 이미 존재합니다"
AppCreateSuccessful: "생성 성공" AppCreateSuccessful: "생성 성공"
AppWriteErr: "파일 {{ .name }} 쓰기 실패 {{ .err }}" AppWriteErr: "파일 {{ .name }} 쓰기 실패 {{ .err }}"
SudoHelper: "{{ .cmd }} 명령을 사용하거나 root 사용자로 전환하세요."
UsernameNeed: "Enterprise 버전은 --username을 지정해야 합니다" # 명령줄 - 수신 IP
ListenIPCommands: "IP 변경" ListenIPCommands: "IP 변경"
ListenIPv4: "IPv4 에서 수신 대기" ListenIPv4: "IPv4 에서 수신 대기"
ListenIPv6: "IPv6 에서 수신 대기" ListenIPv6: "IPv6 에서 수신 대기"
ListenChangeSuccessful: "변경 성공 현재 {{ .value }}에서 수신 대기 중입니다." ListenChangeSuccessful: "변경 성공 현재 {{ .value }}에서 수신 대기 중입니다."
# 명령줄 - 재설정
ResetCommands: "시스템 정보 초기화" ResetCommands: "시스템 정보 초기화"
ResetMFA: "1Panel 이중 인증 취소" ResetMFA: "1Panel 이중 인증 취소"
ResetHttps: "1Panel HTTPS 로그인 취소" ResetHttps: "1Panel HTTPS 로그인 취소"
@@ -260,12 +331,19 @@ ResetEntrance: "1Panel 보안 입구 취소"
ResetIPs: "1Panel 허용 IP 제한 취소" ResetIPs: "1Panel 허용 IP 제한 취소"
ResetDomain: "1Panel 도메인 바인딩 취소" ResetDomain: "1Panel 도메인 바인딩 취소"
ResetPasskey: "1Panel 패스키 초기화" ResetPasskey: "1Panel 패스키 초기화"
# 명령줄 - 사용자
UserList: "1Panel 사용자 목록 가져오기" UserList: "1Panel 사용자 목록 가져오기"
UserTableName: "이름" UserTableName: "이름"
UserTableMFAStatus: "MFA 상태" UserTableMFAStatus: "MFA 상태"
UserTableSuperAdmin: "슈퍼 관리자" UserTableSuperAdmin: "슈퍼 관리자"
UserTableCreatedAt: "생성일" UserTableCreatedAt: "생성일"
UserEmptyList: "사용자를 찾을 수 없습니다" UserEmptyList: "사용자를 찾을 수 없습니다"
UserInfo: "패널 정보 가져오기"
UserInfoAddr: "패널 주소: "
UserInfoPassHelp: "팁: 비밀번호를 변경하려면 다음 명령어를 실행할 수 있습니다: "
# 명령줄 - 복원
RestoreCommands: "1Panel 서비스와 데이터를 롤백" RestoreCommands: "1Panel 서비스와 데이터를 롤백"
RestoreNoSuchFile: "롤백 파일을 찾을 수 없습니다" RestoreNoSuchFile: "롤백 파일을 찾을 수 없습니다"
RestoreStep1: "(1/5) {{ .name }} 디렉터리에서 1Panel 서비스와 데이터의 롤백을 시작합니다..." RestoreStep1: "(1/5) {{ .name }} 디렉터리에서 1Panel 서비스와 데이터의 롤백을 시작합니다..."
@@ -274,6 +352,8 @@ RestoreStep3: "(3/5) 1Panel 스크립트 롤백 완료"
RestoreStep4: "(4/5) 1Panel 서비스 롤백 완료" RestoreStep4: "(4/5) 1Panel 서비스 롤백 완료"
RestoreStep5: "(5/5) 1Panel 데이터 롤백 완료" RestoreStep5: "(5/5) 1Panel 데이터 롤백 완료"
RestoreSuccessful: "롤백이 완료되었습니다. {{ .version }}(으)로 되돌리고 서비스를 다시 시작합니다..." RestoreSuccessful: "롤백이 완료되었습니다. {{ .version }}(으)로 되돌리고 서비스를 다시 시작합니다..."
# 명령줄 - 업데이트
UpdateCommands: "패널 정보 업데이트" UpdateCommands: "패널 정보 업데이트"
UpdateUser: "사용자 정보 업데이트" UpdateUser: "사용자 정보 업데이트"
UpdatePassword: "사용자 비밀번호 업데이트" UpdatePassword: "사용자 비밀번호 업데이트"
@@ -300,28 +380,12 @@ UpdatePortResult: "패널 포트: {{ .name }}"
UpdatePortFirewallAdd: "방화벽 포트 규칙 추가 실패 {{ .err }}, 방화벽 규칙에 {{ .name }} 포트를 수동으로 추가하세요." UpdatePortFirewallAdd: "방화벽 포트 규칙 추가 실패 {{ .err }}, 방화벽 규칙에 {{ .name }} 포트를 수동으로 추가하세요."
UpdatePortFirewallDel: "오류: 방화벽 포트 삭제 실패 {{ .err }}" UpdatePortFirewallDel: "오류: 방화벽 포트 삭제 실패 {{ .err }}"
UpdatePortFirewallReload: "방화벽 다시 로드 실패 {{ .err }}, 방화벽을 수동으로 다시 로드하세요." UpdatePortFirewallReload: "방화벽 다시 로드 실패 {{ .err }}, 방화벽을 수동으로 다시 로드하세요."
UserInfo: "패널 정보 가져오기"
UserInfoAddr: "패널 주소: "
UserInfoPassHelp: "팁: 비밀번호를 변경하려면 다음 명령어를 실행할 수 있습니다: "
DBConnErr: "오류: 데이터베이스 연결 초기화 실패 {{ .err }}"
SystemVersion: "버전: "
SystemMode: "모드: "
#mobile app # 모바일 앱
ErrVerifyToken: '토큰 검증 오류가 발생했습니다. 재설정 후 다시 스캔해 주세요.' ErrVerifyToken: '토큰 검증 오류가 발생했습니다. 재설정 후 다시 스캔해 주세요.'
ErrInvalidToken: '유효하지 않은 토큰입니다. 재설정 후 다시 스캔해 주세요.' ErrInvalidToken: '유효하지 않은 토큰입니다. 재설정 후 다시 스캔해 주세요.'
ErrExpiredToken: '토큰이 만료되었습니다. 재설정 후 다시 스캔해 주세요.' ErrExpiredToken: '토큰이 만료되었습니다. 재설정 후 다시 스캔해 주세요.'
#cluster # 명령 내보내기
ErrMasterDelete: "마스터 노드를 삭제할 수 없습니다. 슬레이브 노드를 먼저 삭제하세요."
ClusterNameIsExist: "클러스터 이름이 이미 존재합니다."
AppStatusUnHealthy: "애플리케이션 상태 획득이 비정상입니다. 노드 목록에서 설치 노드 상태를 확인하세요."
MasterNodePortNotAvailable: "노드 {{ .name }} 포트 {{ .port }} 연결성 검증에 실패했습니다. 방화벽/보안 그룹 설정 및 마스터 노드 상태를 확인하세요."
ClusterMasterNotExist: "클러스터의 마스터 노드가 연결이 끊어졌습니다. 자식 노드를 삭제하세요."
#ssl
ErrReqFailed: "{{.name}} 요청 실패: {{ .err }}"
#command
Name: "이름" Name: "이름"
Command: "명령어" Command: "명령어"
+180 -106
View File
@@ -1,94 +1,49 @@
# ralat asas
ErrInvalidParams: 'Permintaan tidak sah: {{ .detail }}' ErrInvalidParams: 'Permintaan tidak sah: {{ .detail }}'
ErrTokenParse: 'Token tidak sah: {{ .detail }}' ErrTokenParse: 'Token tidak sah: {{ .detail }}'
ErrInitialPassword: 'Kata laluan asal salah' ErrInitialPassword: 'Kata laluan asal salah'
ErrInternalServer: 'Ralat pelayan: {{ .detail }}' ErrInternalServer: 'Ralat pelayan: {{ .detail }}'
ErrInternalServerKey: "Ralat dalaman pelayan:"
ErrRecordExist: 'Rekod sudah wujud' ErrRecordExist: 'Rekod sudah wujud'
ErrRecordNotFound: 'Rekod tidak ditemui' ErrRecordNotFound: 'Rekod tidak ditemui'
ErrStructTransform: 'Ralat penukaran: {{ .err }}' ErrStructTransform: 'Ralat penukaran: {{ .err }}'
ErrNotLogin: 'Belum log masuk: {{ .detail }}'
ErrSessionDataNotFound: "Sesi semasa telah tamat tempoh"
ErrSessionDataFormat: "Format data sesi semasa tidak normal"
ErrPasswordExpired: 'Kata laluan tamat: {{ .detail }}'
ErrNotSupportType: 'Jenis tidak disokong: {{ .name }}' ErrNotSupportType: 'Jenis tidak disokong: {{ .name }}'
ErrProxy: 'Permintaan gagal: {{ .detail }}' ErrDemoEnvironment: 'Tidak tersedia dalam demo'
ErrApiConfigStatusInvalid: 'API dilumpuhkan: {{ .detail }}' ErrCmdTimeout: 'Arahan tamat masa'
ErrApiConfigKeyInvalid: 'Kunci API tidak sah: {{ .detail }}' ErrPortInUsed: "Port {{ .name }} telah digunakan"
ErrApiConfigIPInvalid: 'IP tidak dibenarkan: {{ .detail }}' ErrFileNotFound: "Fail {{ .name }} tidak wujud"
ErrApiConfigDisable: 'API tidak dibenarkan: {{ .detail }}' ErrReqFailed: "{{.name}} permintaan gagal: {{ .err }}"
ErrApiConfigKeyTimeInvalid: 'Cap masa tidak sah: {{ .detail }}'
ErrLoginLocked: "Terlalu banyak percubaan gagal. Log masuk dikunci sementara selama 5 minit."
# request # permintaan dan pintu masuk keselamatan
ErrNoSuchHost: "Pelayan yang diminta tidak dapat ditemui {{ .err }}" ErrNoSuchHost: "Pelayan yang diminta tidak dapat ditemui {{ .err }}"
ErrHttpReqNotFound: "Sumber yang diminta tidak dapat ditemui {{ .err }}" ErrHttpReqNotFound: "Sumber yang diminta tidak dapat ditemui {{ .err }}"
ErrHttpReqFailed: "Permintaan gagal {{ .err }}" ErrHttpReqFailed: "Permintaan gagal {{ .err }}"
ErrHttpReqTimeOut: "Permintaan telah tamat masa {{ .err }}" ErrHttpReqTimeOut: "Permintaan telah tamat masa {{ .err }}"
ErrCreateHttpClient: "Gagal mencipta permintaan {{ .err }}" ErrCreateHttpClient: "Gagal mencipta permintaan {{ .err }}"
ErrProxy: 'Permintaan gagal: {{ .detail }}'
ErrProxySetting: "Maklumat pelayan proksi tidak tersedia {{ .err }}, sila periksa dan cuba lagi" ErrProxySetting: "Maklumat pelayan proksi tidak tersedia {{ .err }}, sila periksa dan cuba lagi"
ErrEntrance: "Maklumat pintu masuk keselamatan salah, sila periksa dan cuba lagi"
ErrEntranceFormat: "Pintu masuk keselamatan {{ .name }} tidak disokong buat masa ini. Sila periksa dan cuba lagi" ErrEntranceFormat: "Pintu masuk keselamatan {{ .name }} tidak disokong buat masa ini. Sila periksa dan cuba lagi"
# common # log masuk dan keselamatan
ErrDemoEnvironment: 'Tidak tersedia dalam demo' ErrNotLogin: 'Belum log masuk: {{ .detail }}'
ErrCmdTimeout: 'Arahan tamat masa' ErrSessionDataNotFound: "Sesi semasa telah tamat tempoh"
ErrEntrance: "Maklumat pintu masuk keselamatan salah, sila periksa dan cuba lagi" ErrSessionDataFormat: "Format data sesi semasa tidak normal"
ErrGroupIsDefault: "Kumpulan lalai tidak boleh dihapuskan" ErrPasswordExpired: 'Kata laluan tamat: {{ .detail }}'
ErrGroupIsInUse: "Kumpulan sedang digunakan dan tidak boleh dipadam." ErrLoginLocked: "Terlalu banyak percubaan gagal. Log masuk dikunci sementara selama 5 minit."
ErrAIProxyUserGroupIsDefault: "Kumpulan pengguna lalai tidak boleh dipadam." ErrApiConfigStatusInvalid: 'API dilumpuhkan: {{ .detail }}'
ErrAIProxyUserGroupInUse: "Kumpulan pengguna sedang digunakan dan tidak boleh dipadam." ErrApiConfigKeyInvalid: 'Kunci API tidak sah: {{ .detail }}'
ErrAIProxyUserGroupExists: "Nama kumpulan pengguna sudah wujud." ErrApiConfigIPInvalid: 'IP tidak dibenarkan: {{ .detail }}'
ErrAIProxyBackendAccountExists: "Akaun model ini telah diimport ke dalam kolam akaun AI Gateway." ErrApiConfigDisable: 'API tidak dibenarkan: {{ .detail }}'
ErrAIProxyModelGroupInUse: "Kumpulan model sedang digunakan dan tidak boleh dipadam." ErrApiConfigKeyTimeInvalid: 'Cap masa tidak sah: {{ .detail }}'
ErrAIProxyModelGroupExists: "Nama kumpulan model sudah wujud." ErrPasskeyDisabled: "Passkey memerlukan HTTPS diaktifkan"
ErrAIProxySensitiveGroupInUse: "Kumpulan kata sensitif sedang digunakan dan tidak boleh dipadam." ErrPasskeyNotConfigured: "Tiada Passkey dikonfigurasikan"
ErrAIProxySensitiveGroupExists: "Nama kumpulan kata sensitif sudah wujud." ErrPasskeyLimit: "Had Passkey telah dicapai (maksimum 5)"
ErrLocalDelete: "Nod tempatan tidak boleh dihapuskan" ErrPasskeySession: "Sesi Passkey telah tamat tempoh atau tidak sah"
ErrPortInUsed: "Port {{ .name }} telah digunakan" ErrPasskeyDuplicate: "Passkey sudah wujud"
ErrInternalServerKey: "Ralat dalaman pelayan:" ErrPasskeyVerify: "Pengesahan Passkey gagal"
MasterNode: "Nod Induk"
# app # pengguna dan kebenaran
CustomAppStoreFileValid: "Pakej stor aplikasi perlu dalam format .tar.gz"
ErrFileNotFound: "Fail {{ .name }} tidak wujud"
# backup
ErrBackupInUsed: 'Akaun sandaran sedang digunakan oleh tugas'
ErrBackupCheck: 'Ujian sambungan gagal: {{ .err }}'
ErrBackupLocal: "Akaun sandaran pelayan tempatan tidak menyokong operasi ini"
ErrBackupPublic: "Akaun sandaran ini dikesan tidak awam, sila semak semula dan cuba lagi"
ErrOSSConn: "Tidak dapat mendapatkan versi terkini, sila semak sambungan rangkaian luar pelayan."
#license
LicenseCheck: 'Periksa sama ada lesen tersedia'
ErrLicenseInUsed: 'Lesen ini telah terikat. Sila periksa dan cuba lagi'
ErrLicenseExpired: 'Lesen ini telah tamat tempoh. Sila periksa dan cuba lagi'
ErrLicense: "Format lesen tidak sah, sila semak dan cuba lagi"
ErrLicenseCheck: "Pengesahan lesen gagal, sila semak dan cuba lagi"
ErrXpackVersion: "Pengesahan lesen gagal, lesen ini terhad kepada versi tertentu, sila semak dan cuba lagi"
ErrLicenseSave: "Gagal menyimpan maklumat lesen {{ .err }}, sila cuba lagi"
ErrLicenseSync: "Penyelarasan maklumat lesen gagal, maklumat lesen tidak ditemui dalam pangkalan data"
ErrLicenseExist: "Rekod lesen ini sudah wujud. Anda boleh terus ke halaman lesen untuk mengikat nod."
ErrXpackNotFound: "Bahagian ini memerlukan Edisi Business. Import lesen di Tetapan Panel > Lesen"
ErrXpackExceptional: "Bahagian ini memerlukan Edisi Business. Segerakkan status lesen di Tetapan Panel > Lesen"
ErrXpackLost: "Lesen telah mencapai had percubaan semula. Pergi ke Tetapan Panel > Lesen dan jalankan penyelarasan manual"
ErrDeviceLost: "Fail yang diperlukan untuk pengesahan lesen hilang, sila semak dan cuba lagi"
ErrDeviceErr: "Persekitaran semasa tidak sepadan dengan persekitaran import lesen. Sila edit lesen dan import semula"
ErrXpackTimeout: "Permintaan tamat masa, sambungan rangkaian mungkin tidak stabil, sila cuba lagi kemudian"
ErrUnbindMaster: "Terdapat nod dalam pengurusan nod, sila keluarkan dahulu dan cuba lagi"
ErrEnterpriseLicenseRequired: "Lesen Edisi Enterprise belum diimport. Sila import lesen terlebih dahulu"
ErrFreeNodeLimit: "Bilangan nod yang boleh ditambah telah mencapai had. Sila beli dan cuba lagi."
ErrNodeBound: "Lesen ini telah diikat dengan nod lain, sila semak dan cuba lagi"
ErrNodeBoundDelete: "Lisensi ini telah diikat dan tidak menyokong operasi penghapusan. Sila semak dan cuba lagi"
ErrNodeBoundLimit: "Nod percuma semasa telah mencapai had, sila semak dan cuba lagi"
ErrLicenseFree: "Nod percuma hanya boleh digunakan apabila lesen terikat dengan betul pada nod. Sila semak dan cuba lagi"
ErrLicenseUnbind: "Lesen ini masih terikat pada nod Edisi Community. Nyahikat di Tetapan Panel > Lesen dan cuba lagi"
ErrLicenseBindCount: "Bilangan nod percuma lesen baharu kurang daripada bilangan nod Edisi Community yang sedang terikat. Sila semak dan cuba lagi"
ErrNoSuchNode: "Maklumat nod tidak ditemui, sila semak dan cuba lagi"
ErrNodeUnbind: "Nod di luar skop lesen dikesan, sila semak dan cuba lagi"
ErrNodeBind: "Nod ini telah diikat dengan lesen, sila semak dan cuba lagi"
ErrNodeLocalRollback: "Nod utama tidak menyokong rollback secara langsung. Jalankan '1pctl restore' secara manual untuk rollback"
ErrIntlLicense: "Versi semasa belum menyokong import lesen edisi antarabangsa. Nantikan"
# user
ErrNoSuchUser: "Maklumat pengguna tidak ditemui, sila semak dan cuba lagi" ErrNoSuchUser: "Maklumat pengguna tidak ditemui, sila semak dan cuba lagi"
ErrToMaster: "Pengguna ini tiada kebenaran untuk melakukan operasi ini pada nod utama, sila semak dan cuba lagi" ErrToMaster: "Pengguna ini tiada kebenaran untuk melakukan operasi ini pada nod utama, sila semak dan cuba lagi"
ErrToNode: "Pengguna ini tiada kebenaran untuk melakukan operasi ini pada nod ini, sila semak dan cuba lagi" ErrToNode: "Pengguna ini tiada kebenaran untuk melakukan operasi ini pada nod ini, sila semak dan cuba lagi"
@@ -101,7 +56,39 @@ ErrRoleBoundToUser: "Peranan ini sudah terikat kepada pengguna dan tidak boleh d
ErrRolePresetCannotBind: "Peranan pratetap sistem tidak boleh diberikan kepada pengguna" ErrRolePresetCannotBind: "Peranan pratetap sistem tidak boleh diberikan kepada pengguna"
ErrNodeAdminMasterForbidden: "Kebenaran Pentadbir Nod tidak boleh ditambah pada nod utama" ErrNodeAdminMasterForbidden: "Kebenaran Pentadbir Nod tidak boleh ditambah pada nod utama"
ErrSuperAdminCannotDelete: "Pengguna super admin tidak boleh dipadam" ErrSuperAdminCannotDelete: "Pengguna super admin tidak boleh dipadam"
ErrGroupIsDefault: "Kumpulan lalai tidak boleh dihapuskan"
ErrGroupIsInUse: "Kumpulan sedang digunakan dan tidak boleh dipadam."
# lesen
LicenseCheck: 'Periksa sama ada lesen tersedia'
ErrLicenseInUsed: 'Lesen ini telah terikat. Sila periksa dan cuba lagi'
ErrLicenseExpired: 'Lesen ini telah tamat tempoh. Sila periksa dan cuba lagi'
ErrLicense: "Format lesen tidak sah, sila semak dan cuba lagi"
ErrLicenseCheck: "Pengesahan lesen gagal, sila semak dan cuba lagi"
ErrXpackVersion: "Pengesahan lesen gagal, lesen ini terhad kepada versi tertentu, sila semak dan cuba lagi"
ErrLicenseSave: "Gagal menyimpan maklumat lesen {{ .err }}, sila cuba lagi"
ErrLicenseSync: "Penyelarasan maklumat lesen gagal, maklumat lesen tidak ditemui dalam pangkalan data"
ErrLicenseExist: "Rekod lesen ini sudah wujud. Anda boleh terus ke halaman lesen untuk mengikat nod."
ErrXpackNotFound: "Bahagian ini memerlukan Edisi Business. Import lesen di Tetapan Panel > Lesen"
ErrXpackExceptional: "Bahagian ini memerlukan Edisi Business. Segerakkan status lesen di Tetapan Panel > Lesen"
ErrXpackLost: "Lesen telah mencapai had percubaan semula. Pergi ke Tetapan Panel > Lesen dan jalankan penyelarasan manual"
ErrEnterpriseLicenseRequired: "Lesen Edisi Enterprise belum diimport. Sila import lesen terlebih dahulu"
ErrDeviceLost: "Fail yang diperlukan untuk pengesahan lesen hilang, sila semak dan cuba lagi"
ErrDeviceErr: "Persekitaran semasa tidak sepadan dengan persekitaran import lesen. Sila edit lesen dan import semula"
ErrXpackTimeout: "Permintaan tamat masa, sambungan rangkaian mungkin tidak stabil, sila cuba lagi kemudian"
ErrUnbindMaster: "Terdapat nod dalam pengurusan nod, sila keluarkan dahulu dan cuba lagi"
ErrFreeNodeLimit: "Bilangan nod yang boleh ditambah telah mencapai had. Sila beli dan cuba lagi."
ErrNodeBound: "Lesen ini telah diikat dengan nod lain, sila semak dan cuba lagi"
ErrNodeBoundDelete: "Lisensi ini telah diikat dan tidak menyokong operasi penghapusan. Sila semak dan cuba lagi"
ErrNodeBoundLimit: "Nod percuma semasa telah mencapai had, sila semak dan cuba lagi"
ErrLicenseFree: "Nod percuma hanya boleh digunakan apabila lesen terikat dengan betul pada nod. Sila semak dan cuba lagi"
ErrLicenseUnbind: "Lesen ini masih terikat pada nod Edisi Community. Nyahikat di Tetapan Panel > Lesen dan cuba lagi"
ErrLicenseBindCount: "Bilangan nod percuma lesen baharu kurang daripada bilangan nod Edisi Community yang sedang terikat. Sila semak dan cuba lagi"
ErrNoSuchNode: "Maklumat nod tidak ditemui, sila semak dan cuba lagi"
ErrNodeUnbind: "Nod di luar skop lesen dikesan, sila semak dan cuba lagi"
ErrNodeBind: "Nod ini telah diikat dengan lesen, sila semak dan cuba lagi"
ErrNodeLocalRollback: "Nod utama tidak menyokong rollback secara langsung. Jalankan '1pctl restore' secara manual untuk rollback"
ErrIntlLicense: "Versi semasa belum menyokong import lesen edisi antarabangsa. Nantikan"
InvalidRequestBodyType: "Format badan permintaan tidak sah, sila periksa dan pastikan kandungan memenuhi format yang diperlukan sebelum mencuba semula" InvalidRequestBodyType: "Format badan permintaan tidak sah, sila periksa dan pastikan kandungan memenuhi format yang diperlukan sebelum mencuba semula"
InvalidLicenseCodeType: "Format kod lesen yang diberikan tidak sah, sila periksa dan cuba lagi" InvalidLicenseCodeType: "Format kod lesen yang diberikan tidak sah, sila periksa dan cuba lagi"
LicenseNotFoundType: "Lesen tidak dijumpai, tiada rekod yang sepadan dengan lesen yang diberikan dalam sistem. Sila periksa dan cuba lagi" LicenseNotFoundType: "Lesen tidak dijumpai, tiada rekod yang sepadan dengan lesen yang diberikan dalam sistem. Sila periksa dan cuba lagi"
@@ -112,10 +99,65 @@ InvalidAssigneeType: "Maklumat pengguna atau peranti sasaran untuk penugasan les
LicenseUsageNotFoundType: "Tiada rekod penggunaan dijumpai. Lesen ini belum diaktifkan atau digunakan. Sila periksa dan cuba lagi" LicenseUsageNotFoundType: "Tiada rekod penggunaan dijumpai. Lesen ini belum diaktifkan atau digunakan. Sila periksa dan cuba lagi"
LicenseUsageLimitExceededType: "Lesen ini sudah terikat pada nod lain. Sila periksa dan cuba lagi" LicenseUsageLimitExceededType: "Lesen ini sudah terikat pada nod lain. Sila periksa dan cuba lagi"
# alert # nod dan kluster
MasterNode: "Nod Induk"
Node: "Nod"
ErrLocalDelete: "Nod tempatan tidak boleh dihapuskan"
ErrMasterDelete: "Tidak dapat menghapus nod utama, sila hapuskan nod perantara dahulu."
ClusterNameIsExist: "Nama kluster sudah wujud."
AppStatusUnHealthy: "Pengambilan status aplikasi tidak normal, sila periksa status nod pemasangan dalam senarai nod."
MasterNodePortNotAvailable: "Pengesahan kesambungan pelabuhan {{ .name }} nod {{ .port }} gagal, sila periksa tetapan firewall/kumpulan keselamatan dan status nod utama."
ClusterMasterNotExist: "Node utama kluster terputus, sila padamkan nod anak."
# mesin maya
ErrVMNotFound: "Mesin maya tidak wujud"
ErrVMAlreadyExists: "Mesin maya sudah wujud"
ErrVMStoragePathInUse: "Laluan kolam storan sudah digunakan oleh [{{ .name }}]"
ErrVMRunning: "Mesin maya sedang berjalan"
ErrVMLibvirtConnect: "Gagal menyambung ke libvirt: {{ .detail }}"
ErrVMPermission: "Tiada kebenaran untuk mengendalikan mesin maya: {{ .detail }}"
ErrVMNetworkNotFound: "Rangkaian mesin maya tidak wujud: {{ .detail }}"
ErrVMInvalidPath: "Laluan mesin maya tidak sah: {{ .detail }}"
ErrVMInvalidInput: "Parameter mesin maya tidak sah: {{ .detail }}"
ErrVMCommandFailed: "Arahan mesin maya gagal: {{ .err }}"
VMSnapshotCreateTask: "Create snapshot [{{ .snapshot }}] for virtual machine [{{ .vm }}]"
VMSnapshotCreateStep: "Create virtual machine snapshot [{{ .snapshot }}]"
VMSnapshotRecoverTask: "Recover snapshot [{{ .snapshot }}] for virtual machine [{{ .vm }}]"
VMSnapshotRecoverStep: "Recover virtual machine snapshot [{{ .snapshot }}]"
VMSnapshotDeleteTask: "Delete snapshot [{{ .snapshot }}] for virtual machine [{{ .vm }}]"
VMSnapshotDeleteStep: "Delete virtual machine snapshot [{{ .snapshot }}]"
# aplikasi
CustomAppStoreFileValid: "Pakej stor aplikasi perlu dalam format .tar.gz"
AppBackup: "Sandaran aplikasi"
AppBackupPush: "Pindahkan fail sandaran aplikasi {{.file}} ke nod {{ .name }}"
ErrSourceTargetSame: "Nod sumber dan nod sasaran tidak boleh sama!"
AppInstall: "Pasang aplikasi {{ .name }} pada nod {{ .targetNode }}"
AppInstallCheck: "Semak persekitaran pemasangan aplikasi"
# sandaran
ErrBackupInUsed: 'Akaun sandaran sedang digunakan oleh tugas'
ErrBackupCheck: 'Ujian sambungan gagal: {{ .err }}'
ErrBackupLocal: "Akaun sandaran pelayan tempatan tidak menyokong operasi ini"
ErrBackupPublic: "Akaun sandaran ini dikesan tidak awam, sila semak semula dan cuba lagi"
ErrOSSConn: "Tidak dapat mendapatkan versi terkini, sila semak sambungan rangkaian luar pelayan."
MvBackup: "Alihkan data ke direktori sandaran"
# amaran
ErrAlertSync: "Ralat penyinkronan maklumat amaran, sila semak dan cuba lagi" ErrAlertSync: "Ralat penyinkronan maklumat amaran, sila semak dan cuba lagi"
#task # gerbang AI
ErrAIProxyUserGroupIsDefault: "Kumpulan pengguna lalai tidak boleh dipadam."
ErrAIProxyUserGroupInUse: "Kumpulan pengguna sedang digunakan dan tidak boleh dipadam."
ErrAIProxyUserGroupExists: "Nama kumpulan pengguna sudah wujud."
ErrAIProxyBackendAccountExists: "Akaun model ini telah diimport ke dalam kolam akaun AI Gateway."
ErrAIProxyModelGroupInUse: "Kumpulan model sedang digunakan dan tidak boleh dipadam."
ErrAIProxyModelGroupExists: "Nama kumpulan model sudah wujud."
ErrAIProxySensitiveGroupInUse: "Kumpulan kata sensitif sedang digunakan dan tidak boleh dipadam."
ErrAIProxySensitiveGroupExists: "Nama kumpulan kata sensitif sudah wujud."
AIBenchmarkRun: "Jalankan penanda aras AI"
# tugas
TaskStart: "{{ .name }} tugas bermula [START]" TaskStart: "{{ .name }} tugas bermula [START]"
TaskEnd: "{{ .name }} tugas tamat [COMPLETED]" TaskEnd: "{{ .name }} tugas tamat [COMPLETED]"
TaskFailed: "{{ .name }} tugas gagal" TaskFailed: "{{ .name }} tugas gagal"
@@ -129,6 +171,16 @@ TaskUpgrade: "Kemas kini"
TaskSync: 'Selaraskan' TaskSync: 'Selaraskan'
TaskSyncForNode: "Segerakan Data Nod" TaskSyncForNode: "Segerakan Data Nod"
TaskBackup: "Sandaran" TaskBackup: "Sandaran"
TaskPush: "Hantar"
TaskRsync: "Sync"
SuccessStatus: "{{ .name }} berjaya"
FailedStatus: "{{ .name }} gagal {{ .err }}"
Start: "Mula"
SubTask: "Tugas Sub"
Skip: "Abaikan ralat dan teruskan..."
Success: "Berjaya"
# tugas kelompok ejen
BatchInstallAgent: "Pasang ejen secara pukal" BatchInstallAgent: "Pasang ejen secara pukal"
DispatchAgentInstallTasks: "Hantar tugas pemasangan ejen" DispatchAgentInstallTasks: "Hantar tugas pemasangan ejen"
BatchUpgradeAgent: "Naik taraf ejen secara pukal" BatchUpgradeAgent: "Naik taraf ejen secara pukal"
@@ -162,20 +214,15 @@ AgentOperateStart: "Mula"
AgentOperateStop: "Henti" AgentOperateStop: "Henti"
AgentOperateRestart: "Mula semula" AgentOperateRestart: "Mula semula"
AgentOperateDelete: "Padam" AgentOperateDelete: "Padam"
SuccessStatus: "{{ .name }} berjaya"
FailedStatus: "{{ .name }} gagal {{ .err }}" # tugas aplikasi dan kemahiran
Start: "Mula"
SubTask: "Tugas Sub"
Skip: "Abaikan ralat dan teruskan..."
PushAppInstallTaskToNode: "Hantar tugas pemasangan aplikasi ke nod [{{ .name }}]" PushAppInstallTaskToNode: "Hantar tugas pemasangan aplikasi ke nod [{{ .name }}]"
TaskPush: "Hantar"
AppInstallTask: "Tugas pemasangan aplikasi" AppInstallTask: "Tugas pemasangan aplikasi"
PushAppFailed: "Gagal menghantar tugas pemasangan aplikasi" PushAppFailed: "Gagal menghantar tugas pemasangan aplikasi"
SkillHubInstallTask: "Pasang kemahiran [{{ .name }}]" SkillHubInstallTask: "Pasang kemahiran [{{ .name }}]"
SkillHubInstallToTarget: "Pasang kemahiran ke sasaran [{{ .name }}]" SkillHubInstallToTarget: "Pasang kemahiran ke sasaran [{{ .name }}]"
Success: "Berjaya"
#script # pustaka skrip
ScriptLibrary: "Pustaka Skrip" ScriptLibrary: "Pustaka Skrip"
RemoteScriptLibrary: "Pustaka Skrip Jauh" RemoteScriptLibrary: "Pustaka Skrip Jauh"
ScriptSyncSkip: "Pustaka skrip semasa sudah versi terkini" ScriptSyncSkip: "Pustaka skrip semasa sudah versi terkini"
@@ -183,7 +230,7 @@ DownloadData: "Muat turun fail pustaka skrip data.yaml"
DownloadPackage: "Muat turun pakej pustaka skrip" DownloadPackage: "Muat turun pakej pustaka skrip"
AnalyticCompletion: "Analisis selesai, sedang menyegerakkan ke pangkalan data..." AnalyticCompletion: "Analisis selesai, sedang menyegerakkan ke pangkalan data..."
Node: "Nod" # penyegerakan nod
SyncNode: "Selaraskan data ke nod {{ .name }}" SyncNode: "Selaraskan data ke nod {{ .name }}"
LocalName: "Nama 'local' hanya digunakan untuk pengenalpastian tempatan sistem" LocalName: "Nama 'local' hanya digunakan untuk pengenalpastian tempatan sistem"
SyncPackageData: "Pakej data segerak" SyncPackageData: "Pakej data segerak"
@@ -199,7 +246,7 @@ SyncCustomApp: "Aplikasi Tersuai"
SyncLanguage: "Bahasa Sistem" SyncLanguage: "Bahasa Sistem"
SyncEdition: "Wilayah Operasi" SyncEdition: "Wilayah Operasi"
#upgrade node # naik taraf nod
NodeUpgrade: "Naik taraf node {{ .name }}" NodeUpgrade: "Naik taraf node {{ .name }}"
UpgradeCheck: "Periksa kemas kini nod" UpgradeCheck: "Periksa kemas kini nod"
UpgradeCheckLocal: "Nod tempatan tidak menyokong peningkatan kelompok, dilangkau..." UpgradeCheckLocal: "Nod tempatan tidak menyokong peningkatan kelompok, dilangkau..."
@@ -212,12 +259,11 @@ LoadAutoUpgradeNodesFailed: "Gagal memuatkan nod naik taraf automatik, ralat: {{
AutoUpgradeNodes: "Nod naik taraf automatik: {{ .nodes }}" AutoUpgradeNodes: "Nod naik taraf automatik: {{ .nodes }}"
UpdateAutoUpgradeNodesStatusFailed: "Gagal mengemas kini status nod naik taraf automatik, ralat: {{ .err }}" UpdateAutoUpgradeNodesStatusFailed: "Gagal mengemas kini status nod naik taraf automatik, ralat: {{ .err }}"
#add node # tambah nod
MasterData: "Data Nod Master" MasterData: "Data Nod Master"
LoadSftpClient: "Dapatkan Klien SFTP" LoadSftpClient: "Dapatkan Klien SFTP"
PackageMasterData: "Hasilkan pakej sandaran nod master" PackageMasterData: "Hasilkan pakej sandaran nod master"
UploadBackup: "Muat naik data sandaran" UploadBackup: "Muat naik data sandaran"
MvBackup: "Alihkan data ke direktori sandaran"
TaskAddNode: "Tambah nod" TaskAddNode: "Tambah nod"
LoadNodeArch: "Dapatkan maklumat seni bina nod" LoadNodeArch: "Dapatkan maklumat seni bina nod"
LoadNodeArchDetail: "Mengesan seni bina nod induk: {{ .local }}, seni bina nod anak: {{ .node }}" LoadNodeArchDetail: "Mengesan seni bina nod induk: {{ .local }}, seni bina nod anak: {{ .node }}"
@@ -230,7 +276,35 @@ SendAgent: "Muat naik pakej pemasangan nod"
StartService: "Mulakan perkhidmatan" StartService: "Mulakan perkhidmatan"
NoBackupNode: "Nod sandaran kosong. Sila pilih nod sandaran untuk disimpan dan cuba lagi" NoBackupNode: "Nod sandaran kosong. Sila pilih nod sandaran untuk disimpan dan cuba lagi"
#cmd # penyegerakan fail dan imej nod
LocalNodeIpFailed: "Failed to get master node IP. Edit the master node and add IP address and SSH authentication information."
HandlePrivateKey: "Handle node private key"
HandlePublicKey: "Handle node public key"
ExchangeFile: "Start syncing {{ .sourcePath }} from node {{ .source }} to node {{ .dest }}:{{ .destPath }}"
NodeFile: "Node file"
ImageSyncTaskName: "Image sync {{ .count }} images"
SSLSyncTaskName: "Certificate sync {{ .count }} certificates"
AppSyncTaskName: "App sync {{ .name }}"
SSLSyncToNode: "Push certificate [{{ .cert }}] to node [{{ .node }}]"
ImageSyncSave: "Save image {{ .image }}"
ImageSyncSaveTags: "Save image tags {{ .tags }}"
ImageSyncToNode: "Sync image {{ .image }} to node {{ .node }}"
ImageSyncLoad: "Load image {{ .image }} on node {{ .node }}"
ImageSyncClean: "Clean temporary files for image {{ .image }}"
ImageSyncNoTag: "Image {{ .image }} has no tag and will be saved by image ID"
ImageSyncFrontendTagsIgnored: "No tags were found for image {{ .image }} on the source node. Frontend tags were ignored."
ImageSyncHandlePrivateKey: "Handle image sync node private key"
ImageSyncHandlePublicKey: "Handle image sync node public key"
ImageSyncTransfer: "Start transferring image temporary file: {{ .source }}:{{ .sourcePath }} -> {{ .dest }}:{{ .destPath }}"
# baris perintah
SudoHelper: "Sila gunakan {{ .cmd }} atau tukar ke pengguna root"
UsernameNeed: "Edisi Enterprise mesti menentukan --username"
DBConnErr: "Ralat: Gagal memulakan sambungan pangkalan data, {{ .err }}"
SystemVersion: "Versi: "
SystemMode: "Mod: "
# baris perintah - aplikasi
AppVersion: "Versi aplikasi" AppVersion: "Versi aplikasi"
AppCommands: "Arahan berkaitan aplikasi" AppCommands: "Arahan berkaitan aplikasi"
AppInit: "Inisialisasi aplikasi" AppInit: "Inisialisasi aplikasi"
@@ -242,12 +316,14 @@ AppMissVersion: "Versi aplikasi hilang, gunakan -v untuk menetapkan"
AppVersionExist: "Versi sudah wujud" AppVersionExist: "Versi sudah wujud"
AppCreateSuccessful: "Ciptaan berjaya" AppCreateSuccessful: "Ciptaan berjaya"
AppWriteErr: "Penulisan fail {{ .name }} gagal {{ .err }}" AppWriteErr: "Penulisan fail {{ .name }} gagal {{ .err }}"
SudoHelper: "Sila gunakan {{ .cmd }} atau tukar ke pengguna root"
UsernameNeed: "Edisi Enterprise mesti menentukan --username" # baris perintah - IP dengar
ListenIPCommands: "Tukar IP mendengar" ListenIPCommands: "Tukar IP mendengar"
ListenIPv4: "Mendengar pada IPv4" ListenIPv4: "Mendengar pada IPv4"
ListenIPv6: "Mendengar pada IPv6" ListenIPv6: "Mendengar pada IPv6"
ListenChangeSuccessful: "Tukar berjaya Kini mendengar pada {{ .value }}" ListenChangeSuccessful: "Tukar berjaya Kini mendengar pada {{ .value }}"
# baris perintah - tetapan semula
ResetCommands: "Tetapkan semula maklumat sistem" ResetCommands: "Tetapkan semula maklumat sistem"
ResetMFA: "Batal pengesahan dua faktor 1Panel" ResetMFA: "Batal pengesahan dua faktor 1Panel"
ResetHttps: "Batal log masuk HTTPS 1Panel" ResetHttps: "Batal log masuk HTTPS 1Panel"
@@ -255,12 +331,19 @@ ResetEntrance: "Batal pintu masuk keselamatan 1Panel"
ResetIPs: "Batal sekatan IP yang dibenarkan 1Panel" ResetIPs: "Batal sekatan IP yang dibenarkan 1Panel"
ResetDomain: "Batal pengikatan domain 1Panel" ResetDomain: "Batal pengikatan domain 1Panel"
ResetPasskey: "Kosongkan passkey 1Panel" ResetPasskey: "Kosongkan passkey 1Panel"
# baris perintah - pengguna
UserList: "Dapatkan senarai pengguna 1Panel" UserList: "Dapatkan senarai pengguna 1Panel"
UserTableName: "Nama" UserTableName: "Nama"
UserTableMFAStatus: "Status MFA" UserTableMFAStatus: "Status MFA"
UserTableSuperAdmin: "Pentadbir Super" UserTableSuperAdmin: "Pentadbir Super"
UserTableCreatedAt: "Dicipta Pada" UserTableCreatedAt: "Dicipta Pada"
UserEmptyList: "Tiada pengguna ditemui" UserEmptyList: "Tiada pengguna ditemui"
UserInfo: "Dapatkan maklumat panel"
UserInfoAddr: "Alamat panel: "
UserInfoPassHelp: "Petua: Untuk menukar kata laluan, anda boleh menjalankan arahan: "
# baris perintah - pulih
RestoreCommands: "Rollback perkhidmatan dan data 1Panel" RestoreCommands: "Rollback perkhidmatan dan data 1Panel"
RestoreNoSuchFile: "Tiada fail rollback ditemui" RestoreNoSuchFile: "Tiada fail rollback ditemui"
RestoreStep1: "(1/5) Memulakan rollback perkhidmatan dan data 1Panel daripada direktori {{ .name }}..." RestoreStep1: "(1/5) Memulakan rollback perkhidmatan dan data 1Panel daripada direktori {{ .name }}..."
@@ -269,6 +352,8 @@ RestoreStep3: "(3/5) Rollback skrip 1Panel berjaya"
RestoreStep4: "(4/5) Rollback perkhidmatan 1Panel berjaya" RestoreStep4: "(4/5) Rollback perkhidmatan 1Panel berjaya"
RestoreStep5: "(5/5) Rollback data 1Panel berjaya" RestoreStep5: "(5/5) Rollback data 1Panel berjaya"
RestoreSuccessful: "Rollback berjaya. Dikembalikan ke {{ .version }}. Perkhidmatan sedang dimulakan semula..." RestoreSuccessful: "Rollback berjaya. Dikembalikan ke {{ .version }}. Perkhidmatan sedang dimulakan semula..."
# baris perintah - kemas kini
UpdateCommands: "Kemas kini maklumat panel" UpdateCommands: "Kemas kini maklumat panel"
UpdateUser: "Kemas kini maklumat pengguna" UpdateUser: "Kemas kini maklumat pengguna"
UpdatePassword: "Kemas kini kata laluan pengguna" UpdatePassword: "Kemas kini kata laluan pengguna"
@@ -295,23 +380,12 @@ UpdatePortResult: "Port Panel: {{ .name }}"
UpdatePortFirewallAdd: "Gagal menambah peraturan port firewall, {{ .err }}, sila tambah port {{ .name }} secara manual ke dalam peraturan firewall." UpdatePortFirewallAdd: "Gagal menambah peraturan port firewall, {{ .err }}, sila tambah port {{ .name }} secara manual ke dalam peraturan firewall."
UpdatePortFirewallDel: "Ralat: Gagal memadam port firewall, {{ .err }}" UpdatePortFirewallDel: "Ralat: Gagal memadam port firewall, {{ .err }}"
UpdatePortFirewallReload: "Gagal memuat semula firewall, {{ .err }}, sila muat semula firewall secara manual." UpdatePortFirewallReload: "Gagal memuat semula firewall, {{ .err }}, sila muat semula firewall secara manual."
UserInfo: "Dapatkan maklumat panel"
UserInfoAddr: "Alamat panel: "
UserInfoPassHelp: "Petua: Untuk menukar kata laluan, anda boleh menjalankan arahan: "
DBConnErr: "Ralat: Gagal memulakan sambungan pangkalan data, {{ .err }}"
SystemVersion: "Versi: "
SystemMode: "Mod: "
#cluster # aplikasi mudah alih
ErrMasterDelete: "Tidak dapat menghapus nod utama, sila hapuskan nod perantara dahulu." ErrVerifyToken: "Ralat pengesahan token, sila tetapkan semula dan imbas semula"
ClusterNameIsExist: "Nama kluster sudah wujud." ErrInvalidToken: "Token tidak sah, sila tetapkan semula dan imbas semula"
AppStatusUnHealthy: "Pengambilan status aplikasi tidak normal, sila periksa status nod pemasangan dalam senarai nod." ErrExpiredToken: "Token telah tamat tempoh, sila tetapkan semula dan imbas semula"
MasterNodePortNotAvailable: "Pengesahan kesambungan pelabuhan {{ .name }} nod {{ .port }} gagal, sila periksa tetapan firewall/kumpulan keselamatan dan status nod utama."
ClusterMasterNotExist: "Node utama kluster terputus, sila padamkan nod anak."
#ssl # eksport perintah
ErrReqFailed: "{{.name}} permintaan gagal: {{ .err }}"
#command
Name: "Nama" Name: "Nama"
Command: "Arahan" Command: "Arahan"
+159 -95
View File
@@ -1,68 +1,65 @@
# erros básicos
ErrInvalidParams: 'Requisição inválida: {{ .detail }}' ErrInvalidParams: 'Requisição inválida: {{ .detail }}'
ErrTokenParse: 'Erro de token: {{ .detail }}' ErrTokenParse: 'Erro de token: {{ .detail }}'
ErrInitialPassword: 'Senha original incorreta' ErrInitialPassword: 'Senha original incorreta'
ErrInternalServer: 'Erro interno: {{ .detail }}' ErrInternalServer: 'Erro interno: {{ .detail }}'
ErrInternalServerKey: "Erro interno do servidor:"
ErrRecordExist: 'Registro já existe' ErrRecordExist: 'Registro já existe'
ErrRecordNotFound: 'Registro não encontrado' ErrRecordNotFound: 'Registro não encontrado'
ErrStructTransform: 'Erro de conversão: {{ .err }}' ErrStructTransform: 'Erro de conversão: {{ .err }}'
ErrNotLogin: 'Sem sessão: {{ .detail }}'
ErrSessionDataNotFound: "A sessão atual expirou"
ErrSessionDataFormat: "O formato dos dados da sessão atual está anormal"
ErrPasswordExpired: 'Senha expirada: {{ .detail }}'
ErrNotSupportType: 'Tipo não suportado: {{ .name }}' ErrNotSupportType: 'Tipo não suportado: {{ .name }}'
ErrProxy: 'Requisição falhou: {{ .detail }}' ErrDemoEnvironment: 'Indisponível em demo'
ErrApiConfigStatusInvalid: 'API desativada: {{ .detail }}' ErrCmdTimeout: 'Comando expirou'
ErrApiConfigKeyInvalid: 'Chave API inválida: {{ .detail }}' ErrPortInUsed: "A porta {{ .name }} já está em uso"
ErrApiConfigIPInvalid: 'IP sem permissão: {{ .detail }}' ErrFileNotFound: "Arquivo {{ .name }} não encontrado"
ErrApiConfigDisable: 'API bloqueada: {{ .detail }}' ErrReqFailed: "{{.name}} solicitação falhou: {{ .err }}"
ErrApiConfigKeyTimeInvalid: 'Timestamp inválido: {{ .detail }}'
ErrLoginLocked: "Muitas tentativas falharam. O login foi bloqueado temporariamente por 5 minutos."
# request # requisição e entrada de segurança
ErrNoSuchHost: "Servidor solicitado não encontrado {{ .err }}" ErrNoSuchHost: "Servidor solicitado não encontrado {{ .err }}"
ErrHttpReqNotFound: "Recurso solicitado não encontrado {{ .err }}" ErrHttpReqNotFound: "Recurso solicitado não encontrado {{ .err }}"
ErrHttpReqFailed: "Falha na requisição {{ .err }}" ErrHttpReqFailed: "Falha na requisição {{ .err }}"
ErrHttpReqTimeOut: "Tempo de requisição esgotado {{ .err }}" ErrHttpReqTimeOut: "Tempo de requisição esgotado {{ .err }}"
ErrCreateHttpClient: "Falha ao criar a requisição {{ .err }}" ErrCreateHttpClient: "Falha ao criar a requisição {{ .err }}"
ErrProxy: 'Requisição falhou: {{ .detail }}'
ErrProxySetting: "Informação do servidor proxy indisponível {{ .err }}, verifique e tente novamente" ErrProxySetting: "Informação do servidor proxy indisponível {{ .err }}, verifique e tente novamente"
ErrEntrance: "Erro nas informações de entrada de segurança, por favor, verifique e tente novamente"
ErrEntranceFormat: "A entrada de segurança {{ .name }} não é suportada atualmente. Por favor verifique e tente novamente" ErrEntranceFormat: "A entrada de segurança {{ .name }} não é suportada atualmente. Por favor verifique e tente novamente"
# common # login e segurança
ErrDemoEnvironment: 'Indisponível em demo' ErrNotLogin: 'Sem sessão: {{ .detail }}'
ErrCmdTimeout: 'Comando expirou' ErrSessionDataNotFound: "A sessão atual expirou"
ErrEntrance: "Erro nas informações de entrada de segurança, por favor, verifique e tente novamente" ErrSessionDataFormat: "O formato dos dados da sessão atual está anormal"
ErrPasswordExpired: 'Senha expirada: {{ .detail }}'
ErrLoginLocked: "Muitas tentativas falharam. O login foi bloqueado temporariamente por 5 minutos."
ErrApiConfigStatusInvalid: 'API desativada: {{ .detail }}'
ErrApiConfigKeyInvalid: 'Chave API inválida: {{ .detail }}'
ErrApiConfigIPInvalid: 'IP sem permissão: {{ .detail }}'
ErrApiConfigDisable: 'API bloqueada: {{ .detail }}'
ErrApiConfigKeyTimeInvalid: 'Timestamp inválido: {{ .detail }}'
ErrPasskeyDisabled: "Passkey requer HTTPS habilitado"
ErrPasskeyNotConfigured: "Nenhum Passkey configurado"
ErrPasskeyLimit: "Limite de Passkeys atingido (máximo 5)"
ErrPasskeySession: "Sessão do Passkey expirada ou inválida"
ErrPasskeyDuplicate: "Passkey já existe"
ErrPasskeyVerify: "Falha na verificação do Passkey"
# usuário e permissão
ErrNoSuchUser: "Informações do usuário não encontradas. Verifique e tente novamente."
ErrToMaster: "Este usuário não tem permissão para executar esta operação no nó principal. Verifique e tente novamente."
ErrToNode: "Este usuário não tem permissão para executar esta operação neste nó. Verifique e tente novamente."
ErrRBAC: "Permissões de usuário insuficientes. Não é possível executar esta operação. Verifique e tente novamente."
ErrNoneNode: "Este usuário não tem permissões de nenhum nó. Contate o administrador ou verifique e tente novamente."
ErrOnlySuperAdmin: "Somente superadministradores podem usar este recurso."
ErrRolePresetCannotDelete: "Funções predefinidas do sistema não podem ser excluídas"
ErrRolePresetCannotUpdate: "Funções predefinidas do sistema não podem ser atualizadas"
ErrRoleBoundToUser: "Esta função já está vinculada a usuários e não pode ser excluída"
ErrRolePresetCannotBind: "Funções predefinidas do sistema não podem ser atribuídas a usuários"
ErrNodeAdminMasterForbidden: "Permissões de administrador de nó não podem ser adicionadas ao nó principal"
ErrSuperAdminCannotDelete: "Usuários superadministradores não podem ser excluídos"
ErrGroupIsDefault: "Grupo padrão não pode ser excluído" ErrGroupIsDefault: "Grupo padrão não pode ser excluído"
ErrGroupIsInUse: "O grupo está em uso e não pode ser excluído." ErrGroupIsInUse: "O grupo está em uso e não pode ser excluído."
ErrAIProxyUserGroupIsDefault: "O grupo de usuários padrão não pode ser excluído."
ErrAIProxyUserGroupInUse: "O grupo de usuários está em uso e não pode ser excluído."
ErrAIProxyUserGroupExists: "O nome do grupo de usuários já existe."
ErrAIProxyBackendAccountExists: "Esta conta de modelo já foi importada para o pool de contas do AI Gateway."
ErrAIProxyModelGroupInUse: "O grupo de modelos está em uso e não pode ser excluído."
ErrAIProxyModelGroupExists: "O nome do grupo de modelos já existe."
ErrAIProxySensitiveGroupInUse: "O grupo de palavras sensíveis está em uso e não pode ser excluído."
ErrAIProxySensitiveGroupExists: "O nome do grupo de palavras sensíveis já existe."
ErrLocalDelete: "O nó local não pode ser excluído"
ErrPortInUsed: "A porta {{ .name }} já está em uso"
ErrInternalServerKey: "Erro interno do servidor:"
MasterNode: "Nó Mestre"
# app # licença
CustomAppStoreFileValid: "O pacote da loja de aplicativos deve estar no formato .tar.gz"
ErrFileNotFound: "Arquivo {{ .name }} não encontrado"
AppBackup: 'Backup de aplicação'
AppBackupPush: 'Transferir arquivo de backup de aplicação {{.file}} para o nó {{ .name }}'
ErrSourceTargetSame: 'O nó de origem e o nó de destino não podem ser os mesmos'
AppInstall: 'Instalar aplicação {{ .name }} no nó {{ .targetNode }}'
AppInstallCheck: 'Verificar ambiente de instalação da aplicação'
# backup
ErrBackupInUsed: 'Conta de backup em uso por tarefa'
ErrBackupCheck: 'Teste de conexão falhou: {{ .err }}'
ErrBackupLocal: "A conta de backup do servidor local não suporta essa operação"
ErrBackupPublic: "A conta de backup detectada não é pública, por favor verifique e tente novamente"
ErrOSSConn: "Não foi possível obter a versão mais recente, verifique a conectividade externa do servidor."
#license
LicenseCheck: 'Verificar se a licença está disponível' LicenseCheck: 'Verificar se a licença está disponível'
ErrLicenseInUsed: 'Esta licença já está vinculada. Por favor, verifique e tente novamente' ErrLicenseInUsed: 'Esta licença já está vinculada. Por favor, verifique e tente novamente'
ErrLicenseExpired: 'Esta licença expirou. Por favor, verifique e tente novamente' ErrLicenseExpired: 'Esta licença expirou. Por favor, verifique e tente novamente'
@@ -92,21 +89,6 @@ ErrNodeUnbind: "Nó fora do escopo da licença detectado, por favor verifique e
ErrNodeBind: "Este nó já está vinculado a uma licença, por favor verifique e tente novamente" ErrNodeBind: "Este nó já está vinculado a uma licença, por favor verifique e tente novamente"
ErrNodeLocalRollback: "O nó principal não suporta rollback direto. Por favor, execute manualmente o comando '1pctl restore' para fazer o rollback" ErrNodeLocalRollback: "O nó principal não suporta rollback direto. Por favor, execute manualmente o comando '1pctl restore' para fazer o rollback"
ErrIntlLicense: "A versão atual ainda não oferece suporte à importação de licença da edição internacional. Em breve" ErrIntlLicense: "A versão atual ainda não oferece suporte à importação de licença da edição internacional. Em breve"
# user
ErrNoSuchUser: "Informações do usuário não encontradas. Verifique e tente novamente."
ErrToMaster: "Este usuário não tem permissão para executar esta operação no nó principal. Verifique e tente novamente."
ErrToNode: "Este usuário não tem permissão para executar esta operação neste nó. Verifique e tente novamente."
ErrRBAC: "Permissões de usuário insuficientes. Não é possível executar esta operação. Verifique e tente novamente."
ErrNoneNode: "Este usuário não tem permissões de nenhum nó. Contate o administrador ou verifique e tente novamente."
ErrOnlySuperAdmin: "Somente superadministradores podem usar este recurso."
ErrRolePresetCannotDelete: "Funções predefinidas do sistema não podem ser excluídas"
ErrRolePresetCannotUpdate: "Funções predefinidas do sistema não podem ser atualizadas"
ErrRoleBoundToUser: "Esta função já está vinculada a usuários e não pode ser excluída"
ErrRolePresetCannotBind: "Funções predefinidas do sistema não podem ser atribuídas a usuários"
ErrNodeAdminMasterForbidden: "Permissões de administrador de nó não podem ser adicionadas ao nó principal"
ErrSuperAdminCannotDelete: "Usuários superadministradores não podem ser excluídos"
InvalidRequestBodyType: "Formato do corpo da requisição inválido. Verifique se o conteúdo está no formato correto e tente novamente" InvalidRequestBodyType: "Formato do corpo da requisição inválido. Verifique se o conteúdo está no formato correto e tente novamente"
InvalidLicenseCodeType: "Formato do código de licença inválido. Verifique e tente novamente" InvalidLicenseCodeType: "Formato do código de licença inválido. Verifique e tente novamente"
LicenseNotFoundType: "Licença não encontrada. Não há registros correspondentes no sistema para a licença fornecida. Verifique e tente novamente" LicenseNotFoundType: "Licença não encontrada. Não há registros correspondentes no sistema para a licença fornecida. Verifique e tente novamente"
@@ -117,10 +99,65 @@ InvalidAssigneeType: "Informações do usuário ou dispositivo alvo para atribui
LicenseUsageNotFoundType: "Nenhum registro de uso encontrado. Esta licença ainda não foi ativada ou usada. Verifique e tente novamente" LicenseUsageNotFoundType: "Nenhum registro de uso encontrado. Esta licença ainda não foi ativada ou usada. Verifique e tente novamente"
LicenseUsageLimitExceededType: "Esta licença já está vinculada a outro nó. Verifique e tente novamente" LicenseUsageLimitExceededType: "Esta licença já está vinculada a outro nó. Verifique e tente novamente"
# alert # nó e cluster
MasterNode: "Nó Mestre"
Node: "Nó"
ErrLocalDelete: "O nó local não pode ser excluído"
ErrMasterDelete: "Não é possível excluir o nó mestre, exclua os nós escravos primeiro."
ClusterNameIsExist: "O nome do cluster já existe."
AppStatusUnHealthy: "A aquisição do status do aplicativo está anormal, verifique o status dos nós de instalação na lista de nós."
MasterNodePortNotAvailable: "A verificação de conectividade da porta {{ .port }} do nó {{ .name }} falhou, verifique as configurações de firewall/grupo de segurança e o status do nó mestre."
ClusterMasterNotExist: "O nó mestre do cluster está desconectado, por favor, exclua os nós filhos."
# máquina virtual
ErrVMNotFound: "Máquina virtual não existe"
ErrVMAlreadyExists: "Máquina virtual já existe"
ErrVMStoragePathInUse: "O caminho do pool de armazenamento já é usado por [{{ .name }}]"
ErrVMRunning: "Máquina virtual está em execução"
ErrVMLibvirtConnect: "Falha ao conectar ao libvirt: {{ .detail }}"
ErrVMPermission: "Sem permissão para operar a máquina virtual: {{ .detail }}"
ErrVMNetworkNotFound: "Rede da máquina virtual não existe: {{ .detail }}"
ErrVMInvalidPath: "Caminho da máquina virtual inválido: {{ .detail }}"
ErrVMInvalidInput: "Parâmetro da máquina virtual inválido: {{ .detail }}"
ErrVMCommandFailed: "Falha no comando da máquina virtual: {{ .err }}"
VMSnapshotCreateTask: "Create snapshot [{{ .snapshot }}] for virtual machine [{{ .vm }}]"
VMSnapshotCreateStep: "Create virtual machine snapshot [{{ .snapshot }}]"
VMSnapshotRecoverTask: "Recover snapshot [{{ .snapshot }}] for virtual machine [{{ .vm }}]"
VMSnapshotRecoverStep: "Recover virtual machine snapshot [{{ .snapshot }}]"
VMSnapshotDeleteTask: "Delete snapshot [{{ .snapshot }}] for virtual machine [{{ .vm }}]"
VMSnapshotDeleteStep: "Delete virtual machine snapshot [{{ .snapshot }}]"
# aplicativo
CustomAppStoreFileValid: "O pacote da loja de aplicativos deve estar no formato .tar.gz"
AppBackup: 'Backup de aplicação'
AppBackupPush: 'Transferir arquivo de backup de aplicação {{.file}} para o nó {{ .name }}'
ErrSourceTargetSame: 'O nó de origem e o nó de destino não podem ser os mesmos'
AppInstall: 'Instalar aplicação {{ .name }} no nó {{ .targetNode }}'
AppInstallCheck: 'Verificar ambiente de instalação da aplicação'
# backup
ErrBackupInUsed: 'Conta de backup em uso por tarefa'
ErrBackupCheck: 'Teste de conexão falhou: {{ .err }}'
ErrBackupLocal: "A conta de backup do servidor local não suporta essa operação"
ErrBackupPublic: "A conta de backup detectada não é pública, por favor verifique e tente novamente"
ErrOSSConn: "Não foi possível obter a versão mais recente, verifique a conectividade externa do servidor."
MvBackup: "Mover dados para diretório de backup"
# alerta
ErrAlertSync: "Erro na sincronização das informações de alerta, verifique e tente novamente" ErrAlertSync: "Erro na sincronização das informações de alerta, verifique e tente novamente"
#task # gateway de IA
ErrAIProxyUserGroupIsDefault: "O grupo de usuários padrão não pode ser excluído."
ErrAIProxyUserGroupInUse: "O grupo de usuários está em uso e não pode ser excluído."
ErrAIProxyUserGroupExists: "O nome do grupo de usuários já existe."
ErrAIProxyBackendAccountExists: "Esta conta de modelo já foi importada para o pool de contas do AI Gateway."
ErrAIProxyModelGroupInUse: "O grupo de modelos está em uso e não pode ser excluído."
ErrAIProxyModelGroupExists: "O nome do grupo de modelos já existe."
ErrAIProxySensitiveGroupInUse: "O grupo de palavras sensíveis está em uso e não pode ser excluído."
ErrAIProxySensitiveGroupExists: "O nome do grupo de palavras sensíveis já existe."
AIBenchmarkRun: "Executar benchmark de IA"
# tarefa
TaskStart: "{{ .name }} tarefa iniciada [START]" TaskStart: "{{ .name }} tarefa iniciada [START]"
TaskEnd: "{{ .name }} tarefa finalizada [COMPLETED]" TaskEnd: "{{ .name }} tarefa finalizada [COMPLETED]"
TaskFailed: "{{ .name }} tarefa falhou" TaskFailed: "{{ .name }} tarefa falhou"
@@ -134,6 +171,16 @@ TaskUpgrade: "Atualizar"
TaskSync: 'Sincronizar' TaskSync: 'Sincronizar'
TaskSyncForNode: "Sincronizar Dados do Nó" TaskSyncForNode: "Sincronizar Dados do Nó"
TaskBackup: "Backup" TaskBackup: "Backup"
TaskPush: "Enviar"
TaskRsync: "Sync"
SuccessStatus: "{{ .name }} bem-sucedido"
FailedStatus: "{{ .name }} falhou {{ .err }}"
Start: "Iniciar"
SubTask: "Subtarefa"
Skip: "Ignorar erros e continuar..."
Success: "Sucesso"
# tarefa em lote do agente
BatchInstallAgent: "Instalar agentes em lote" BatchInstallAgent: "Instalar agentes em lote"
DispatchAgentInstallTasks: "Distribuir tarefas de instalação de agentes" DispatchAgentInstallTasks: "Distribuir tarefas de instalação de agentes"
BatchUpgradeAgent: "Atualizar agentes em lote" BatchUpgradeAgent: "Atualizar agentes em lote"
@@ -167,20 +214,15 @@ AgentOperateStart: "Iniciar"
AgentOperateStop: "Parar" AgentOperateStop: "Parar"
AgentOperateRestart: "Reiniciar" AgentOperateRestart: "Reiniciar"
AgentOperateDelete: "Excluir" AgentOperateDelete: "Excluir"
SuccessStatus: "{{ .name }} bem-sucedido"
FailedStatus: "{{ .name }} falhou {{ .err }}" # tarefa de aplicativo e habilidade
Start: "Iniciar"
SubTask: "Subtarefa"
Skip: "Ignorar erros e continuar..."
PushAppInstallTaskToNode: "Enviar tarefa de instalação de aplicativo para o nó [{{ .name }}]" PushAppInstallTaskToNode: "Enviar tarefa de instalação de aplicativo para o nó [{{ .name }}]"
TaskPush: "Enviar"
AppInstallTask: "Tarefa de instalação de aplicativo" AppInstallTask: "Tarefa de instalação de aplicativo"
PushAppFailed: "Falha ao enviar tarefa de instalação de aplicativo" PushAppFailed: "Falha ao enviar tarefa de instalação de aplicativo"
SkillHubInstallTask: "Instalar skill [{{ .name }}]" SkillHubInstallTask: "Instalar skill [{{ .name }}]"
SkillHubInstallToTarget: "Instalar skill no destino [{{ .name }}]" SkillHubInstallToTarget: "Instalar skill no destino [{{ .name }}]"
Success: "Sucesso"
#script # biblioteca de scripts
ScriptLibrary: "Biblioteca de Scripts" ScriptLibrary: "Biblioteca de Scripts"
RemoteScriptLibrary: "Biblioteca de Scripts Remota" RemoteScriptLibrary: "Biblioteca de Scripts Remota"
ScriptSyncSkip: "A biblioteca de scripts atual já é a versão mais recente" ScriptSyncSkip: "A biblioteca de scripts atual já é a versão mais recente"
@@ -188,7 +230,7 @@ DownloadData: "Baixando arquivo data.yaml da biblioteca de scripts"
DownloadPackage: "Baixando pacote da biblioteca de scripts" DownloadPackage: "Baixando pacote da biblioteca de scripts"
AnalyticCompletion: "Análise concluída, agora sincronizando com o banco de dados..." AnalyticCompletion: "Análise concluída, agora sincronizando com o banco de dados..."
Node: "Nó" # sincronização de nós
SyncNode: "Sincronizar dados para o nó {{ .name }}" SyncNode: "Sincronizar dados para o nó {{ .name }}"
LocalName: "O nome 'local' é usado apenas para identificação local do sistema" LocalName: "O nome 'local' é usado apenas para identificação local do sistema"
SyncPackageData: "Empacotar dados de sincronização" SyncPackageData: "Empacotar dados de sincronização"
@@ -204,7 +246,7 @@ SyncCustomApp: "Aplicativo Personalizado"
SyncLanguage: "Idioma do Sistema" SyncLanguage: "Idioma do Sistema"
SyncEdition: "Região de Operação" SyncEdition: "Região de Operação"
#upgrade node # atualização de nós
NodeUpgrade: "Atualizar nó {{ .name }}" NodeUpgrade: "Atualizar nó {{ .name }}"
UpgradeCheck: "Verificar atualizações do nó" UpgradeCheck: "Verificar atualizações do nó"
UpgradeCheckLocal: "Nós locais não suportam atualização em lote, pulando..." UpgradeCheckLocal: "Nós locais não suportam atualização em lote, pulando..."
@@ -217,12 +259,11 @@ LoadAutoUpgradeNodesFailed: "Falha ao carregar nós de atualização automática
AutoUpgradeNodes: "Nós de atualização automática: {{ .nodes }}" AutoUpgradeNodes: "Nós de atualização automática: {{ .nodes }}"
UpdateAutoUpgradeNodesStatusFailed: "Falha ao atualizar o status dos nós de atualização automática, erro: {{ .err }}" UpdateAutoUpgradeNodesStatusFailed: "Falha ao atualizar o status dos nós de atualização automática, erro: {{ .err }}"
#add node # adicionar nó
MasterData: "Dados do Nó Mestre" MasterData: "Dados do Nó Mestre"
LoadSftpClient: "Carregar Cliente SFTP" LoadSftpClient: "Carregar Cliente SFTP"
PackageMasterData: "Gerar pacote de backup do nó mestre" PackageMasterData: "Gerar pacote de backup do nó mestre"
UploadBackup: "Carregar dados de backup" UploadBackup: "Carregar dados de backup"
MvBackup: "Mover dados para diretório de backup"
TaskAddNode: "Adicionar nó" TaskAddNode: "Adicionar nó"
LoadNodeArch: "Obter informações de arquitetura do nó" LoadNodeArch: "Obter informações de arquitetura do nó"
LoadNodeArchDetail: "Arquitetura do nó mestre detectada: {{ .local }}, arquitetura do nó filho: {{ .node }}" LoadNodeArchDetail: "Arquitetura do nó mestre detectada: {{ .local }}, arquitetura do nó filho: {{ .node }}"
@@ -235,7 +276,35 @@ SendAgent: "Enviando pacote de instalação do nó"
StartService: "Iniciando serviço" StartService: "Iniciando serviço"
NoBackupNode: "O nó de backup está vazio atualmente. Selecione um nó de backup para salvar e tente novamente" NoBackupNode: "O nó de backup está vazio atualmente. Selecione um nó de backup para salvar e tente novamente"
#cmd # sincronização de arquivos e imagens do nó
LocalNodeIpFailed: "Failed to get master node IP. Edit the master node and add IP address and SSH authentication information."
HandlePrivateKey: "Handle node private key"
HandlePublicKey: "Handle node public key"
ExchangeFile: "Start syncing {{ .sourcePath }} from node {{ .source }} to node {{ .dest }}:{{ .destPath }}"
NodeFile: "Node file"
ImageSyncTaskName: "Image sync {{ .count }} images"
SSLSyncTaskName: "Certificate sync {{ .count }} certificates"
AppSyncTaskName: "App sync {{ .name }}"
SSLSyncToNode: "Push certificate [{{ .cert }}] to node [{{ .node }}]"
ImageSyncSave: "Save image {{ .image }}"
ImageSyncSaveTags: "Save image tags {{ .tags }}"
ImageSyncToNode: "Sync image {{ .image }} to node {{ .node }}"
ImageSyncLoad: "Load image {{ .image }} on node {{ .node }}"
ImageSyncClean: "Clean temporary files for image {{ .image }}"
ImageSyncNoTag: "Image {{ .image }} has no tag and will be saved by image ID"
ImageSyncFrontendTagsIgnored: "No tags were found for image {{ .image }} on the source node. Frontend tags were ignored."
ImageSyncHandlePrivateKey: "Handle image sync node private key"
ImageSyncHandlePublicKey: "Handle image sync node public key"
ImageSyncTransfer: "Start transferring image temporary file: {{ .source }}:{{ .sourcePath }} -> {{ .dest }}:{{ .destPath }}"
# linha de comando
SudoHelper: "Por favor, use {{ .cmd }} ou altere para o usuário root"
UsernameNeed: "A edição Enterprise deve especificar --username"
DBConnErr: "Erro: Falha ao inicializar a conexão com o banco de dados, {{ .err }}"
SystemVersion: "versão: "
SystemMode: "modo: "
# linha de comando - aplicativo
AppVersion: "Versão do aplicativo" AppVersion: "Versão do aplicativo"
AppCommands: "Comandos relacionados ao aplicativo" AppCommands: "Comandos relacionados ao aplicativo"
AppInit: "Inicializar aplicativo" AppInit: "Inicializar aplicativo"
@@ -247,12 +316,14 @@ AppMissVersion: "Versão do aplicativo ausente, use -v para especificar"
AppVersionExist: "A versão já existe" AppVersionExist: "A versão já existe"
AppCreateSuccessful: "Criação bem-sucedida" AppCreateSuccessful: "Criação bem-sucedida"
AppWriteErr: "Falha ao escrever no arquivo {{ .name }} {{ .err }}" AppWriteErr: "Falha ao escrever no arquivo {{ .name }} {{ .err }}"
SudoHelper: "Por favor, use {{ .cmd }} ou altere para o usuário root"
UsernameNeed: "A edição Enterprise deve especificar --username" # linha de comando - IP de escuta
ListenIPCommands: "Trocar IP de escuta" ListenIPCommands: "Trocar IP de escuta"
ListenIPv4: "Escutando em IPv4" ListenIPv4: "Escutando em IPv4"
ListenIPv6: "Escutando em IPv6" ListenIPv6: "Escutando em IPv6"
ListenChangeSuccessful: "Troca bem-sucedida Agora escutando em {{ .value }}" ListenChangeSuccessful: "Troca bem-sucedida Agora escutando em {{ .value }}"
# linha de comando - redefinir
ResetCommands: "Redefinir informações do sistema" ResetCommands: "Redefinir informações do sistema"
ResetMFA: "Cancelar autenticação de dois fatores do 1Panel" ResetMFA: "Cancelar autenticação de dois fatores do 1Panel"
ResetHttps: "Cancelar login https do 1Panel" ResetHttps: "Cancelar login https do 1Panel"
@@ -260,12 +331,19 @@ ResetEntrance: "Cancelar entrada segura do 1Panel"
ResetIPs: "Cancelar restrições de IP autorizado do 1Panel" ResetIPs: "Cancelar restrições de IP autorizado do 1Panel"
ResetDomain: "Cancelar vinculação de domínio do 1Panel" ResetDomain: "Cancelar vinculação de domínio do 1Panel"
ResetPasskey: "Redefinir passkeys do 1Panel" ResetPasskey: "Redefinir passkeys do 1Panel"
# linha de comando - usuário
UserList: "Obter a lista de usuários do 1Panel" UserList: "Obter a lista de usuários do 1Panel"
UserTableName: "Nome" UserTableName: "Nome"
UserTableMFAStatus: "Status MFA" UserTableMFAStatus: "Status MFA"
UserTableSuperAdmin: "Superadministrador" UserTableSuperAdmin: "Superadministrador"
UserTableCreatedAt: "Criado em" UserTableCreatedAt: "Criado em"
UserEmptyList: "Nenhum usuário encontrado" UserEmptyList: "Nenhum usuário encontrado"
UserInfo: "Obter informações do painel"
UserInfoAddr: "Endereço do painel: "
UserInfoPassHelp: "Dica: Para alterar a senha, você pode executar o comando: "
# linha de comando - restaurar
RestoreCommands: "Fazer rollback do serviço e dos dados do 1Panel" RestoreCommands: "Fazer rollback do serviço e dos dados do 1Panel"
RestoreNoSuchFile: "Nenhum arquivo de rollback encontrado" RestoreNoSuchFile: "Nenhum arquivo de rollback encontrado"
RestoreStep1: "(1/5) Iniciando o rollback do serviço e dos dados do 1Panel a partir do diretório {{ .name }}..." RestoreStep1: "(1/5) Iniciando o rollback do serviço e dos dados do 1Panel a partir do diretório {{ .name }}..."
@@ -274,6 +352,8 @@ RestoreStep3: "(3/5) Rollback dos scripts do 1Panel concluído"
RestoreStep4: "(4/5) Rollback do serviço do 1Panel concluído" RestoreStep4: "(4/5) Rollback do serviço do 1Panel concluído"
RestoreStep5: "(5/5) Rollback dos dados do 1Panel concluído" RestoreStep5: "(5/5) Rollback dos dados do 1Panel concluído"
RestoreSuccessful: "Rollback concluído. Revertido para {{ .version }}. Reiniciando o serviço..." RestoreSuccessful: "Rollback concluído. Revertido para {{ .version }}. Reiniciando o serviço..."
# linha de comando - atualizar
UpdateCommands: "Atualizar informações do painel" UpdateCommands: "Atualizar informações do painel"
UpdateUser: "Atualizar informações do usuário" UpdateUser: "Atualizar informações do usuário"
UpdatePassword: "Atualizar senha do usuário" UpdatePassword: "Atualizar senha do usuário"
@@ -300,28 +380,12 @@ UpdatePortResult: "Porta do painel: {{ .name }}"
UpdatePortFirewallAdd: "Falha ao adicionar regra de porta ao firewall, {{ .err }}, por favor, adicione manualmente a porta {{ .name }} às regras do firewall." UpdatePortFirewallAdd: "Falha ao adicionar regra de porta ao firewall, {{ .err }}, por favor, adicione manualmente a porta {{ .name }} às regras do firewall."
UpdatePortFirewallDel: "Erro: Falha ao excluir a porta do firewall, {{ .err }}" UpdatePortFirewallDel: "Erro: Falha ao excluir a porta do firewall, {{ .err }}"
UpdatePortFirewallReload: "Falha ao recarregar o firewall, {{ .err }}, por favor, recarregue o firewall manualmente." UpdatePortFirewallReload: "Falha ao recarregar o firewall, {{ .err }}, por favor, recarregue o firewall manualmente."
UserInfo: "Obter informações do painel"
UserInfoAddr: "Endereço do painel: "
UserInfoPassHelp: "Dica: Para alterar a senha, você pode executar o comando: "
DBConnErr: "Erro: Falha ao inicializar a conexão com o banco de dados, {{ .err }}"
SystemVersion: "versão: "
SystemMode: "modo: "
#mobile app # aplicativo móvel
ErrVerifyToken: 'Erro de verificação do token, por favor, reinicie e escaneie novamente.' ErrVerifyToken: 'Erro de verificação do token, por favor, reinicie e escaneie novamente.'
ErrInvalidToken: 'Token inválido, por favor, reinicie e escaneie novamente.' ErrInvalidToken: 'Token inválido, por favor, reinicie e escaneie novamente.'
ErrExpiredToken: 'O token expirou, por favor, reinicie e escaneie novamente.' ErrExpiredToken: 'O token expirou, por favor, reinicie e escaneie novamente.'
#cluster # exportação de comandos
ErrMasterDelete: "Não é possível excluir o nó mestre, exclua os nós escravos primeiro."
ClusterNameIsExist: "O nome do cluster já existe."
AppStatusUnHealthy: "A aquisição do status do aplicativo está anormal, verifique o status dos nós de instalação na lista de nós."
MasterNodePortNotAvailable: "A verificação de conectividade da porta {{ .port }} do nó {{ .name }} falhou, verifique as configurações de firewall/grupo de segurança e o status do nó mestre."
ClusterMasterNotExist: "O nó mestre do cluster está desconectado, por favor, exclua os nós filhos."
#ssl
ErrReqFailed: "{{.name}} solicitação falhou: {{ .err }}"
#command
Name: "Название" Name: "Название"
Command: "Команда" Command: "Команда"
+160 -95
View File
@@ -1,68 +1,65 @@
# базовые ошибки
ErrInvalidParams: 'Неверный запрос: {{ .detail }}' ErrInvalidParams: 'Неверный запрос: {{ .detail }}'
ErrTokenParse: 'Ошибка токена: {{ .detail }}' ErrTokenParse: 'Ошибка токена: {{ .detail }}'
ErrInitialPassword: 'Исходный пароль неверен' ErrInitialPassword: 'Исходный пароль неверен'
ErrInternalServer: 'Внутренняя ошибка: {{ .detail }}' ErrInternalServer: 'Внутренняя ошибка: {{ .detail }}'
ErrInternalServerKey: "Внутренняя ошибка сервера:"
ErrRecordExist: 'Запись уже существует' ErrRecordExist: 'Запись уже существует'
ErrRecordNotFound: 'Запись не найдена' ErrRecordNotFound: 'Запись не найдена'
ErrStructTransform: 'Ошибка преобразования: {{ .err }}' ErrStructTransform: 'Ошибка преобразования: {{ .err }}'
ErrNotLogin: 'Не авторизован: {{ .detail }}'
ErrSessionDataNotFound: "Текущая сессия истекла"
ErrSessionDataFormat: "Ненормальный формат данных текущей сессии"
ErrPasswordExpired: 'Пароль истёк: {{ .detail }}'
ErrNotSupportType: 'Тип не поддерживается: {{ .name }}' ErrNotSupportType: 'Тип не поддерживается: {{ .name }}'
ErrProxy: 'Запрос не удался: {{ .detail }}' ErrDemoEnvironment: 'Недоступно в демо'
ErrApiConfigStatusInvalid: 'API отключено: {{ .detail }}' ErrCmdTimeout: 'Команда завершилась по тайм-ауту'
ErrApiConfigKeyInvalid: 'Неверный API-ключ: {{ .detail }}' ErrPortInUsed: "Порт {{ .name }} уже используется"
ErrApiConfigIPInvalid: 'IP не в списке: {{ .detail }}' ErrFileNotFound: "Файл {{ .name }} не найден"
ErrApiConfigDisable: 'Доступ по API запрещён: {{ .detail }}' ErrReqFailed: "{{.name}} запрос не удался: {{ .err }}"
ErrApiConfigKeyTimeInvalid: 'Неверная метка времени: {{ .detail }}'
ErrLoginLocked: "Слишком много неудачных попыток. Вход временно заблокирован на 5 минут."
# request # запрос и вход безопасности
ErrNoSuchHost: "Не удалось найти запрашиваемый сервер {{ .err }}" ErrNoSuchHost: "Не удалось найти запрашиваемый сервер {{ .err }}"
ErrHttpReqNotFound: "Не удалось найти запрашиваемый ресурс {{ .err }}" ErrHttpReqNotFound: "Не удалось найти запрашиваемый ресурс {{ .err }}"
ErrHttpReqFailed: "Ошибка запроса {{ .err }}" ErrHttpReqFailed: "Ошибка запроса {{ .err }}"
ErrHttpReqTimeOut: "Время ожидания запроса истекло {{ .err }}" ErrHttpReqTimeOut: "Время ожидания запроса истекло {{ .err }}"
ErrCreateHttpClient: "Ошибка создания запроса {{ .err }}" ErrCreateHttpClient: "Ошибка создания запроса {{ .err }}"
ErrProxy: 'Запрос не удался: {{ .detail }}'
ErrProxySetting: "Информация о прокси-сервере недоступна {{ .err }}, проверьте и повторите попытку" ErrProxySetting: "Информация о прокси-сервере недоступна {{ .err }}, проверьте и повторите попытку"
ErrEntrance: "Ошибка информации о безопасном входе, проверьте и повторите попытку"
ErrEntranceFormat: "Защищенный вход {{ .name }} в настоящее время не поддерживается. Пожалуйста, проверьте и повторите попытку" ErrEntranceFormat: "Защищенный вход {{ .name }} в настоящее время не поддерживается. Пожалуйста, проверьте и повторите попытку"
# common # вход и безопасность
ErrDemoEnvironment: 'Недоступно в демо' ErrNotLogin: 'Не авторизован: {{ .detail }}'
ErrCmdTimeout: 'Команда завершилась по тайм-ауту' ErrSessionDataNotFound: "Текущая сессия истекла"
ErrEntrance: "Ошибка информации о безопасном входе, проверьте и повторите попытку" ErrSessionDataFormat: "Ненормальный формат данных текущей сессии"
ErrPasswordExpired: 'Пароль истёк: {{ .detail }}'
ErrLoginLocked: "Слишком много неудачных попыток. Вход временно заблокирован на 5 минут."
ErrApiConfigStatusInvalid: 'API отключено: {{ .detail }}'
ErrApiConfigKeyInvalid: 'Неверный API-ключ: {{ .detail }}'
ErrApiConfigIPInvalid: 'IP не в списке: {{ .detail }}'
ErrApiConfigDisable: 'Доступ по API запрещён: {{ .detail }}'
ErrApiConfigKeyTimeInvalid: 'Неверная метка времени: {{ .detail }}'
ErrPasskeyDisabled: "Для Passkey требуется включить HTTPS"
ErrPasskeyNotConfigured: "Passkey не настроен"
ErrPasskeyLimit: "Достигнут лимит Passkey (максимум 5)"
ErrPasskeySession: "Сеанс Passkey истек или недействителен"
ErrPasskeyDuplicate: "Passkey уже существует"
ErrPasskeyVerify: "Не удалось проверить Passkey"
# пользователь и права
ErrNoSuchUser: "Информация о пользователе не найдена. Проверьте и повторите попытку."
ErrToMaster: "У этого пользователя нет прав для выполнения этой операции на основном узле. Проверьте и повторите попытку."
ErrToNode: "У этого пользователя нет прав для выполнения этой операции на этом узле. Проверьте и повторите попытку."
ErrRBAC: "Недостаточно прав пользователя. Операция не может быть выполнена. Проверьте и повторите попытку."
ErrNoneNode: "У этого пользователя нет прав ни на один узел. Обратитесь к администратору или проверьте и повторите попытку."
ErrOnlySuperAdmin: "Эта функция доступна только супер администраторам."
ErrRolePresetCannotDelete: "Системные предустановленные роли нельзя удалять"
ErrRolePresetCannotUpdate: "Системные предустановленные роли нельзя обновлять"
ErrRoleBoundToUser: "Эта роль уже привязана к пользователям и не может быть удалена"
ErrRolePresetCannotBind: "Системные предустановленные роли нельзя назначать пользователям"
ErrNodeAdminMasterForbidden: "Права администратора узла нельзя добавить к главному узлу"
ErrSuperAdminCannotDelete: "Пользователей супер-администратора нельзя удалять"
ErrGroupIsDefault: "Группу по умолчанию нельзя удалить" ErrGroupIsDefault: "Группу по умолчанию нельзя удалить"
ErrGroupIsInUse: "Группа используется и не может быть удалена." ErrGroupIsInUse: "Группа используется и не может быть удалена."
ErrAIProxyUserGroupIsDefault: "Группу пользователей по умолчанию нельзя удалить."
ErrAIProxyUserGroupInUse: "Группа пользователей используется и не может быть удалена."
ErrAIProxyUserGroupExists: "Имя группы пользователей уже существует."
ErrAIProxyBackendAccountExists: "Эта учетная запись модели уже импортирована в пул аккаунтов AI Gateway."
ErrAIProxyModelGroupInUse: "Группа моделей используется и не может быть удалена."
ErrAIProxyModelGroupExists: "Имя группы моделей уже существует."
ErrAIProxySensitiveGroupInUse: "Группа чувствительных слов используется и не может быть удалена."
ErrAIProxySensitiveGroupExists: "Имя группы чувствительных слов уже существует."
ErrLocalDelete: "Локальный узел нельзя удалить"
ErrPortInUsed: "Порт {{ .name }} уже используется"
ErrInternalServerKey: "Внутренняя ошибка сервера:"
MasterNode: "Главный узел"
# app # лицензия
CustomAppStoreFileValid: "Пакет магазина приложений должен быть в формате .tar.gz"
ErrFileNotFound: "Файл {{ .name }} не найден"
AppBackup: 'Резервная копия приложения'
AppBackupPush: 'Передать файл резервной копии приложения {{.file}} на узел {{ .name }}'
ErrSourceTargetSame: 'Исходный узел и целевой узел не могут быть одинаковыми'
AppInstall: 'Установить приложение {{ .name }} на узел {{ .targetNode }}'
AppInstallCheck: 'Проверить среду установки приложения'
# backup
ErrBackupInUsed: 'Аккаунт бэкапа занят задачей'
ErrBackupCheck: 'Проверка подключения не удалась: {{ .err }}'
ErrBackupLocal: "Локальная учетная запись резервного копирования не поддерживает эту операцию"
ErrBackupPublic: "Обнаружено, что эта учетная запись резервного копирования не является публичной, проверьте и повторите попытку"
ErrOSSConn: "Не удалось получить последнюю версию, проверьте подключение сервера к внешней сети."
#license
LicenseCheck: 'Проверить доступность лицензии' LicenseCheck: 'Проверить доступность лицензии'
ErrLicenseInUsed: 'Лицензия уже привязана. Пожалуйста, проверьте и повторите попытку' ErrLicenseInUsed: 'Лицензия уже привязана. Пожалуйста, проверьте и повторите попытку'
ErrLicenseExpired: 'Срок действия лицензии истек. Пожалуйста, проверьте и повторите попытку' ErrLicenseExpired: 'Срок действия лицензии истек. Пожалуйста, проверьте и повторите попытку'
@@ -92,21 +89,6 @@ ErrNodeUnbind: "Обнаружен узел вне области действи
ErrNodeBind: "Этот узел уже связан с лицензией, проверьте и повторите попытку" ErrNodeBind: "Этот узел уже связан с лицензией, проверьте и повторите попытку"
ErrNodeLocalRollback: "Прямой откат на основном узле не поддерживается. Выполните '1pctl restore' вручную для отката" ErrNodeLocalRollback: "Прямой откат на основном узле не поддерживается. Выполните '1pctl restore' вручную для отката"
ErrIntlLicense: "Текущая версия пока не поддерживает импорт международной лицензии. Скоро будет доступно" ErrIntlLicense: "Текущая версия пока не поддерживает импорт международной лицензии. Скоро будет доступно"
# user
ErrNoSuchUser: "Информация о пользователе не найдена. Проверьте и повторите попытку."
ErrToMaster: "У этого пользователя нет прав для выполнения этой операции на основном узле. Проверьте и повторите попытку."
ErrToNode: "У этого пользователя нет прав для выполнения этой операции на этом узле. Проверьте и повторите попытку."
ErrRBAC: "Недостаточно прав пользователя. Операция не может быть выполнена. Проверьте и повторите попытку."
ErrNoneNode: "У этого пользователя нет прав ни на один узел. Обратитесь к администратору или проверьте и повторите попытку."
ErrOnlySuperAdmin: "Эта функция доступна только супер администраторам."
ErrRolePresetCannotDelete: "Системные предустановленные роли нельзя удалять"
ErrRolePresetCannotUpdate: "Системные предустановленные роли нельзя обновлять"
ErrRoleBoundToUser: "Эта роль уже привязана к пользователям и не может быть удалена"
ErrRolePresetCannotBind: "Системные предустановленные роли нельзя назначать пользователям"
ErrNodeAdminMasterForbidden: "Права администратора узла нельзя добавить к главному узлу"
ErrSuperAdminCannotDelete: "Пользователей супер-администратора нельзя удалять"
InvalidRequestBodyType: "Неверный формат тела запроса. Проверьте, соответствует ли содержимое требуемому формату, и повторите попытку" InvalidRequestBodyType: "Неверный формат тела запроса. Проверьте, соответствует ли содержимое требуемому формату, и повторите попытку"
InvalidLicenseCodeType: "Указан неверный формат лицензионного кода. Проверьте и повторите попытку" InvalidLicenseCodeType: "Указан неверный формат лицензионного кода. Проверьте и повторите попытку"
LicenseNotFoundType: "Лицензия не найдена. В системе нет записей, соответствующих указанной лицензии. Проверьте и повторите попытку" LicenseNotFoundType: "Лицензия не найдена. В системе нет записей, соответствующих указанной лицензии. Проверьте и повторите попытку"
@@ -117,10 +99,65 @@ InvalidAssigneeType: "Некорректная информация о целе
LicenseUsageNotFoundType: "Записи об использовании отсутствуют. Эта лицензия еще не активирована или не использовалась. Проверьте и повторите попытку" LicenseUsageNotFoundType: "Записи об использовании отсутствуют. Эта лицензия еще не активирована или не использовалась. Проверьте и повторите попытку"
LicenseUsageLimitExceededType: "Эта лицензия уже привязана к другому узлу. Проверьте и повторите попытку" LicenseUsageLimitExceededType: "Эта лицензия уже привязана к другому узлу. Проверьте и повторите попытку"
# alert # узел и кластер
MasterNode: "Главный узел"
Node: "Узел"
ErrLocalDelete: "Локальный узел нельзя удалить"
ErrMasterDelete: "Невозможно удалить основной узел, сначала удалите подчиненные узлы."
ClusterNameIsExist: "Имя кластера уже существует."
AppStatusUnHealthy: "Получение статуса приложения аномально, пожалуйста, проверьте статус узлов установки в списке узлов."
MasterNodePortNotAvailable: "Проверка подключения порта {{ .port }} узла {{ .name }} не удалась, пожалуйста, проверьте настройки брандмауэра/группы безопасности и статус главного узла."
ClusterMasterNotExist: "Основной узел кластера отключен, пожалуйста, удалите дочерние узлы."
# виртуальная машина
ErrVMNotFound: "Виртуальная машина не существует"
ErrVMAlreadyExists: "Виртуальная машина уже существует"
ErrVMStoragePathInUse: "Путь пула хранения уже используется [{{ .name }}]"
ErrVMRunning: "Виртуальная машина запущена"
ErrVMLibvirtConnect: "Не удалось подключиться к libvirt: {{ .detail }}"
ErrVMPermission: "Нет разрешения на операцию с виртуальной машиной: {{ .detail }}"
ErrVMNetworkNotFound: "Сеть виртуальной машины не существует: {{ .detail }}"
ErrVMInvalidPath: "Недопустимый путь виртуальной машины: {{ .detail }}"
ErrVMInvalidInput: "Недопустимые параметры виртуальной машины: {{ .detail }}"
ErrVMCommandFailed: "Ошибка выполнения команды виртуальной машины: {{ .err }}"
VMSnapshotCreateTask: "Create snapshot [{{ .snapshot }}] for virtual machine [{{ .vm }}]"
VMSnapshotCreateStep: "Create virtual machine snapshot [{{ .snapshot }}]"
VMSnapshotRecoverTask: "Recover snapshot [{{ .snapshot }}] for virtual machine [{{ .vm }}]"
VMSnapshotRecoverStep: "Recover virtual machine snapshot [{{ .snapshot }}]"
VMSnapshotDeleteTask: "Delete snapshot [{{ .snapshot }}] for virtual machine [{{ .vm }}]"
VMSnapshotDeleteStep: "Delete virtual machine snapshot [{{ .snapshot }}]"
# приложение
CustomAppStoreFileValid: "Пакет магазина приложений должен быть в формате .tar.gz"
AppBackup: 'Резервная копия приложения'
AppBackupPush: 'Передать файл резервной копии приложения {{.file}} на узел {{ .name }}'
ErrSourceTargetSame: 'Исходный узел и целевой узел не могут быть одинаковыми'
AppInstall: 'Установить приложение {{ .name }} на узел {{ .targetNode }}'
AppInstallCheck: 'Проверить среду установки приложения'
# резервное копирование
ErrBackupInUsed: 'Аккаунт бэкапа занят задачей'
ErrBackupCheck: 'Проверка подключения не удалась: {{ .err }}'
ErrBackupLocal: "Локальная учетная запись резервного копирования не поддерживает эту операцию"
ErrBackupPublic: "Обнаружено, что эта учетная запись резервного копирования не является публичной, проверьте и повторите попытку"
ErrOSSConn: "Не удалось получить последнюю версию, проверьте подключение сервера к внешней сети."
MvBackup: "Переместить данные в резервный каталог"
# оповещение
ErrAlertSync: "Ошибка синхронизации информации об оповещениях, пожалуйста, проверьте и повторите попытку" ErrAlertSync: "Ошибка синхронизации информации об оповещениях, пожалуйста, проверьте и повторите попытку"
# task # AI-шлюз
ErrAIProxyUserGroupIsDefault: "Группу пользователей по умолчанию нельзя удалить."
ErrAIProxyUserGroupInUse: "Группа пользователей используется и не может быть удалена."
ErrAIProxyUserGroupExists: "Имя группы пользователей уже существует."
ErrAIProxyBackendAccountExists: "Эта учетная запись модели уже импортирована в пул аккаунтов AI Gateway."
ErrAIProxyModelGroupInUse: "Группа моделей используется и не может быть удалена."
ErrAIProxyModelGroupExists: "Имя группы моделей уже существует."
ErrAIProxySensitiveGroupInUse: "Группа чувствительных слов используется и не может быть удалена."
ErrAIProxySensitiveGroupExists: "Имя группы чувствительных слов уже существует."
AIBenchmarkRun: "Выполнить тест производительности AI"
# задача
TaskStart: "{{ .name }} задача начата [START]" TaskStart: "{{ .name }} задача начата [START]"
TaskEnd: "{{ .name }} задача завершена [COMPLETED]" TaskEnd: "{{ .name }} задача завершена [COMPLETED]"
TaskFailed: "{{ .name }} задача не выполнена" TaskFailed: "{{ .name }} задача не выполнена"
@@ -134,6 +171,16 @@ TaskUpgrade: "Обновить"
TaskSync: 'Синхронизация' TaskSync: 'Синхронизация'
TaskSyncForNode: "Синхронизировать Данные Узла" TaskSyncForNode: "Синхронизировать Данные Узла"
TaskBackup: "Резервная копия" TaskBackup: "Резервная копия"
TaskPush: "Отправить"
TaskRsync: "Sync"
SuccessStatus: "{{ .name }} успешно"
FailedStatus: "{{ .name }} не удалось {{ .err }}"
Start: "Начать"
SubTask: "Подзадача"
Skip: "Пропустить ошибки и продолжить..."
Success: "Успешно"
# пакетная задача агента
BatchInstallAgent: "Пакетная установка агентов" BatchInstallAgent: "Пакетная установка агентов"
DispatchAgentInstallTasks: "Отправить задачи установки агентов" DispatchAgentInstallTasks: "Отправить задачи установки агентов"
BatchUpgradeAgent: "Пакетное обновление агентов" BatchUpgradeAgent: "Пакетное обновление агентов"
@@ -167,19 +214,15 @@ AgentOperateStart: "Запустить"
AgentOperateStop: "Остановить" AgentOperateStop: "Остановить"
AgentOperateRestart: "Перезапустить" AgentOperateRestart: "Перезапустить"
AgentOperateDelete: "Удалить" AgentOperateDelete: "Удалить"
SuccessStatus: "{{ .name }} успешно"
FailedStatus: "{{ .name }} не удалось {{ .err }}" # задача приложения и навыка
Start: "Начать" PushAppInstallTaskToNode: "Отправить задачу установки приложения на узел [{{ .name }}]"
SubTask: "Подзадача"
Skip: "Пропустить ошибки и продолжить..."
TaskPush: "Отправить"
AppInstallTask: "Задача установки приложения" AppInstallTask: "Задача установки приложения"
PushAppFailed: "Не удалось отправить задачу установки приложения" PushAppFailed: "Не удалось отправить задачу установки приложения"
SkillHubInstallTask: "Установить навык [{{ .name }}]" SkillHubInstallTask: "Установить навык [{{ .name }}]"
SkillHubInstallToTarget: "Установить навык в цель [{{ .name }}]" SkillHubInstallToTarget: "Установить навык в цель [{{ .name }}]"
Success: "Успешно"
#script # библиотека скриптов
ScriptLibrary: "Библиотека скриптов" ScriptLibrary: "Библиотека скриптов"
RemoteScriptLibrary: "Удаленная Библиотека Скриптов" RemoteScriptLibrary: "Удаленная Библиотека Скриптов"
ScriptSyncSkip: "Текущая библиотека скриптов уже является последней версией" ScriptSyncSkip: "Текущая библиотека скриптов уже является последней версией"
@@ -187,7 +230,7 @@ DownloadData: "Загрузка файла библиотеки скриптов
DownloadPackage: "Загрузка архива библиотеки скриптов" DownloadPackage: "Загрузка архива библиотеки скриптов"
AnalyticCompletion: "Анализ завершён, начинается синхронизация с базой данных..." AnalyticCompletion: "Анализ завершён, начинается синхронизация с базой данных..."
Node: "Узел" # синхронизация узла
SyncNode: "Синхронизировать данные с узлом {{ .name }}" SyncNode: "Синхронизировать данные с узлом {{ .name }}"
LocalName: "Имя 'local' используется только для локальной идентификации в системе" LocalName: "Имя 'local' используется только для локальной идентификации в системе"
SyncPackageData: "Упаковка данных синхронизации" SyncPackageData: "Упаковка данных синхронизации"
@@ -203,7 +246,7 @@ SyncCustomApp: "Пользовательское приложение"
SyncLanguage: "Язык системы" SyncLanguage: "Язык системы"
SyncEdition: "Регион работы" SyncEdition: "Регион работы"
#upgrade node # обновление узла
NodeUpgrade: "Обновление узла {{ .name }}" NodeUpgrade: "Обновление узла {{ .name }}"
UpgradeCheck: "Проверить обновления узла" UpgradeCheck: "Проверить обновления узла"
UpgradeCheckLocal: "Локальные узлы не поддерживают массовое обновление, пропуск..." UpgradeCheckLocal: "Локальные узлы не поддерживают массовое обновление, пропуск..."
@@ -216,12 +259,11 @@ LoadAutoUpgradeNodesFailed: "Не удалось загрузить узлы а
AutoUpgradeNodes: "Узлы автообновления: {{ .nodes }}" AutoUpgradeNodes: "Узлы автообновления: {{ .nodes }}"
UpdateAutoUpgradeNodesStatusFailed: "Не удалось обновить статус узлов автообновления, ошибка: {{ .err }}" UpdateAutoUpgradeNodesStatusFailed: "Не удалось обновить статус узлов автообновления, ошибка: {{ .err }}"
#add node # добавление узла
MasterData: "Данные главного узла" MasterData: "Данные главного узла"
LoadSftpClient: "Загрузить SFTP-клиент" LoadSftpClient: "Загрузить SFTP-клиент"
PackageMasterData: "Создать архив резервной копии главного узла" PackageMasterData: "Создать архив резервной копии главного узла"
UploadBackup: "Загрузить резервные данные" UploadBackup: "Загрузить резервные данные"
MvBackup: "Переместить данные в резервный каталог"
TaskAddNode: "Добавить узел" TaskAddNode: "Добавить узел"
LoadNodeArch: "Получить информацию об архитектуре узла" LoadNodeArch: "Получить информацию об архитектуре узла"
LoadNodeArchDetail: "Обнаружена архитектура главного узла: {{ .local }}, архитектура дочернего узла: {{ .node }}" LoadNodeArchDetail: "Обнаружена архитектура главного узла: {{ .local }}, архитектура дочернего узла: {{ .node }}"
@@ -234,7 +276,35 @@ SendAgent: "Отправить установочный пакет узла"
StartService: "Запустить сервис" StartService: "Запустить сервис"
NoBackupNode: "Резервный узел в настоящее время пуст. Выберите резервный узел для сохранения и повторите попытку" NoBackupNode: "Резервный узел в настоящее время пуст. Выберите резервный узел для сохранения и повторите попытку"
#cmd # синхронизация файлов и образов узла
LocalNodeIpFailed: "Failed to get master node IP. Edit the master node and add IP address and SSH authentication information."
HandlePrivateKey: "Handle node private key"
HandlePublicKey: "Handle node public key"
ExchangeFile: "Start syncing {{ .sourcePath }} from node {{ .source }} to node {{ .dest }}:{{ .destPath }}"
NodeFile: "Node file"
ImageSyncTaskName: "Image sync {{ .count }} images"
SSLSyncTaskName: "Certificate sync {{ .count }} certificates"
AppSyncTaskName: "App sync {{ .name }}"
SSLSyncToNode: "Push certificate [{{ .cert }}] to node [{{ .node }}]"
ImageSyncSave: "Save image {{ .image }}"
ImageSyncSaveTags: "Save image tags {{ .tags }}"
ImageSyncToNode: "Sync image {{ .image }} to node {{ .node }}"
ImageSyncLoad: "Load image {{ .image }} on node {{ .node }}"
ImageSyncClean: "Clean temporary files for image {{ .image }}"
ImageSyncNoTag: "Image {{ .image }} has no tag and will be saved by image ID"
ImageSyncFrontendTagsIgnored: "No tags were found for image {{ .image }} on the source node. Frontend tags were ignored."
ImageSyncHandlePrivateKey: "Handle image sync node private key"
ImageSyncHandlePublicKey: "Handle image sync node public key"
ImageSyncTransfer: "Start transferring image temporary file: {{ .source }}:{{ .sourcePath }} -> {{ .dest }}:{{ .destPath }}"
# командная строка
SudoHelper: "Пожалуйста, используйте {{ .cmd }} или переключитесь на пользователя root"
UsernameNeed: "Для Enterprise-версии необходимо указать --username"
DBConnErr: "Ошибка: не удалось инициализировать соединение с базой данных, {{ .err }}"
SystemVersion: "Версия:"
SystemMode: "Режим:"
# командная строка - приложение
AppVersion: "Версия приложения" AppVersion: "Версия приложения"
AppCommands: "Команды приложения" AppCommands: "Команды приложения"
AppInit: "Инициализация приложения" AppInit: "Инициализация приложения"
@@ -246,12 +316,14 @@ AppMissVersion: "Отсутствует версия приложения, ис
AppVersionExist: "Версия уже существует" AppVersionExist: "Версия уже существует"
AppCreateSuccessful: "Успешно создано" AppCreateSuccessful: "Успешно создано"
AppWriteErr: "Не удалось записать файл {{ .name }} {{ .err }}" AppWriteErr: "Не удалось записать файл {{ .name }} {{ .err }}"
SudoHelper: "Пожалуйста, используйте {{ .cmd }} или переключитесь на пользователя root"
UsernameNeed: "Для Enterprise-версии необходимо указать --username" # командная строка - IP прослушивания
ListenIPCommands: "Переключить IP для прослушивания" ListenIPCommands: "Переключить IP для прослушивания"
ListenIPv4: "Прослушивание IPv4" ListenIPv4: "Прослушивание IPv4"
ListenIPv6: "Прослушивание IPv6" ListenIPv6: "Прослушивание IPv6"
ListenChangeSuccessful: "Переключено успешно Теперь прослушиваем {{ .value }}" ListenChangeSuccessful: "Переключено успешно Теперь прослушиваем {{ .value }}"
# командная строка - сброс
ResetCommands: "Сбросить информацию о системе" ResetCommands: "Сбросить информацию о системе"
ResetMFA: "Отменить двухфакторную аутентификацию 1Panel" ResetMFA: "Отменить двухфакторную аутентификацию 1Panel"
ResetHttps: "Отменить вход в 1Panel через https" ResetHttps: "Отменить вход в 1Panel через https"
@@ -259,12 +331,19 @@ ResetEntrance: "Отменить безопасный вход 1Panel"
ResetIPs: "Отменить ограничения авторизованных IP для 1Panel" ResetIPs: "Отменить ограничения авторизованных IP для 1Panel"
ResetDomain: "Отменить привязку домена доступа 1Panel" ResetDomain: "Отменить привязку домена доступа 1Panel"
ResetPasskey: "Сбросить passkey 1Panel" ResetPasskey: "Сбросить passkey 1Panel"
# командная строка - пользователь
UserList: "Получить список пользователей 1Panel" UserList: "Получить список пользователей 1Panel"
UserTableName: "Имя" UserTableName: "Имя"
UserTableMFAStatus: "Статус MFA" UserTableMFAStatus: "Статус MFA"
UserTableSuperAdmin: "Суперадмин" UserTableSuperAdmin: "Суперадмин"
UserTableCreatedAt: "Создано" UserTableCreatedAt: "Создано"
UserEmptyList: "Пользователи не найдены" UserEmptyList: "Пользователи не найдены"
UserInfo: "Получить информацию о панели"
UserInfoAddr: "Адрес панели:"
UserInfoPassHelp: "Подсказка: для изменения пароля можно выполнить команду:"
# командная строка - восстановление
RestoreCommands: "Откатить сервис и данные 1Panel" RestoreCommands: "Откатить сервис и данные 1Panel"
RestoreNoSuchFile: "Файлы для отката не найдены" RestoreNoSuchFile: "Файлы для отката не найдены"
RestoreStep1: "(1/5) Начинаем откат сервиса и данных 1Panel из каталога {{ .name }}..." RestoreStep1: "(1/5) Начинаем откат сервиса и данных 1Panel из каталога {{ .name }}..."
@@ -273,6 +352,8 @@ RestoreStep3: "(3/5) Откат скриптов 1Panel завершён"
RestoreStep4: "(4/5) Откат сервиса 1Panel завершён" RestoreStep4: "(4/5) Откат сервиса 1Panel завершён"
RestoreStep5: "(5/5) Откат данных 1Panel завершён" RestoreStep5: "(5/5) Откат данных 1Panel завершён"
RestoreSuccessful: "Откат завершён. Возвращено к версии {{ .version }}. Перезапускаем сервис..." RestoreSuccessful: "Откат завершён. Возвращено к версии {{ .version }}. Перезапускаем сервис..."
# командная строка - обновление
UpdateCommands: "Изменить информацию панели" UpdateCommands: "Изменить информацию панели"
UpdateUser: "Изменить информацию пользователя" UpdateUser: "Изменить информацию пользователя"
UpdatePassword: "Изменить пароль пользователя" UpdatePassword: "Изменить пароль пользователя"
@@ -299,28 +380,12 @@ UpdatePortResult: "Порт панели: {{ .name }}"
UpdatePortFirewallAdd: "Не удалось добавить правило фаервола для порта, {{ .err }}, пожалуйста, вручную добавьте порт {{ .name }} в правила фаервола." UpdatePortFirewallAdd: "Не удалось добавить правило фаервола для порта, {{ .err }}, пожалуйста, вручную добавьте порт {{ .name }} в правила фаервола."
UpdatePortFirewallDel: "Ошибка: не удалось удалить правило фаервола для порта, {{ .err }}" UpdatePortFirewallDel: "Ошибка: не удалось удалить правило фаервола для порта, {{ .err }}"
UpdatePortFirewallReload: "Не удалось перезагрузить фаервол, {{ .err }}, пожалуйста, вручную перезагрузите фаервол." UpdatePortFirewallReload: "Не удалось перезагрузить фаервол, {{ .err }}, пожалуйста, вручную перезагрузите фаервол."
UserInfo: "Получить информацию о панели"
UserInfoAddr: "Адрес панели:"
UserInfoPassHelp: "Подсказка: для изменения пароля можно выполнить команду:"
DBConnErr: "Ошибка: не удалось инициализировать соединение с базой данных, {{ .err }}"
SystemVersion: "Версия:"
SystemMode: "Режим:"
#mobile app # мобильное приложение
ErrVerifyToken: 'шибка проверки токена, пожалуйста, сбросьте и отсканируйте снова.' ErrVerifyToken: 'шибка проверки токена, пожалуйста, сбросьте и отсканируйте снова.'
ErrInvalidToken: 'Неверный токен, пожалуйста, сбросьте и отсканируйте снова.' ErrInvalidToken: 'Неверный токен, пожалуйста, сбросьте и отсканируйте снова.'
ErrExpiredToken: 'Токен истек, пожалуйста, сбросьте и отсканируйте снова.' ErrExpiredToken: 'Токен истек, пожалуйста, сбросьте и отсканируйте снова.'
#cluster # экспорт команд
ErrMasterDelete: "Невозможно удалить основной узел, сначала удалите подчиненные узлы."
ClusterNameIsExist: "Имя кластера уже существует."
AppStatusUnHealthy: "Получение статуса приложения аномально, пожалуйста, проверьте статус узлов установки в списке узлов."
MasterNodePortNotAvailable: "Проверка подключения порта {{ .port }} узла {{ .name }} не удалась, пожалуйста, проверьте настройки брандмауэра/группы безопасности и статус главного узла."
ClusterMasterNotExist: "Основной узел кластера отключен, пожалуйста, удалите дочерние узлы."
#ssl
ErrReqFailed: "{{.name}} запрос не удался: {{ .err }}"
#command
Name: "Название" Name: "Название"
Command: "Команда" Command: "Команда"
+160 -95
View File
@@ -1,68 +1,65 @@
# temel hatalar
ErrInvalidParams: 'İstek geçersiz: {{ .detail }}' ErrInvalidParams: 'İstek geçersiz: {{ .detail }}'
ErrTokenParse: 'Token hatası: {{ .detail }}' ErrTokenParse: 'Token hatası: {{ .detail }}'
ErrInitialPassword: 'Orijinal şifre yanlış' ErrInitialPassword: 'Orijinal şifre yanlış'
ErrInternalServer: 'Sunucu hatası: {{ .detail }}' ErrInternalServer: 'Sunucu hatası: {{ .detail }}'
ErrInternalServerKey: "İç sunucu hatası:"
ErrRecordExist: 'Kayıt zaten var' ErrRecordExist: 'Kayıt zaten var'
ErrRecordNotFound: 'Kayıt bulunamadı' ErrRecordNotFound: 'Kayıt bulunamadı'
ErrStructTransform: 'Dönüşüm hatası: {{ .err }}' ErrStructTransform: 'Dönüşüm hatası: {{ .err }}'
ErrNotLogin: 'Oturum açılmamış: {{ .detail }}'
ErrSessionDataNotFound: "Mevcut oturumun süresi doldu"
ErrSessionDataFormat: "Mevcut oturum verisi biçimi anormal"
ErrPasswordExpired: 'Şifre süresi doldu: {{ .detail }}'
ErrNotSupportType: 'Bu tür desteklenmiyor: {{ .name }}' ErrNotSupportType: 'Bu tür desteklenmiyor: {{ .name }}'
ErrProxy: 'İstek başarısız: {{ .detail }}' ErrDemoEnvironment: 'Demo modunda yok'
ErrApiConfigStatusInvalid: 'API kapalı: {{ .detail }}' ErrCmdTimeout: 'Komut zaman aşımına uğradı'
ErrApiConfigKeyInvalid: 'Geçersiz API anahtarı: {{ .detail }}' ErrPortInUsed: "{{ .name }} portu zaten kullanımda"
ErrApiConfigIPInvalid: 'IP izinli değil: {{ .detail }}' ErrFileNotFound: "{{ .name }} dosyası mevcut değil"
ErrApiConfigDisable: 'API erişimi kapalı: {{ .detail }}' ErrReqFailed: "{{.name}} istek başarısız: {{ .err }}"
ErrApiConfigKeyTimeInvalid: 'Zaman damgası hatalı: {{ .detail }}'
ErrLoginLocked: "Çok fazla başarısız deneme yapıldı. Giriş 5 dakika boyunca geçici olarak kilitlendi."
# request # istek ve güvenlik girişi
ErrNoSuchHost: "İstenen sunucu bulunamıyor {{ .err }}" ErrNoSuchHost: "İstenen sunucu bulunamıyor {{ .err }}"
ErrHttpReqNotFound: "İstenen kaynak bulunamıyor {{ .err }}" ErrHttpReqNotFound: "İstenen kaynak bulunamıyor {{ .err }}"
ErrHttpReqFailed: "İstek başarısız {{ .err }}" ErrHttpReqFailed: "İstek başarısız {{ .err }}"
ErrHttpReqTimeOut: "İstek zaman aşımına uğradı {{ .err }}" ErrHttpReqTimeOut: "İstek zaman aşımına uğradı {{ .err }}"
ErrCreateHttpClient: "İstek oluşturma başarısız {{ .err }}" ErrCreateHttpClient: "İstek oluşturma başarısız {{ .err }}"
ErrProxy: 'İstek başarısız: {{ .detail }}'
ErrProxySetting: "Proxy sunucu bilgisi kullanılamıyor {{ .err }}, lütfen kontrol edip tekrar deneyin" ErrProxySetting: "Proxy sunucu bilgisi kullanılamıyor {{ .err }}, lütfen kontrol edip tekrar deneyin"
ErrEntrance: "Güvenlik girişi bilgi hatası, lütfen kontrol edip tekrar deneyin"
ErrEntranceFormat: "{{ .name }} güvenlik girişi şu anda desteklenmiyor. Lütfen kontrol edip tekrar deneyin" ErrEntranceFormat: "{{ .name }} güvenlik girişi şu anda desteklenmiyor. Lütfen kontrol edip tekrar deneyin"
# common # oturum açma ve güvenlik
ErrDemoEnvironment: 'Demo modunda yok' ErrNotLogin: 'Oturum açılmamış: {{ .detail }}'
ErrCmdTimeout: 'Komut zaman aşımına uğradı' ErrSessionDataNotFound: "Mevcut oturumun süresi doldu"
ErrEntrance: "Güvenlik girişi bilgi hatası, lütfen kontrol edip tekrar deneyin" ErrSessionDataFormat: "Mevcut oturum verisi biçimi anormal"
ErrPasswordExpired: 'Şifre süresi doldu: {{ .detail }}'
ErrLoginLocked: "Çok fazla başarısız deneme yapıldı. Giriş 5 dakika boyunca geçici olarak kilitlendi."
ErrApiConfigStatusInvalid: 'API kapalı: {{ .detail }}'
ErrApiConfigKeyInvalid: 'Geçersiz API anahtarı: {{ .detail }}'
ErrApiConfigIPInvalid: 'IP izinli değil: {{ .detail }}'
ErrApiConfigDisable: 'API erişimi kapalı: {{ .detail }}'
ErrApiConfigKeyTimeInvalid: 'Zaman damgası hatalı: {{ .detail }}'
ErrPasskeyDisabled: "Passkey kullanmak için HTTPS etkinleştirilmelidir"
ErrPasskeyNotConfigured: "Passkey yapılandırılmamış"
ErrPasskeyLimit: "Passkey sınırına ulaşıldı (en fazla 5)"
ErrPasskeySession: "Passkey oturumu süresi dolmuş veya geçersiz"
ErrPasskeyDuplicate: "Passkey zaten mevcut"
ErrPasskeyVerify: "Passkey doğrulaması başarısız"
# kullanıcı ve izin
ErrNoSuchUser: "Kullanıcı bilgisi bulunamadı, lütfen kontrol edip tekrar deneyin"
ErrToMaster: "Bu kullanıcının ana düğümde bu işlemi yapma izni yok, lütfen kontrol edip tekrar deneyin"
ErrToNode: "Bu kullanıcının bu düğümde bu işlemi yapma izni yok, lütfen kontrol edip tekrar deneyin"
ErrRBAC: "Kullanıcı izinleri yetersiz, bu işlem yapılamaz. Lütfen kontrol edip tekrar deneyin"
ErrNoneNode: "Bu kullanıcının hiçbir düğüm izni yok. Lütfen yöneticiyle iletişime geçin veya kontrol edip tekrar deneyin"
ErrOnlySuperAdmin: "Bu özellik yalnızca süper yöneticiler tarafından kullanılabilir"
ErrRolePresetCannotDelete: "Sistem ön tanımlı rolleri silinemez"
ErrRolePresetCannotUpdate: "Sistem ön tanımlı rolleri güncellenemez"
ErrRoleBoundToUser: "Bu rol zaten kullanıcılara bağlı ve silinemez"
ErrRolePresetCannotBind: "Sistem ön tanımlı rolleri kullanıcılara atanamaz"
ErrNodeAdminMasterForbidden: "Ana düğüme düğüm yöneticisi izni eklenemez"
ErrSuperAdminCannotDelete: "Süper yönetici kullanıcılar silinemez"
ErrGroupIsDefault: "Varsayılan grup, silinemez" ErrGroupIsDefault: "Varsayılan grup, silinemez"
ErrGroupIsInUse: "Grup kullanımda ve silinemez." ErrGroupIsInUse: "Grup kullanımda ve silinemez."
ErrAIProxyUserGroupIsDefault: "Varsayılan kullanıcı grubu silinemez."
ErrAIProxyUserGroupInUse: "Kullanıcı grubu kullanımda ve silinemez."
ErrAIProxyUserGroupExists: "Kullanıcı grubu adı zaten mevcut."
ErrAIProxyBackendAccountExists: "Bu model hesabı AI Gateway hesap havuzuna zaten aktarılmış."
ErrAIProxyModelGroupInUse: "Model grubu kullanımda ve silinemez."
ErrAIProxyModelGroupExists: "Model grubu adı zaten mevcut."
ErrAIProxySensitiveGroupInUse: "Hassas kelime grubu kullanımda ve silinemez."
ErrAIProxySensitiveGroupExists: "Hassas kelime grubu adı zaten mevcut."
ErrLocalDelete: "Yerel düğüm silinemez"
ErrPortInUsed: "{{ .name }} portu zaten kullanımda"
ErrInternalServerKey: "İç sunucu hatası:"
MasterNode: "Ana Düğüm"
# app # lisans
CustomAppStoreFileValid: "Uygulama mağazası paketi .tar.gz formatında olmalıdır"
ErrFileNotFound: "{{ .name }} dosyası mevcut değil"
AppBackup: 'Uygulama yedekleme'
AppBackupPush: 'Uygulama yedek dosyası {{.file}} düğüm {{ .name }} a aktar'
ErrSourceTargetSame: 'Kaynak düğüm ve hedef düğüm aynı olamaz'
AppInstall: 'Düğüm {{ .targetNode }} üzerine {{ .name }} uygulamasını yükle'
AppInstallCheck: 'Uygulama kurulum ortamını kontrol et'
# backup
ErrBackupInUsed: 'Yedek hesabı görevde kullanılıyor'
ErrBackupCheck: 'Bağlantı testi başarısız: {{ .err }}'
ErrBackupLocal: "Yerel sunucu yedekleme hesabı bu işlemi desteklemiyor"
ErrBackupPublic: "Bu yedekleme hesabının herkese açık olmadığı tespit edildi, lütfen kontrol edip tekrar deneyin"
ErrOSSConn: "En son sürüm alınamıyor, lütfen sunucunun dış ağ bağlantısını kontrol edin."
#license
LicenseCheck: 'Lisansın mevcut olup olmadığını kontrol et' LicenseCheck: 'Lisansın mevcut olup olmadığını kontrol et'
ErrLicenseInUsed: 'Lisans zaten bağlı. Lütfen kontrol edip tekrar deneyin' ErrLicenseInUsed: 'Lisans zaten bağlı. Lütfen kontrol edip tekrar deneyin'
ErrLicenseExpired: 'Lisansın süresi dolmuş. Lütfen kontrol edip tekrar deneyin' ErrLicenseExpired: 'Lisansın süresi dolmuş. Lütfen kontrol edip tekrar deneyin'
@@ -77,6 +74,7 @@ ErrXpackExceptional: "Bu bölüm Business Sürüm gerektirir. Lisans durumunu Pa
ErrXpackLost: "Lisans yeniden deneme sınırına ulaştı. Panel Ayarları > Lisans bölümüne gidip manuel senkronizasyon çalıştırın" ErrXpackLost: "Lisans yeniden deneme sınırına ulaştı. Panel Ayarları > Lisans bölümüne gidip manuel senkronizasyon çalıştırın"
ErrEnterpriseLicenseRequired: "Enterprise Edition lisansı içe aktarılmamış. Önce bir lisans içe aktarın." ErrEnterpriseLicenseRequired: "Enterprise Edition lisansı içe aktarılmamış. Önce bir lisans içe aktarın."
ErrDeviceLost: "Lisans doğrulama için gerekli dosyalar eksik, lütfen kontrol edip tekrar deneyin" ErrDeviceLost: "Lisans doğrulama için gerekli dosyalar eksik, lütfen kontrol edip tekrar deneyin"
ErrDeviceErr: "Mevcut ortam lisans içe aktarma ortamıyla eşleşmiyor. Lütfen lisansı düzenleyip yeniden içe aktarın."
ErrXpackTimeout: "İstek zaman aşımı, ağ bağlantısı kararsız olabilir, lütfen daha sonra tekrar deneyin" ErrXpackTimeout: "İstek zaman aşımı, ağ bağlantısı kararsız olabilir, lütfen daha sonra tekrar deneyin"
ErrUnbindMaster: "Düğüm yönetiminde düğümler tespit edildi, mevcut lisansın bağı çözülemiyor, lütfen önce düğümleri kaldırın ve tekrar deneyin" ErrUnbindMaster: "Düğüm yönetiminde düğümler tespit edildi, mevcut lisansın bağı çözülemiyor, lütfen önce düğümleri kaldırın ve tekrar deneyin"
ErrFreeNodeLimit: "Eklenebilecek düğüm sayısı sınırına ulaşıldı. Satın aldıktan sonra tekrar deneyin." ErrFreeNodeLimit: "Eklenebilecek düğüm sayısı sınırına ulaşıldı. Satın aldıktan sonra tekrar deneyin."
@@ -91,21 +89,6 @@ ErrNodeUnbind: "Bu düğüm lisans bağlama aralığında değil, lütfen kontro
ErrNodeBind: "Bu düğüm zaten bir lisansa bağlı, lütfen kontrol edip tekrar deneyin" ErrNodeBind: "Bu düğüm zaten bir lisansa bağlı, lütfen kontrol edip tekrar deneyin"
ErrNodeLocalRollback: "Ana düğüm doğrudan rollback'i desteklemez. Rollback için '1pctl restore' komutunu manuel çalıştırın" ErrNodeLocalRollback: "Ana düğüm doğrudan rollback'i desteklemez. Rollback için '1pctl restore' komutunu manuel çalıştırın"
ErrIntlLicense: "Mevcut sürüm uluslararası sürüm lisansının içe aktarılmasını henüz desteklemiyor. Yakında" ErrIntlLicense: "Mevcut sürüm uluslararası sürüm lisansının içe aktarılmasını henüz desteklemiyor. Yakında"
# user
ErrNoSuchUser: "Kullanıcı bilgisi bulunamadı, lütfen kontrol edip tekrar deneyin"
ErrToMaster: "Bu kullanıcının ana düğümde bu işlemi yapma izni yok, lütfen kontrol edip tekrar deneyin"
ErrToNode: "Bu kullanıcının bu düğümde bu işlemi yapma izni yok, lütfen kontrol edip tekrar deneyin"
ErrRBAC: "Kullanıcı izinleri yetersiz, bu işlem yapılamaz. Lütfen kontrol edip tekrar deneyin"
ErrNoneNode: "Bu kullanıcının hiçbir düğüm izni yok. Lütfen yöneticiyle iletişime geçin veya kontrol edip tekrar deneyin"
ErrOnlySuperAdmin: "Bu özellik yalnızca süper yöneticiler tarafından kullanılabilir"
ErrRolePresetCannotDelete: "Sistem ön tanımlı rolleri silinemez"
ErrRolePresetCannotUpdate: "Sistem ön tanımlı rolleri güncellenemez"
ErrRoleBoundToUser: "Bu rol zaten kullanıcılara bağlı ve silinemez"
ErrRolePresetCannotBind: "Sistem ön tanımlı rolleri kullanıcılara atanamaz"
ErrNodeAdminMasterForbidden: "Ana düğüme düğüm yöneticisi izni eklenemez"
ErrSuperAdminCannotDelete: "Süper yönetici kullanıcılar silinemez"
InvalidRequestBodyType: "Geçersiz istek gövdesi formatı, lütfen içeriğin format gereksinimlerine uygun olduğunu kontrol edip tekrar deneyin" InvalidRequestBodyType: "Geçersiz istek gövdesi formatı, lütfen içeriğin format gereksinimlerine uygun olduğunu kontrol edip tekrar deneyin"
InvalidLicenseCodeType: "Sağlanan lisans kodu formatı geçersiz, lütfen kontrol edip tekrar deneyin" InvalidLicenseCodeType: "Sağlanan lisans kodu formatı geçersiz, lütfen kontrol edip tekrar deneyin"
LicenseNotFoundType: "Lisans bulunamadı, sistemde sağlanan lisansla eşleşen bir kayıt yok. Lütfen kontrol edip tekrar deneyin" LicenseNotFoundType: "Lisans bulunamadı, sistemde sağlanan lisansla eşleşen bir kayıt yok. Lütfen kontrol edip tekrar deneyin"
@@ -116,10 +99,65 @@ InvalidAssigneeType: "Lisans ataması için hedef kullanıcı veya cihaz bilgisi
LicenseUsageNotFoundType: "Kullanım kaydı bulunamadı. Bu lisans henüz etkinleştirilmemiş veya kullanılmamış. Lütfen kontrol edip tekrar deneyin" LicenseUsageNotFoundType: "Kullanım kaydı bulunamadı. Bu lisans henüz etkinleştirilmemiş veya kullanılmamış. Lütfen kontrol edip tekrar deneyin"
LicenseUsageLimitExceededType: "Bu lisans zaten başka bir düğüme bağlı. Lütfen kontrol edip tekrar deneyin" LicenseUsageLimitExceededType: "Bu lisans zaten başka bir düğüme bağlı. Lütfen kontrol edip tekrar deneyin"
# alert # düğüm ve küme
MasterNode: "Ana Düğüm"
Node: "Düğüm"
ErrLocalDelete: "Yerel düğüm silinemez"
ErrMasterDelete: "Ana düğümü silinemiyor, lütfen önce alt düğümleri silin."
ClusterNameIsExist: "Küme adı zaten var."
AppStatusUnHealthy: "Uygulama durumu alımı anormal, lütfen düğüm listesindeki yükleme düğümü durumunu kontrol edin."
MasterNodePortNotAvailable: "Düğüm {{ .name }} portu {{ .port }} bağlantı doğrulaması başarısız oldu, lütfen güvenlik duvarı/güvenlik grubu ayarlarını ve ana düğüm durumunu kontrol edin."
ClusterMasterNotExist: "Küme ana düğümü bağlantısı kesildi, lütfen alt düğümleri silin."
# sanal makine
ErrVMNotFound: "Sanal makine mevcut değil"
ErrVMAlreadyExists: "Sanal makine zaten mevcut"
ErrVMStoragePathInUse: "Depolama havuzu yolu zaten [{{ .name }}] tarafından kullanılıyor"
ErrVMRunning: "Sanal makine çalışıyor"
ErrVMLibvirtConnect: "libvirt bağlantısı başarısız: {{ .detail }}"
ErrVMPermission: "Sanal makine işlemi için izin yok: {{ .detail }}"
ErrVMNetworkNotFound: "Sanal makine ağı mevcut değil: {{ .detail }}"
ErrVMInvalidPath: "Geçersiz sanal makine yolu: {{ .detail }}"
ErrVMInvalidInput: "Geçersiz sanal makine parametresi: {{ .detail }}"
ErrVMCommandFailed: "Sanal makine komutu başarısız: {{ .err }}"
VMSnapshotCreateTask: "Create snapshot [{{ .snapshot }}] for virtual machine [{{ .vm }}]"
VMSnapshotCreateStep: "Create virtual machine snapshot [{{ .snapshot }}]"
VMSnapshotRecoverTask: "Recover snapshot [{{ .snapshot }}] for virtual machine [{{ .vm }}]"
VMSnapshotRecoverStep: "Recover virtual machine snapshot [{{ .snapshot }}]"
VMSnapshotDeleteTask: "Delete snapshot [{{ .snapshot }}] for virtual machine [{{ .vm }}]"
VMSnapshotDeleteStep: "Delete virtual machine snapshot [{{ .snapshot }}]"
# uygulama
CustomAppStoreFileValid: "Uygulama mağazası paketi .tar.gz formatında olmalıdır"
AppBackup: 'Uygulama yedekleme'
AppBackupPush: 'Uygulama yedek dosyası {{.file}} düğüm {{ .name }} a aktar'
ErrSourceTargetSame: 'Kaynak düğüm ve hedef düğüm aynı olamaz'
AppInstall: 'Düğüm {{ .targetNode }} üzerine {{ .name }} uygulamasını yükle'
AppInstallCheck: 'Uygulama kurulum ortamını kontrol et'
# yedekleme
ErrBackupInUsed: 'Yedek hesabı görevde kullanılıyor'
ErrBackupCheck: 'Bağlantı testi başarısız: {{ .err }}'
ErrBackupLocal: "Yerel sunucu yedekleme hesabı bu işlemi desteklemiyor"
ErrBackupPublic: "Bu yedekleme hesabının herkese açık olmadığı tespit edildi, lütfen kontrol edip tekrar deneyin"
ErrOSSConn: "En son sürüm alınamıyor, lütfen sunucunun dış ağ bağlantısını kontrol edin."
MvBackup: "Verileri yedek dizinine taşı"
# uyarı
ErrAlertSync: "Uyarı bilgisi senkronizasyon hatası, lütfen kontrol edip tekrar deneyin" ErrAlertSync: "Uyarı bilgisi senkronizasyon hatası, lütfen kontrol edip tekrar deneyin"
# task # AI ağ geçidi
ErrAIProxyUserGroupIsDefault: "Varsayılan kullanıcı grubu silinemez."
ErrAIProxyUserGroupInUse: "Kullanıcı grubu kullanımda ve silinemez."
ErrAIProxyUserGroupExists: "Kullanıcı grubu adı zaten mevcut."
ErrAIProxyBackendAccountExists: "Bu model hesabı AI Gateway hesap havuzuna zaten aktarılmış."
ErrAIProxyModelGroupInUse: "Model grubu kullanımda ve silinemez."
ErrAIProxyModelGroupExists: "Model grubu adı zaten mevcut."
ErrAIProxySensitiveGroupInUse: "Hassas kelime grubu kullanımda ve silinemez."
ErrAIProxySensitiveGroupExists: "Hassas kelime grubu adı zaten mevcut."
AIBenchmarkRun: "AI kıyaslama testini çalıştır"
# görev
TaskStart: "{{ .name }} görevi başladı [BAŞLANGIÇ]" TaskStart: "{{ .name }} görevi başladı [BAŞLANGIÇ]"
TaskEnd: "{{ .name }} görevi bitti [TAMAMLANDI]" TaskEnd: "{{ .name }} görevi bitti [TAMAMLANDI]"
TaskFailed: "{{ .name }} görevi başarısız" TaskFailed: "{{ .name }} görevi başarısız"
@@ -133,6 +171,16 @@ TaskUpgrade: "Yükseltme"
TaskSync: 'Senkronize' TaskSync: 'Senkronize'
TaskSyncForNode: "Düğüm Verilerini Senkronize Et" TaskSyncForNode: "Düğüm Verilerini Senkronize Et"
TaskBackup: "Yedekleme" TaskBackup: "Yedekleme"
TaskPush: "Gönder"
TaskRsync: "Sync"
SuccessStatus: "{{ .name }} başarılı"
FailedStatus: "{{ .name }} başarısız {{ .err }}"
Start: "Başla"
SubTask: "Alt görev"
Skip: "Hataları atla ve devam et..."
Success: "Başarılı"
# ajan toplu görevi
BatchInstallAgent: "Aracıları toplu kur" BatchInstallAgent: "Aracıları toplu kur"
DispatchAgentInstallTasks: "Aracı kurulum görevlerini gönder" DispatchAgentInstallTasks: "Aracı kurulum görevlerini gönder"
BatchUpgradeAgent: "Aracıları toplu yükselt" BatchUpgradeAgent: "Aracıları toplu yükselt"
@@ -166,20 +214,15 @@ AgentOperateStart: "Başlat"
AgentOperateStop: "Durdur" AgentOperateStop: "Durdur"
AgentOperateRestart: "Yeniden başlat" AgentOperateRestart: "Yeniden başlat"
AgentOperateDelete: "Sil" AgentOperateDelete: "Sil"
SuccessStatus: "{{ .name }} başarılı"
FailedStatus: "{{ .name }} başarısız {{ .err }}" # uygulama ve beceri görevi
Start: "Başla"
SubTask: "Alt görev"
Skip: "Hataları atla ve devam et..."
PushAppInstallTaskToNode: "Uygulama kurulum görevini düğüme [{{ .name }}] gönder" PushAppInstallTaskToNode: "Uygulama kurulum görevini düğüme [{{ .name }}] gönder"
TaskPush: "Gönder"
AppInstallTask: "Uygulama kurulum görevi" AppInstallTask: "Uygulama kurulum görevi"
PushAppFailed: "Uygulama kurulum görevi gönderilemedi" PushAppFailed: "Uygulama kurulum görevi gönderilemedi"
SkillHubInstallTask: "Skill yükle [{{ .name }}]" SkillHubInstallTask: "Skill yükle [{{ .name }}]"
SkillHubInstallToTarget: "Skill hedefe yükle [{{ .name }}]" SkillHubInstallToTarget: "Skill hedefe yükle [{{ .name }}]"
Success: "Başarılı"
#script # betik kitaplığı
ScriptLibrary: "Betik Kütüphanesi" ScriptLibrary: "Betik Kütüphanesi"
RemoteScriptLibrary: "Uzak Komut Dosyası Kütüphanesi" RemoteScriptLibrary: "Uzak Komut Dosyası Kütüphanesi"
ScriptSyncSkip: "Mevcut betik kütüphanesi zaten en son sürüm" ScriptSyncSkip: "Mevcut betik kütüphanesi zaten en son sürüm"
@@ -187,7 +230,7 @@ DownloadData: "Betik kütüphanesi dosyası data.yaml indiriliyor"
DownloadPackage: "Betik kütüphanesi paketi indiriliyor" DownloadPackage: "Betik kütüphanesi paketi indiriliyor"
AnalyticCompletion: "Analiz tamamlandı, şimdi veritabanına senkronize ediliyor..." AnalyticCompletion: "Analiz tamamlandı, şimdi veritabanına senkronize ediliyor..."
Node: "Düğüm" # düğüm senkronizasyonu
SyncNode: "Verileri {{ .name }} düğümüne senkronize et" SyncNode: "Verileri {{ .name }} düğümüne senkronize et"
LocalName: "'local' adı yalnızca sistem yerel tanımlaması için kullanılır" LocalName: "'local' adı yalnızca sistem yerel tanımlaması için kullanılır"
SyncPackageData: "Paket senkronizasyon verisi" SyncPackageData: "Paket senkronizasyon verisi"
@@ -203,7 +246,7 @@ SyncCustomApp: "Özel Uygulama"
SyncLanguage: "Sistem Dili" SyncLanguage: "Sistem Dili"
SyncEdition: "Çalışma Bölgesi" SyncEdition: "Çalışma Bölgesi"
#upgrade node # düğüm yükseltme
NodeUpgrade: "Düğümü yükselt {{ .name }}" NodeUpgrade: "Düğümü yükselt {{ .name }}"
UpgradeCheck: "Düğüm güncellemelerini kontrol et" UpgradeCheck: "Düğüm güncellemelerini kontrol et"
UpgradeCheckLocal: "Yerel düğümler toplu yükseltmeleri desteklemiyor, atlanıyor..." UpgradeCheckLocal: "Yerel düğümler toplu yükseltmeleri desteklemiyor, atlanıyor..."
@@ -216,12 +259,11 @@ LoadAutoUpgradeNodesFailed: "Otomatik yükseltme düğümleri yüklenemedi, hata
AutoUpgradeNodes: "Otomatik yükseltme düğümleri: {{ .nodes }}" AutoUpgradeNodes: "Otomatik yükseltme düğümleri: {{ .nodes }}"
UpdateAutoUpgradeNodesStatusFailed: "Otomatik yükseltme düğümlerinin durumu güncellenemedi, hata: {{ .err }}" UpdateAutoUpgradeNodesStatusFailed: "Otomatik yükseltme düğümlerinin durumu güncellenemedi, hata: {{ .err }}"
#add node # düğüm ekleme
MasterData: "Ana Düğüm Verisi" MasterData: "Ana Düğüm Verisi"
LoadSftpClient: "SFTP İstemcisini Yükle" LoadSftpClient: "SFTP İstemcisini Yükle"
PackageMasterData: "Ana düğüm yedek paketi oluştur" PackageMasterData: "Ana düğüm yedek paketi oluştur"
UploadBackup: "Yedek verileri yükle" UploadBackup: "Yedek verileri yükle"
MvBackup: "Verileri yedek dizinine taşı"
TaskAddNode: "Düğüm ekle" TaskAddNode: "Düğüm ekle"
LoadNodeArch: "Düğüm mimari bilgilerini al" LoadNodeArch: "Düğüm mimari bilgilerini al"
LoadNodeArchDetail: "Ana düğüm mimarisi tespit edildi: {{ .local }}, alt düğüm mimarisi: {{ .node }}" LoadNodeArchDetail: "Ana düğüm mimarisi tespit edildi: {{ .local }}, alt düğüm mimarisi: {{ .node }}"
@@ -234,7 +276,35 @@ SendAgent: "Düğüm kurulum paketini dağıt"
StartService: "Servisi başlat" StartService: "Servisi başlat"
NoBackupNode: "Yedek düğüm şu anda boş. Lütfen kaydetmek için bir yedek düğüm seçin ve tekrar deneyin" NoBackupNode: "Yedek düğüm şu anda boş. Lütfen kaydetmek için bir yedek düğüm seçin ve tekrar deneyin"
#cmd # düğüm dosyası ve imaj senkronizasyonu
LocalNodeIpFailed: "Failed to get master node IP. Edit the master node and add IP address and SSH authentication information."
HandlePrivateKey: "Handle node private key"
HandlePublicKey: "Handle node public key"
ExchangeFile: "Start syncing {{ .sourcePath }} from node {{ .source }} to node {{ .dest }}:{{ .destPath }}"
NodeFile: "Node file"
ImageSyncTaskName: "Image sync {{ .count }} images"
SSLSyncTaskName: "Certificate sync {{ .count }} certificates"
AppSyncTaskName: "App sync {{ .name }}"
SSLSyncToNode: "Push certificate [{{ .cert }}] to node [{{ .node }}]"
ImageSyncSave: "Save image {{ .image }}"
ImageSyncSaveTags: "Save image tags {{ .tags }}"
ImageSyncToNode: "Sync image {{ .image }} to node {{ .node }}"
ImageSyncLoad: "Load image {{ .image }} on node {{ .node }}"
ImageSyncClean: "Clean temporary files for image {{ .image }}"
ImageSyncNoTag: "Image {{ .image }} has no tag and will be saved by image ID"
ImageSyncFrontendTagsIgnored: "No tags were found for image {{ .image }} on the source node. Frontend tags were ignored."
ImageSyncHandlePrivateKey: "Handle image sync node private key"
ImageSyncHandlePublicKey: "Handle image sync node public key"
ImageSyncTransfer: "Start transferring image temporary file: {{ .source }}:{{ .sourcePath }} -> {{ .dest }}:{{ .destPath }}"
# komut satırı
SudoHelper: "Lütfen {{ .cmd }} kullanın veya root kullanıcısına geçin"
UsernameNeed: "Enterprise sürümü --username belirtmelidir"
DBConnErr: "Hata: Veritabanı bağlantısını başlatma başarısız, {{ .err }}"
SystemVersion: "sürüm: "
SystemMode: "mod: "
# komut satırı - uygulama
AppVersion: "Uygulama sürümü" AppVersion: "Uygulama sürümü"
AppCommands: "Uygulama ile ilgili komutlar" AppCommands: "Uygulama ile ilgili komutlar"
AppInit: "Uygulamayı başlat" AppInit: "Uygulamayı başlat"
@@ -246,12 +316,14 @@ AppMissVersion: "Uygulama sürümü eksik, belirtmek için -v kullanın"
AppVersionExist: "Sürüm zaten mevcut" AppVersionExist: "Sürüm zaten mevcut"
AppCreateSuccessful: "Oluşturma başarılı" AppCreateSuccessful: "Oluşturma başarılı"
AppWriteErr: "Dosya {{ .name }} yazma başarısız {{ .err }}" AppWriteErr: "Dosya {{ .name }} yazma başarısız {{ .err }}"
SudoHelper: "Lütfen {{ .cmd }} kullanın veya root kullanıcısına geçin"
UsernameNeed: "Enterprise sürümü --username belirtmelidir" # komut satırı - dinleme IP
ListenIPCommands: "Dinleme IP'sini değiştir" ListenIPCommands: "Dinleme IP'sini değiştir"
ListenIPv4: "IPv4'te dinle" ListenIPv4: "IPv4'te dinle"
ListenIPv6: "IPv6'da dinle" ListenIPv6: "IPv6'da dinle"
ListenChangeSuccessful: "Değişiklik başarılı Şimdi {{ .value }} üzerinde dinleniyor" ListenChangeSuccessful: "Değişiklik başarılı Şimdi {{ .value }} üzerinde dinleniyor"
# komut satırı - sıfırlama
ResetCommands: "Sistem bilgilerini sıfırla" ResetCommands: "Sistem bilgilerini sıfırla"
ResetMFA: "1Panel iki faktörlü kimlik doğrulamayı iptal et" ResetMFA: "1Panel iki faktörlü kimlik doğrulamayı iptal et"
ResetHttps: "1Panel https girişini iptal et" ResetHttps: "1Panel https girişini iptal et"
@@ -259,12 +331,19 @@ ResetEntrance: "1Panel güvenli girişi iptal et"
ResetIPs: "1Panel yetkili IP kısıtlamalarını iptal et" ResetIPs: "1Panel yetkili IP kısıtlamalarını iptal et"
ResetDomain: "1Panel alan adı bağlamasını iptal et" ResetDomain: "1Panel alan adı bağlamasını iptal et"
ResetPasskey: "1Panel passkey'lerini sıfırla" ResetPasskey: "1Panel passkey'lerini sıfırla"
# komut satırı - kullanıcı
UserList: "1Panel kullanıcı listesini getir" UserList: "1Panel kullanıcı listesini getir"
UserTableName: "Ad" UserTableName: "Ad"
UserTableMFAStatus: "MFA Durumu" UserTableMFAStatus: "MFA Durumu"
UserTableSuperAdmin: "Süper Yönetici" UserTableSuperAdmin: "Süper Yönetici"
UserTableCreatedAt: "Oluşturulma" UserTableCreatedAt: "Oluşturulma"
UserEmptyList: "Kullanıcı bulunamadı" UserEmptyList: "Kullanıcı bulunamadı"
UserInfo: "Panel bilgilerini al"
UserInfoAddr: "Panel adresi: "
UserInfoPassHelp: "İpucu: Şifreyi değiştirmek için komutu çalıştırabilirsiniz: "
# komut satırı - geri yükleme
RestoreCommands: "1Panel servisini ve verilerini geri al" RestoreCommands: "1Panel servisini ve verilerini geri al"
RestoreNoSuchFile: "Rollback için dosya bulunamadı" RestoreNoSuchFile: "Rollback için dosya bulunamadı"
RestoreStep1: "(1/5) {{ .name }} dizininden 1Panel hizmeti ve verileri geri alınıyor..." RestoreStep1: "(1/5) {{ .name }} dizininden 1Panel hizmeti ve verileri geri alınıyor..."
@@ -273,6 +352,8 @@ RestoreStep3: "(3/5) 1Panel betikleri için geri alma tamamlandı"
RestoreStep4: "(4/5) 1Panel hizmeti için geri alma tamamlandı" RestoreStep4: "(4/5) 1Panel hizmeti için geri alma tamamlandı"
RestoreStep5: "(5/5) 1Panel verileri için geri alma tamamlandı" RestoreStep5: "(5/5) 1Panel verileri için geri alma tamamlandı"
RestoreSuccessful: "Geri alma tamamlandı. {{ .version }} sürümüne dönüldü. Hizmet yeniden başlatılıyor..." RestoreSuccessful: "Geri alma tamamlandı. {{ .version }} sürümüne dönüldü. Hizmet yeniden başlatılıyor..."
# komut satırı - güncelleme
UpdateCommands: "Panel bilgilerini güncelle" UpdateCommands: "Panel bilgilerini güncelle"
UpdateUser: "Kullanıcı bilgilerini güncelle" UpdateUser: "Kullanıcı bilgilerini güncelle"
UpdatePassword: "Kullanıcı şifresini güncelle" UpdatePassword: "Kullanıcı şifresini güncelle"
@@ -299,28 +380,12 @@ UpdatePortResult: "Panel Portu: {{ .name }}"
UpdatePortFirewallAdd: "Güvenlik duvarı port kuralı ekleme başarısız, {{ .err }}, lütfen {{ .name }} portunu güvenlik duvarı kurallarına manuel olarak ekleyin." UpdatePortFirewallAdd: "Güvenlik duvarı port kuralı ekleme başarısız, {{ .err }}, lütfen {{ .name }} portunu güvenlik duvarı kurallarına manuel olarak ekleyin."
UpdatePortFirewallDel: "Hata: Güvenlik duvarı portu silme başarısız, {{ .err }}" UpdatePortFirewallDel: "Hata: Güvenlik duvarı portu silme başarısız, {{ .err }}"
UpdatePortFirewallReload: "Güvenlik duvarını yeniden yükleme başarısız, {{ .err }}, lütfen güvenlik duvarını manuel olarak yeniden yükleyin." UpdatePortFirewallReload: "Güvenlik duvarını yeniden yükleme başarısız, {{ .err }}, lütfen güvenlik duvarını manuel olarak yeniden yükleyin."
UserInfo: "Panel bilgilerini al"
UserInfoAddr: "Panel adresi: "
UserInfoPassHelp: "İpucu: Şifreyi değiştirmek için komutu çalıştırabilirsiniz: "
DBConnErr: "Hata: Veritabanı bağlantısını başlatma başarısız, {{ .err }}"
SystemVersion: "sürüm: "
SystemMode: "mod: "
#mobile app # mobil uygulama
ErrVerifyToken: 'Token doğrulama hatası, lütfen sıfırlayın ve tekrar tarayın.' ErrVerifyToken: 'Token doğrulama hatası, lütfen sıfırlayın ve tekrar tarayın.'
ErrInvalidToken: 'Geçersiz token, lütfen sıfırlayın ve tekrar tarayın.' ErrInvalidToken: 'Geçersiz token, lütfen sıfırlayın ve tekrar tarayın.'
ErrExpiredToken: 'Token süresi dolmuş, lütfen sıfırlayın ve tekrar tarayın.' ErrExpiredToken: 'Token süresi dolmuş, lütfen sıfırlayın ve tekrar tarayın.'
#cluster # komut dışa aktarma
ErrMasterDelete: "Ana düğümü silinemiyor, lütfen önce alt düğümleri silin."
ClusterNameIsExist: "Küme adı zaten var."
AppStatusUnHealthy: "Uygulama durumu alımı anormal, lütfen düğüm listesindeki yükleme düğümü durumunu kontrol edin."
MasterNodePortNotAvailable: "Düğüm {{ .name }} portu {{ .port }} bağlantı doğrulaması başarısız oldu, lütfen güvenlik duvarı/güvenlik grubu ayarlarını ve ana düğüm durumunu kontrol edin."
ClusterMasterNotExist: "Küme ana düğümü bağlantısı kesildi, lütfen alt düğümleri silin."
#ssl
ErrReqFailed: "{{.name}} istek başarısız: {{ .err }}"
#command
Name: "Ad" Name: "Ad"
Command: "Komut" Command: "Komut"

Some files were not shown because too many files have changed in this diff Show More