mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2026-10-09 16:00:29 +00:00
Compare commits
123
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d114933fe9 | ||
|
|
432412e596 | ||
|
|
1b577e3d41 | ||
|
|
eda9641d35 | ||
|
|
6808e4892c | ||
|
|
0d71cd4db2 | ||
|
|
b6b3304a71 | ||
|
|
59a0a573ed | ||
|
|
e82d686940 | ||
|
|
b48bb88aa1 | ||
|
|
5ce9ec5b64 | ||
|
|
740f3549ad | ||
|
|
aa8a9e8b1e | ||
|
|
14218e3495 | ||
|
|
c526eb2962 | ||
|
|
1ff8292be4 | ||
|
|
d4394616af | ||
|
|
462ca6b373 | ||
|
|
657c3ad37a | ||
|
|
90d11a3b74 | ||
|
|
883f3db725 | ||
|
|
75da72c265 | ||
|
|
78eef15f5b | ||
|
|
735cf3cc71 | ||
|
|
99c5d9a8b2 | ||
|
|
3a0d2039d0 | ||
|
|
98e2d6390a | ||
|
|
975e7f9f58 | ||
|
|
77c90a26f8 | ||
|
|
17cb12df8b | ||
|
|
c986b04667 | ||
|
|
754e016f20 | ||
|
|
f67ce75492 | ||
|
|
e236ca5607 | ||
|
|
10e74c4fe4 | ||
|
|
473c0a5ff2 | ||
|
|
7fbe6e4091 | ||
|
|
65dbb53a07 | ||
|
|
c21910c203 | ||
|
|
1728511bad | ||
|
|
e63f6672f8 | ||
|
|
7fa9754ce7 | ||
|
|
475e4ca629 | ||
|
|
32dee74edf | ||
|
|
6715559925 | ||
|
|
2f380c9f2f | ||
|
|
0aebb0d2db | ||
|
|
b7cf9aab2b | ||
|
|
ea2f1875bc | ||
|
|
83524940ed | ||
|
|
8c33eb8409 | ||
|
|
644655af86 | ||
|
|
8082f4d2ca | ||
|
|
3c896bc5f8 | ||
|
|
5c7ce6d8d4 | ||
|
|
222702f66b | ||
|
|
b3b3feb1b9 | ||
|
|
133140040b | ||
|
|
d70f903432 | ||
|
|
f77f305316 | ||
|
|
13b5908442 | ||
|
|
d1335db986 | ||
|
|
1e8836ad95 | ||
|
|
d155217ce3 | ||
|
|
9ddb996a44 | ||
|
|
226eccf5f1 | ||
|
|
4b2d6f0ef2 | ||
|
|
f1c9ad45a7 | ||
|
|
93489c85fa | ||
|
|
8cead06d7b | ||
|
|
625cd9f32f | ||
|
|
9aab3b42af | ||
|
|
6684cd57d7 | ||
|
|
00d95d6e19 | ||
|
|
36f03e5daf | ||
|
|
7c395a6bf8 | ||
|
|
e9a7cac5fd | ||
|
|
9f00b431d4 | ||
|
|
1705d44378 | ||
|
|
537e2c730c | ||
|
|
b4dc6b1ab0 | ||
|
|
1f22285cf4 | ||
|
|
1d546236e4 | ||
|
|
982e0bbd3e | ||
|
|
5a67a62733 | ||
|
|
961ebd30a1 | ||
|
|
9819546694 | ||
|
|
5c8d391a73 | ||
|
|
0e84b9a2a7 | ||
|
|
1f58da501e | ||
|
|
0041184a3e | ||
|
|
112468949d | ||
|
|
7e03e94460 | ||
|
|
fd9b299b14 | ||
|
|
37932d7fb2 | ||
|
|
f0f2087f54 | ||
|
|
f3de09e5d7 | ||
|
|
1a8c1613a4 | ||
|
|
5209275f28 | ||
|
|
924e59d948 | ||
|
|
87a39cab3a | ||
|
|
f9a70757a1 | ||
|
|
741acee393 | ||
|
|
c964a02088 | ||
|
|
ba71613ae6 | ||
|
|
5493b41381 | ||
|
|
c3f45d4787 | ||
|
|
a8a92da483 | ||
|
|
a77e61a861 | ||
|
|
e589728987 | ||
|
|
cc3cdef5f3 | ||
|
|
7101af0594 | ||
|
|
df6cda7143 | ||
|
|
62beb534d2 | ||
|
|
9a70bf1c2d | ||
|
|
6f4559c7cd | ||
|
|
8b2bcdc814 | ||
|
|
0f6ddf26fd | ||
|
|
ebe472a9db | ||
|
|
c1a87baad7 | ||
|
|
c7f185a184 | ||
|
|
4ca2ba5482 | ||
|
|
727b74895d |
+25
-1
@@ -1,33 +1,43 @@
|
||||
name: Create Release And Upload Cloudflare R2
|
||||
name: Build And Publish (OSS + R2)
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
jobs:
|
||||
create-release:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '22.19.0'
|
||||
|
||||
- name: Build Web
|
||||
run: |
|
||||
cd frontend && npm install && npm run build:pro
|
||||
env:
|
||||
NODE_OPTIONS: --max-old-space-size=8192
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.24'
|
||||
cache-dependency-path: |
|
||||
core/go.sum
|
||||
agent/go.sum
|
||||
|
||||
- name: Build Release
|
||||
uses: goreleaser/goreleaser-action@v6
|
||||
with:
|
||||
distribution: goreleaser
|
||||
version: '~> v2'
|
||||
args: release --skip=publish --clean
|
||||
|
||||
- name: Upload Assets
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
@@ -36,10 +46,24 @@ jobs:
|
||||
files: |
|
||||
dist/*.tar.gz
|
||||
dist/checksums.txt
|
||||
|
||||
- name: Setup OSSUTIL
|
||||
uses: yizhoumo/setup-ossutil@v2
|
||||
with:
|
||||
endpoint: ${{ secrets.OSS_ENDPOINT }}
|
||||
access-key-id: ${{ secrets.OSS_ACCESS_KEY_ID }}
|
||||
access-key-secret: ${{ secrets.OSS_ACCESS_KEY_SECRET }}
|
||||
ossutil-version: '1.7.18'
|
||||
|
||||
- name: Upload Assets to OSS
|
||||
run: |
|
||||
ossutil cp -r dist/ oss://resource-fit2cloud-com/1panel/package/v2/stable/${{ github.ref_name }}/release/ --include "*.tar.gz" --include "checksums.txt" --only-current-dir --force
|
||||
|
||||
- name: Setup Rclone
|
||||
uses: AnimMouse/setup-rclone@v1
|
||||
with:
|
||||
rclone_config: ${{ secrets.RCLONE_CONFIG }}
|
||||
|
||||
- name: Upload to Cloudflare R2
|
||||
run: |
|
||||
rclone copy dist/ cloudflare_r2:package/v2/stable/${{ github.ref_name }}/release/ --include "*.tar.gz" --include "checksums.txt" --progress
|
||||
@@ -1,47 +0,0 @@
|
||||
name: Create Release And Upload assets
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
jobs:
|
||||
create-release:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v4
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '22.19.0'
|
||||
- name: Build Web
|
||||
run: |
|
||||
cd frontend && npm install && npm run build:pro
|
||||
env:
|
||||
NODE_OPTIONS: --max-old-space-size=8192
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.24'
|
||||
- name: Build Release
|
||||
uses: goreleaser/goreleaser-action@v6
|
||||
with:
|
||||
distribution: goreleaser
|
||||
version: '~> v2'
|
||||
args: release --skip=publish --clean
|
||||
- name: Upload Assets
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
with:
|
||||
draft: true
|
||||
files: |
|
||||
dist/*.tar.gz
|
||||
dist/checksums.txt
|
||||
- name: Setup OSSUTIL
|
||||
uses: yizhoumo/setup-ossutil@v2
|
||||
with:
|
||||
endpoint: ${{ secrets.OSS_ENDPOINT }}
|
||||
access-key-id: ${{ secrets.OSS_ACCESS_KEY_ID }}
|
||||
access-key-secret: ${{ secrets.OSS_ACCESS_KEY_SECRET }}
|
||||
ossutil-version: '1.7.18'
|
||||
- name: Upload Assets to OSS
|
||||
run: ossutil cp -r dist/ oss://resource-fit2cloud-com/1panel/package/v2/stable/${{ github.ref_name }}/release/ --include "*.tar.gz" --include "checksums.txt" --only-current-dir --force
|
||||
@@ -1,4 +1,5 @@
|
||||
<p align="center"><a href="https://1panel.pro"><img src="https://resource.1panel.pro/img/1panel-logo.png" alt="1Panel" width="300" /></a></p>
|
||||
<h3 align="center">Take control of your VPS with 1Panel</h3>
|
||||
<p align="center">
|
||||
<a href="https://trendshift.io/repositories/2462" target="_blank"><img src="https://trendshift.io/api/badge/repositories/2462" alt="1Panel-dev%2F1Panel | Trendshift" style="width: 240px; height: auto;" /></a>
|
||||
</p>
|
||||
@@ -31,39 +32,28 @@
|
||||
------------------------------
|
||||
## What is 1Panel?
|
||||
|
||||
1Panel is a modern, open-source Linux server management panel that streamlines administration through an intuitive, clean web interface.
|
||||
1Panel is a modern, open-source VPS control panel that streamlines administration through an intuitive, clean web interface.
|
||||
|
||||
## Key Features
|
||||
|
||||
🔹 **AI Integration**
|
||||
Seamlessly deploy OpenClaw agents, host local LLMs via Ollama, and monitor GPU utilization—all within a unified workspace engineered for efficient AI development and inference.
|
||||
|
||||
🔹 **One-Click Website Deployment**
|
||||
Launch production-ready websites instantly with automatic domain binding, SSL certificate provisioning, and configuration—zero manual setup required.
|
||||
|
||||
🔹 **Curated App Marketplace**
|
||||
Discover, install, and update trusted open-source applications (WordPress, MySQL, Redis, and more) with a single click.
|
||||
|
||||
🔹 **Centralized Server Management**
|
||||
Monitor system resources and manage files, databases, containers, and services effortlessly through a unified, intuitive dashboard.
|
||||
|
||||
🔹 **Enterprise-Grade Security**
|
||||
Strengthen defenses with container isolation, firewall controls, audit logging, and secure deployment practices—ensuring compliance and peace of mind.
|
||||
|
||||
🔹 **Intelligent Backup & Restore**
|
||||
Schedule automated backups or perform instant restores to local storage or leading cloud platforms (AWS S3, Cloudflare R2, and more), with flexible retention and destination options.
|
||||
- **One-Click OpenClaw Deployment**: Seamlessly deploy OpenClaw agents, host local LLMs using Ollama, and monitor GPU utilization—all within a unified workspace.
|
||||
- **One-Click Website Deployment**: Launch production-ready websites instantly with automatic domain binding, SSL certificate provisioning, and configuration—zero manual setup required.
|
||||
- **Curated App Marketplace**: Discover, install, and update trusted open-source applications (Nextcloud, Bitwarden, Umami, and more) with a single click.
|
||||
- **Centralized Server Management**: Monitor system resources and manage files, databases, containers, and services effortlessly through a unified, intuitive dashboard.
|
||||
- **Enterprise-Grade Security**: Strengthen your defenses with container isolation, firewall controls, audit logging, and secure deployment practices—ensuring compliance and peace of mind.
|
||||
- **Intelligent Backup & Restore**: Schedule automated backups or perform instant restores to local storage or major cloud platforms (AWS S3, Cloudflare R2, and more), with flexible retention and destination options.
|
||||
|
||||
## Quick Start
|
||||
|
||||
Execute the script below and follow the prompts to install 1Panel:
|
||||
|
||||
```bash
|
||||
bash -c "$(curl -sSL https://resource.fit2cloud.com/1panel/package/v2/quick_start.sh)"
|
||||
bash -c "$(curl -sSL https://resource.1panel.pro/v2/quick_start.sh)"
|
||||
```
|
||||
|
||||
## Screenshot
|
||||
|
||||

|
||||

|
||||
|
||||
## Star History
|
||||
|
||||
|
||||
+267
-1
@@ -113,7 +113,7 @@ func (b *BaseApi) UpdateAgentModelConfig(c *gin.Context) {
|
||||
|
||||
// @Tags AI
|
||||
// @Summary Get Providers
|
||||
// @Success 200 {object} []dto.ProviderInfo
|
||||
// @Success 200 {array} dto.ProviderInfo
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /ai/agents/providers [get]
|
||||
@@ -271,6 +271,252 @@ func (b *BaseApi) UpdateAgentFeishuConfig(c *gin.Context) {
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
// @Tags AI
|
||||
// @Summary Get Agent Telegram channel config
|
||||
// @Accept json
|
||||
// @Param request body dto.AgentTelegramConfigReq true "request"
|
||||
// @Success 200 {object} dto.AgentTelegramConfig
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /ai/agents/channel/telegram/get [post]
|
||||
func (b *BaseApi) GetAgentTelegramConfig(c *gin.Context) {
|
||||
var req dto.AgentTelegramConfigReq
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
data, err := agentService.GetTelegramConfig(req)
|
||||
if err != nil {
|
||||
helper.BadRequest(c, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, data)
|
||||
}
|
||||
|
||||
// @Tags AI
|
||||
// @Summary Update Agent Telegram channel config
|
||||
// @Accept json
|
||||
// @Param request body dto.AgentTelegramConfigUpdateReq true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /ai/agents/channel/telegram/update [post]
|
||||
func (b *BaseApi) UpdateAgentTelegramConfig(c *gin.Context) {
|
||||
var req dto.AgentTelegramConfigUpdateReq
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
if err := agentService.UpdateTelegramConfig(req); err != nil {
|
||||
helper.BadRequest(c, err)
|
||||
return
|
||||
}
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
// @Tags AI
|
||||
// @Summary Get Agent Discord channel config
|
||||
// @Accept json
|
||||
// @Param request body dto.AgentDiscordConfigReq true "request"
|
||||
// @Success 200 {object} dto.AgentDiscordConfig
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /ai/agents/channel/discord/get [post]
|
||||
func (b *BaseApi) GetAgentDiscordConfig(c *gin.Context) {
|
||||
var req dto.AgentDiscordConfigReq
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
data, err := agentService.GetDiscordConfig(req)
|
||||
if err != nil {
|
||||
helper.BadRequest(c, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, data)
|
||||
}
|
||||
|
||||
// @Tags AI
|
||||
// @Summary Update Agent Discord channel config
|
||||
// @Accept json
|
||||
// @Param request body dto.AgentDiscordConfigUpdateReq true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /ai/agents/channel/discord/update [post]
|
||||
func (b *BaseApi) UpdateAgentDiscordConfig(c *gin.Context) {
|
||||
var req dto.AgentDiscordConfigUpdateReq
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
if err := agentService.UpdateDiscordConfig(req); err != nil {
|
||||
helper.BadRequest(c, err)
|
||||
return
|
||||
}
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
// @Tags AI
|
||||
// @Summary Get Agent QQ Bot channel config
|
||||
// @Accept json
|
||||
// @Param request body dto.AgentQQBotConfigReq true "request"
|
||||
// @Success 200 {object} dto.AgentQQBotConfig
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /ai/agents/channel/qqbot/get [post]
|
||||
func (b *BaseApi) GetAgentQQBotConfig(c *gin.Context) {
|
||||
var req dto.AgentQQBotConfigReq
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
data, err := agentService.GetQQBotConfig(req)
|
||||
if err != nil {
|
||||
helper.BadRequest(c, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, data)
|
||||
}
|
||||
|
||||
// @Tags AI
|
||||
// @Summary Update Agent QQ Bot channel config
|
||||
// @Accept json
|
||||
// @Param request body dto.AgentQQBotConfigUpdateReq true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /ai/agents/channel/qqbot/update [post]
|
||||
func (b *BaseApi) UpdateAgentQQBotConfig(c *gin.Context) {
|
||||
var req dto.AgentQQBotConfigUpdateReq
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
if err := agentService.UpdateQQBotConfig(req); err != nil {
|
||||
helper.BadRequest(c, err)
|
||||
return
|
||||
}
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
// @Tags AI
|
||||
// @Summary Install Agent plugin
|
||||
// @Accept json
|
||||
// @Param request body dto.AgentPluginInstallReq true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /ai/agents/plugin/install [post]
|
||||
func (b *BaseApi) InstallAgentPlugin(c *gin.Context) {
|
||||
var req dto.AgentPluginInstallReq
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
if err := agentService.InstallPlugin(req); err != nil {
|
||||
helper.BadRequest(c, err)
|
||||
return
|
||||
}
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
// @Tags AI
|
||||
// @Summary Check Agent plugin installation status
|
||||
// @Accept json
|
||||
// @Param request body dto.AgentPluginCheckReq true "request"
|
||||
// @Success 200 {object} dto.AgentPluginStatus
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /ai/agents/plugin/check [post]
|
||||
func (b *BaseApi) CheckAgentPlugin(c *gin.Context) {
|
||||
var req dto.AgentPluginCheckReq
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
data, err := agentService.CheckPlugin(req)
|
||||
if err != nil {
|
||||
helper.BadRequest(c, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, data)
|
||||
}
|
||||
|
||||
// @Tags AI
|
||||
// @Summary Get Agent Browser config
|
||||
// @Accept json
|
||||
// @Param request body dto.AgentBrowserConfigReq true "request"
|
||||
// @Success 200 {object} dto.AgentBrowserConfig
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /ai/agents/browser/get [post]
|
||||
func (b *BaseApi) GetAgentBrowserConfig(c *gin.Context) {
|
||||
var req dto.AgentBrowserConfigReq
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
data, err := agentService.GetBrowserConfig(req)
|
||||
if err != nil {
|
||||
helper.BadRequest(c, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, data)
|
||||
}
|
||||
|
||||
// @Tags AI
|
||||
// @Summary Update Agent Browser config
|
||||
// @Accept json
|
||||
// @Param request body dto.AgentBrowserConfigUpdateReq true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /ai/agents/browser/update [post]
|
||||
func (b *BaseApi) UpdateAgentBrowserConfig(c *gin.Context) {
|
||||
var req dto.AgentBrowserConfigUpdateReq
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
if err := agentService.UpdateBrowserConfig(req); err != nil {
|
||||
helper.BadRequest(c, err)
|
||||
return
|
||||
}
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
// @Tags AI
|
||||
// @Summary Get Agent Other config
|
||||
// @Accept json
|
||||
// @Param request body dto.AgentOtherConfigReq true "request"
|
||||
// @Success 200 {object} dto.AgentOtherConfig
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /ai/agents/other/get [post]
|
||||
func (b *BaseApi) GetAgentOtherConfig(c *gin.Context) {
|
||||
var req dto.AgentOtherConfigReq
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
data, err := agentService.GetOtherConfig(req)
|
||||
if err != nil {
|
||||
helper.BadRequest(c, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, data)
|
||||
}
|
||||
|
||||
// @Tags AI
|
||||
// @Summary Update Agent Other config
|
||||
// @Accept json
|
||||
// @Param request body dto.AgentOtherConfigUpdateReq true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /ai/agents/other/update [post]
|
||||
func (b *BaseApi) UpdateAgentOtherConfig(c *gin.Context) {
|
||||
var req dto.AgentOtherConfigUpdateReq
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
if err := agentService.UpdateOtherConfig(req); err != nil {
|
||||
helper.BadRequest(c, err)
|
||||
return
|
||||
}
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
// @Tags AI
|
||||
// @Summary Approve Agent Feishu pairing code
|
||||
// @Accept json
|
||||
@@ -290,3 +536,23 @@ func (b *BaseApi) ApproveAgentFeishuPairing(c *gin.Context) {
|
||||
}
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
// @Tags AI
|
||||
// @Summary Approve Agent channel pairing code
|
||||
// @Accept json
|
||||
// @Param request body dto.AgentChannelPairingApproveReq true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /ai/agents/channel/pairing/approve [post]
|
||||
func (b *BaseApi) ApproveAgentChannelPairing(c *gin.Context) {
|
||||
var req dto.AgentChannelPairingApproveReq
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
if err := agentService.ApproveChannelPairing(req); err != nil {
|
||||
helper.BadRequest(c, err)
|
||||
return
|
||||
}
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ func (b *BaseApi) LoadPort(c *gin.Context) {
|
||||
// @Success 200 {object} response.DatabaseConn
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /apps/installed/conninfo [POST]
|
||||
// @Router /apps/installed/conninfo [post]
|
||||
func (b *BaseApi) LoadConnInfo(c *gin.Context) {
|
||||
var req dto.OperationWithNameAndType
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
@@ -349,3 +349,15 @@ func (b *BaseApi) GetAppInstallInfo(c *gin.Context) {
|
||||
}
|
||||
helper.SuccessWithData(c, info)
|
||||
}
|
||||
|
||||
func (b *BaseApi) UpdateAppInstallSort(c *gin.Context) {
|
||||
var req request.AppInstallSort
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
if err := appInstallService.UpdateSort(req); err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
@@ -306,27 +306,6 @@ func (b *BaseApi) ContainerCreate(c *gin.Context) {
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
// @Tags Container
|
||||
// @Summary Create container by command
|
||||
// @Accept json
|
||||
// @Param request body dto.ContainerCreateByCommand true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /containers/command [post]
|
||||
func (b *BaseApi) ContainerCreateByCommand(c *gin.Context) {
|
||||
var req dto.ContainerCreateByCommand
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err := containerService.ContainerCreateByCommand(req); err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
// @Tags Container
|
||||
// @Summary Upgrade container
|
||||
// @Accept json
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
// @Tags Container Docker
|
||||
// @Summary Load docker status
|
||||
// @Produce json
|
||||
// @Success 200 {string} dto.DockerStatus
|
||||
// @Success 200 {object} dto.DockerStatus
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /containers/docker/status [get]
|
||||
@@ -24,7 +24,7 @@ func (b *BaseApi) LoadDockerStatus(c *gin.Context) {
|
||||
// @Tags Container Docker
|
||||
// @Summary Load docker daemon.json
|
||||
// @Produce json
|
||||
// @Success 200 {object} string
|
||||
// @Success 200 {string} string
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /containers/daemonjson/file [get]
|
||||
|
||||
@@ -32,7 +32,7 @@ func (b *BaseApi) PageTasks(c *gin.Context) {
|
||||
|
||||
// @Tags TaskLog
|
||||
// @Summary Get the number of executing tasks
|
||||
// @Success 200 {object} int64
|
||||
// @Success 200 {integer} int64
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /logs/tasks/executing/count [get]
|
||||
|
||||
@@ -506,7 +506,7 @@ func (b *BaseApi) GetProxyConfig(c *gin.Context) {
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /websites/proxies/update [post]
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"修改网站 [domain] 反向代理配置 ","formatEN":"Update domain [domain] proxy config"}
|
||||
// @x-panel-log {"bodyKeys":["id","name","operate"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"修改 [operate] 网站 [domain] 反向代理配置 [name] ","formatEN":"Update [operate] domain [domain] proxy config [name]"}
|
||||
func (b *BaseApi) UpdateProxyConfig(c *gin.Context) {
|
||||
var req request.WebsiteProxyConfig
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
@@ -520,6 +520,50 @@ func (b *BaseApi) UpdateProxyConfig(c *gin.Context) {
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
// @Tags Website
|
||||
// @Summary Delete proxy config
|
||||
// @Accept json
|
||||
// @Param request body request.WebsiteProxyDel true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /websites/proxies/delete [post]
|
||||
// @x-panel-log {"bodyKeys":["id","name"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"删除网站 [domain] 反向代理配置 [name] ","formatEN":"Delete domain [domain] proxy config [name]"}
|
||||
func (b *BaseApi) DeleteProxyConfig(c *gin.Context) {
|
||||
var req request.WebsiteProxyDel
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
err := websiteService.DeleteProxy(req)
|
||||
if err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
// @Tags Website
|
||||
// @Summary Update proxy config status
|
||||
// @Accept json
|
||||
// @Param request body request.WebsiteProxyStatusUpdate true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /websites/proxies/status [post]
|
||||
// @x-panel-log {"bodyKeys":["id","name","status"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"修改网站 [domain] 反向代理配置 [name] 状态 [status] ","formatEN":"Update domain [domain] proxy config [name] status [status]"}
|
||||
func (b *BaseApi) UpdateProxyConfigStatus(c *gin.Context) {
|
||||
var req request.WebsiteProxyStatusUpdate
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
err := websiteService.UpdateProxyStatus(req)
|
||||
if err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
// @Tags Website
|
||||
// @Summary Update proxy file
|
||||
// @Accept json
|
||||
@@ -528,7 +572,7 @@ func (b *BaseApi) UpdateProxyConfig(c *gin.Context) {
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /websites/proxies/file [post]
|
||||
// @x-panel-log {"bodyKeys":["websiteID"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteID","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"更新反向代理文件 [domain]","formatEN":"Nginx conf proxy file update [domain]"}
|
||||
// @x-panel-log {"bodyKeys":["websiteID","name"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteID","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"修改网站 [domain] 反向代理配置文件 [name] ","formatEN":"Update domain [domain] proxy config file [name]"}
|
||||
func (b *BaseApi) UpdateProxyConfigFile(c *gin.Context) {
|
||||
var req request.NginxProxyUpdate
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
|
||||
+152
-35
@@ -6,9 +6,10 @@ type AgentCreateReq struct {
|
||||
Name string `json:"name" validate:"required"`
|
||||
AppVersion string `json:"appVersion" validate:"required"`
|
||||
WebUIPort int `json:"webUIPort" validate:"required"`
|
||||
BridgePort int `json:"bridgePort" validate:"required"`
|
||||
Provider string `json:"provider" validate:"required"`
|
||||
Model string `json:"model" validate:"required"`
|
||||
BridgePort int `json:"bridgePort"`
|
||||
AgentType string `json:"agentType"`
|
||||
Provider string `json:"provider"`
|
||||
Model string `json:"model"`
|
||||
APIType string `json:"apiType"`
|
||||
MaxTokens int `json:"maxTokens"`
|
||||
ContextWindow int `json:"contextWindow"`
|
||||
@@ -33,6 +34,7 @@ type AgentCreateReq struct {
|
||||
type AgentItem struct {
|
||||
ID uint `json:"id"`
|
||||
Name string `json:"name"`
|
||||
AgentType string `json:"agentType"`
|
||||
Provider string `json:"provider"`
|
||||
ProviderName string `json:"providerName"`
|
||||
Model string `json:"model"`
|
||||
@@ -73,28 +75,30 @@ type AgentModelConfigUpdateReq struct {
|
||||
}
|
||||
|
||||
type AgentAccountCreateReq struct {
|
||||
Provider string `json:"provider" validate:"required"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
APIKey string `json:"apiKey" validate:"required"`
|
||||
BaseURL string `json:"baseURL"`
|
||||
Model string `json:"model"`
|
||||
APIType string `json:"apiType"`
|
||||
MaxTokens int `json:"maxTokens"`
|
||||
ContextWindow int `json:"contextWindow"`
|
||||
Remark string `json:"remark"`
|
||||
Provider string `json:"provider" validate:"required"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
APIKey string `json:"apiKey" validate:"required"`
|
||||
RememberAPIKey bool `json:"rememberApiKey"`
|
||||
BaseURL string `json:"baseURL"`
|
||||
Model string `json:"model"`
|
||||
APIType string `json:"apiType"`
|
||||
MaxTokens int `json:"maxTokens"`
|
||||
ContextWindow int `json:"contextWindow"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
type AgentAccountUpdateReq struct {
|
||||
ID uint `json:"id" validate:"required"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
APIKey string `json:"apiKey" validate:"required"`
|
||||
BaseURL string `json:"baseURL"`
|
||||
Model string `json:"model"`
|
||||
APIType string `json:"apiType"`
|
||||
MaxTokens int `json:"maxTokens"`
|
||||
ContextWindow int `json:"contextWindow"`
|
||||
Remark string `json:"remark"`
|
||||
SyncAgents bool `json:"syncAgents"`
|
||||
ID uint `json:"id" validate:"required"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
APIKey string `json:"apiKey" validate:"required"`
|
||||
RememberAPIKey bool `json:"rememberApiKey"`
|
||||
BaseURL string `json:"baseURL"`
|
||||
Model string `json:"model"`
|
||||
APIType string `json:"apiType"`
|
||||
MaxTokens int `json:"maxTokens"`
|
||||
ContextWindow int `json:"contextWindow"`
|
||||
Remark string `json:"remark"`
|
||||
SyncAgents bool `json:"syncAgents"`
|
||||
}
|
||||
|
||||
type AgentAccountVerifyReq struct {
|
||||
@@ -114,19 +118,20 @@ type AgentAccountSearch struct {
|
||||
}
|
||||
|
||||
type AgentAccountInfo struct {
|
||||
ID uint `json:"id"`
|
||||
Provider string `json:"provider"`
|
||||
ProviderName string `json:"providerName"`
|
||||
Name string `json:"name"`
|
||||
APIKey string `json:"apiKey"`
|
||||
BaseURL string `json:"baseUrl"`
|
||||
Model string `json:"model"`
|
||||
APIType string `json:"apiType"`
|
||||
MaxTokens int `json:"maxTokens"`
|
||||
ContextWindow int `json:"contextWindow"`
|
||||
Verified bool `json:"verified"`
|
||||
Remark string `json:"remark"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
ID uint `json:"id"`
|
||||
Provider string `json:"provider"`
|
||||
ProviderName string `json:"providerName"`
|
||||
Name string `json:"name"`
|
||||
APIKey string `json:"apiKey"`
|
||||
RememberAPIKey bool `json:"rememberApiKey"`
|
||||
BaseURL string `json:"baseUrl"`
|
||||
Model string `json:"model"`
|
||||
APIType string `json:"apiType"`
|
||||
MaxTokens int `json:"maxTokens"`
|
||||
ContextWindow int `json:"contextWindow"`
|
||||
Verified bool `json:"verified"`
|
||||
Remark string `json:"remark"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
}
|
||||
|
||||
type ProviderModelInfo struct {
|
||||
@@ -167,3 +172,115 @@ type AgentFeishuConfig struct {
|
||||
AppID string `json:"appId"`
|
||||
AppSecret string `json:"appSecret"`
|
||||
}
|
||||
|
||||
type AgentTelegramConfigReq struct {
|
||||
AgentID uint `json:"agentId" validate:"required"`
|
||||
}
|
||||
|
||||
type AgentTelegramConfigUpdateReq struct {
|
||||
AgentID uint `json:"agentId" validate:"required"`
|
||||
Enabled bool `json:"enabled"`
|
||||
DmPolicy string `json:"dmPolicy" validate:"required"`
|
||||
BotToken string `json:"botToken" validate:"required"`
|
||||
Proxy string `json:"proxy"`
|
||||
}
|
||||
|
||||
type AgentTelegramConfig struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
DmPolicy string `json:"dmPolicy"`
|
||||
BotToken string `json:"botToken"`
|
||||
Proxy string `json:"proxy"`
|
||||
}
|
||||
|
||||
type AgentChannelPairingApproveReq struct {
|
||||
AgentID uint `json:"agentId" validate:"required"`
|
||||
Type string `json:"type" validate:"required,oneof=feishu telegram discord"`
|
||||
PairingCode string `json:"pairingCode" validate:"required"`
|
||||
}
|
||||
|
||||
type AgentQQBotConfigReq struct {
|
||||
AgentID uint `json:"agentId" validate:"required"`
|
||||
}
|
||||
|
||||
type AgentQQBotConfigUpdateReq struct {
|
||||
AgentID uint `json:"agentId" validate:"required"`
|
||||
Enabled bool `json:"enabled"`
|
||||
AppID string `json:"appId" validate:"required"`
|
||||
ClientSecret string `json:"clientSecret" validate:"required"`
|
||||
}
|
||||
|
||||
type AgentQQBotConfig struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
AppID string `json:"appId"`
|
||||
ClientSecret string `json:"clientSecret"`
|
||||
Installed bool `json:"installed"`
|
||||
}
|
||||
|
||||
type AgentPluginInstallReq struct {
|
||||
AgentID uint `json:"agentId" validate:"required"`
|
||||
Type string `json:"type" validate:"required,oneof=qqbot"`
|
||||
TaskID string `json:"taskID" validate:"required"`
|
||||
}
|
||||
|
||||
type AgentPluginCheckReq struct {
|
||||
AgentID uint `json:"agentId" validate:"required"`
|
||||
Type string `json:"type" validate:"required,oneof=qqbot"`
|
||||
}
|
||||
|
||||
type AgentPluginStatus struct {
|
||||
Installed bool `json:"installed"`
|
||||
}
|
||||
|
||||
type AgentDiscordConfigReq struct {
|
||||
AgentID uint `json:"agentId" validate:"required"`
|
||||
}
|
||||
|
||||
type AgentDiscordConfigUpdateReq struct {
|
||||
AgentID uint `json:"agentId" validate:"required"`
|
||||
Enabled bool `json:"enabled"`
|
||||
DmPolicy string `json:"dmPolicy" validate:"required"`
|
||||
GroupPolicy string `json:"groupPolicy" validate:"required,oneof=open allowlist disabled"`
|
||||
Token string `json:"token" validate:"required"`
|
||||
Proxy string `json:"proxy"`
|
||||
}
|
||||
|
||||
type AgentDiscordConfig struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
DmPolicy string `json:"dmPolicy"`
|
||||
GroupPolicy string `json:"groupPolicy"`
|
||||
Token string `json:"token"`
|
||||
Proxy string `json:"proxy"`
|
||||
}
|
||||
|
||||
type AgentBrowserConfigReq struct {
|
||||
AgentID uint `json:"agentId" validate:"required"`
|
||||
}
|
||||
|
||||
type AgentBrowserConfigUpdateReq struct {
|
||||
AgentID uint `json:"agentId" validate:"required"`
|
||||
Enabled bool `json:"enabled"`
|
||||
Headless bool `json:"headless"`
|
||||
NoSandbox bool `json:"noSandbox"`
|
||||
DefaultProfile string `json:"defaultProfile" validate:"required"`
|
||||
}
|
||||
|
||||
type AgentBrowserConfig struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
ExecutablePath string `json:"executablePath"`
|
||||
Headless bool `json:"headless"`
|
||||
NoSandbox bool `json:"noSandbox"`
|
||||
DefaultProfile string `json:"defaultProfile"`
|
||||
}
|
||||
|
||||
type AgentOtherConfigReq struct {
|
||||
AgentID uint `json:"agentId" validate:"required"`
|
||||
}
|
||||
|
||||
type AgentOtherConfigUpdateReq struct {
|
||||
AgentID uint `json:"agentId" validate:"required"`
|
||||
UserTimezone string `json:"userTimezone" validate:"required"`
|
||||
}
|
||||
|
||||
type AgentOtherConfig struct {
|
||||
UserTimezone string `json:"userTimezone"`
|
||||
}
|
||||
|
||||
@@ -95,10 +95,16 @@ type ContainerOperate struct {
|
||||
Privileged bool `json:"privileged"`
|
||||
AutoRemove bool `json:"autoRemove"`
|
||||
Volumes []VolumeHelper `json:"volumes"`
|
||||
ExtraHosts []ExtraHost `json:"extraHosts"`
|
||||
Labels []string `json:"labels"`
|
||||
Env []string `json:"env"`
|
||||
RestartPolicy string `json:"restartPolicy"`
|
||||
}
|
||||
|
||||
type ExtraHost struct {
|
||||
Hostname string `json:"hostname"`
|
||||
IP string `json:"ip"`
|
||||
}
|
||||
type ContainerNetwork struct {
|
||||
Network string `json:"network"`
|
||||
Ipv4 string `json:"ipv4"`
|
||||
|
||||
@@ -138,3 +138,12 @@ type AppUpdateVersion struct {
|
||||
AppInstallID uint `json:"appInstallID" validate:"required"`
|
||||
UpdateVersion string `json:"updateVersion"`
|
||||
}
|
||||
|
||||
type AppInstallSortItem struct {
|
||||
InstallID uint `json:"installID"`
|
||||
SortOrder int `json:"sortOrder"`
|
||||
}
|
||||
|
||||
type AppInstallSort struct {
|
||||
Items []AppInstallSortItem `json:"items" validate:"required"`
|
||||
}
|
||||
|
||||
@@ -272,6 +272,17 @@ type WebsiteProxyConfig struct {
|
||||
CorsConfig
|
||||
}
|
||||
|
||||
type WebsiteProxyDelete struct {
|
||||
ID uint `json:"id" validate:"required"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
}
|
||||
|
||||
type WebsiteProxyStatusUpdate struct {
|
||||
ID uint `json:"id" validate:"required"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
Status string `json:"status" validate:"required"`
|
||||
}
|
||||
|
||||
type CorsConfig struct {
|
||||
Cors bool `json:"cors"`
|
||||
AllowOrigins string `json:"allowOrigins"`
|
||||
|
||||
@@ -6,8 +6,8 @@ type WebsiteSSLSearch struct {
|
||||
dto.PageInfo
|
||||
AcmeAccountID string `json:"acmeAccountID"`
|
||||
Domain string `json:"domain"`
|
||||
OrderBy string `json:"orderBy" validate:"required,oneof=expire_date"`
|
||||
Order string `json:"order" validate:"required,oneof=null ascending descending"`
|
||||
OrderBy string `json:"orderBy" validate:"omitempty,oneof=created_at expire_date"`
|
||||
Order string `json:"order" validate:"omitempty,oneof=null ascending descending"`
|
||||
}
|
||||
|
||||
type WebsiteSSLListReq struct {
|
||||
|
||||
@@ -126,6 +126,7 @@ type AppInstallDTO struct {
|
||||
WebUI string `json:"webUI"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
Favorite bool `json:"favorite"`
|
||||
SortOrder int `json:"sortOrder"`
|
||||
App AppDetail `json:"app"`
|
||||
Container string `json:"container"`
|
||||
IsEdit bool `json:"isEdit"`
|
||||
|
||||
@@ -3,6 +3,7 @@ package model
|
||||
type Agent struct {
|
||||
BaseModel
|
||||
Name string `json:"name" gorm:"not null;unique"`
|
||||
AgentType string `json:"agentType" gorm:"default:openclaw"`
|
||||
Provider string `json:"provider"`
|
||||
Model string `json:"model"`
|
||||
APIType string `json:"apiType"`
|
||||
|
||||
@@ -2,16 +2,17 @@ package model
|
||||
|
||||
type AgentAccount struct {
|
||||
BaseModel
|
||||
Provider string `json:"provider"`
|
||||
Name string `json:"name"`
|
||||
APIKey string `json:"apiKey"`
|
||||
BaseURL string `json:"baseUrl"`
|
||||
Model string `json:"model"`
|
||||
APIType string `json:"apiType"`
|
||||
MaxTokens int `json:"maxTokens"`
|
||||
ContextWindow int `json:"contextWindow"`
|
||||
Verified bool `json:"verified"`
|
||||
Remark string `json:"remark"`
|
||||
Provider string `json:"provider"`
|
||||
Name string `json:"name"`
|
||||
APIKey string `json:"apiKey"`
|
||||
BaseURL string `json:"baseUrl"`
|
||||
Model string `json:"model"`
|
||||
APIType string `json:"apiType"`
|
||||
MaxTokens int `json:"maxTokens"`
|
||||
ContextWindow int `json:"contextWindow"`
|
||||
RememberAPIKey bool `json:"rememberApiKey"`
|
||||
Verified bool `json:"verified"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
func (AgentAccount) TableName() string {
|
||||
|
||||
@@ -26,6 +26,7 @@ type AppInstall struct {
|
||||
HttpsPort int `json:"httpsPort"`
|
||||
WebUI string `json:"webUI"`
|
||||
Favorite bool `json:"favorite"`
|
||||
SortOrder int `json:"sortOrder" gorm:"default:0"`
|
||||
|
||||
App App `json:"app" gorm:"-:migration"`
|
||||
}
|
||||
|
||||
+117
-56
@@ -20,16 +20,34 @@ type Meta struct {
|
||||
}
|
||||
|
||||
var catalog = map[string]Meta{
|
||||
"custom": {
|
||||
Key: "custom",
|
||||
DisplayName: "Custom",
|
||||
Sort: 10,
|
||||
DefaultBaseURL: "",
|
||||
EnvKey: "CUSTOM_API_KEY",
|
||||
Enabled: true,
|
||||
Models: []Model{},
|
||||
},
|
||||
"ollama": {
|
||||
Key: "ollama",
|
||||
DisplayName: "Ollama",
|
||||
Sort: 10,
|
||||
Sort: 15,
|
||||
Enabled: true,
|
||||
},
|
||||
"vllm": {
|
||||
Key: "vllm",
|
||||
DisplayName: "vLLM",
|
||||
Sort: 20,
|
||||
DefaultBaseURL: "",
|
||||
EnvKey: "VLLM_API_KEY",
|
||||
Enabled: true,
|
||||
Models: []Model{},
|
||||
},
|
||||
"deepseek": {
|
||||
Key: "deepseek",
|
||||
DisplayName: "DeepSeek",
|
||||
Sort: 20,
|
||||
Sort: 25,
|
||||
DefaultBaseURL: "https://api.deepseek.com/v1",
|
||||
EnvKey: "DEEPSEEK_API_KEY",
|
||||
Enabled: true,
|
||||
@@ -39,19 +57,94 @@ var catalog = map[string]Meta{
|
||||
{ID: "deepseek/deepseek-r1:1.5b", Name: "DeepSeek R1 1.5B"},
|
||||
},
|
||||
},
|
||||
"custom": {
|
||||
Key: "custom",
|
||||
DisplayName: "Custom",
|
||||
"bailian-coding-plan": {
|
||||
Key: "bailian-coding-plan",
|
||||
DisplayName: "阿里云百炼 Coding Plan",
|
||||
Sort: 30,
|
||||
DefaultBaseURL: "",
|
||||
EnvKey: "CUSTOM_API_KEY",
|
||||
DefaultBaseURL: "https://coding.dashscope.aliyuncs.com/v1",
|
||||
EnvKey: "QWEN_API_KEY",
|
||||
Enabled: true,
|
||||
Models: []Model{},
|
||||
Models: []Model{
|
||||
{ID: "bailian-coding-plan/qwen3.5-plus", Name: "Qwen3.5-Plus"},
|
||||
{ID: "bailian-coding-plan/qwen3-max", Name: "Qwen3-Max"},
|
||||
{ID: "bailian-coding-plan/qwen3-coder-next", Name: "Qwen3-Coder-Next"},
|
||||
{ID: "bailian-coding-plan/qwen3-coder-plus", Name: "Qwen3-Coder-Plus"},
|
||||
{ID: "bailian-coding-plan/minimax-m2.5", Name: "MiniMax M2.5"},
|
||||
{ID: "bailian-coding-plan/glm-5", Name: "GLM-5"},
|
||||
{ID: "bailian-coding-plan/kimi-k2.5", Name: "Kimi-k2.5"},
|
||||
{ID: "bailian-coding-plan/glm-4.7", Name: "GLM-4.7"},
|
||||
},
|
||||
},
|
||||
"ark-coding-plan": {
|
||||
Key: "ark-coding-plan",
|
||||
DisplayName: "方舟 Coding Plan",
|
||||
Sort: 35,
|
||||
DefaultBaseURL: "https://ark.cn-beijing.volces.com/api/coding/v3",
|
||||
EnvKey: "ARK_API_KEY",
|
||||
Enabled: true,
|
||||
Models: []Model{
|
||||
{ID: "ark-coding-plan/doubao-seed-2.0-code", Name: "Doubao-Seed-2.0-Code"},
|
||||
{ID: "ark-coding-plan/doubao-seed-code", Name: "Doubao-Seed-Code"},
|
||||
{ID: "ark-coding-plan/kimi-k2.5", Name: "Kimi-K2.5"},
|
||||
{ID: "ark-coding-plan/glm-4.7", Name: "GLM-4.7"},
|
||||
{ID: "ark-coding-plan/deepseek-v3.2", Name: "DeepSeek-V3.2"},
|
||||
{ID: "ark-coding-plan/kimi-k2-thinking", Name: "Kimi-K2-thinking"},
|
||||
},
|
||||
},
|
||||
"zai": {
|
||||
Key: "zai",
|
||||
DisplayName: "Z.ai",
|
||||
Sort: 40,
|
||||
DefaultBaseURL: "https://open.bigmodel.cn/api/paas/v4",
|
||||
EnvKey: "ZAI_API_KEY",
|
||||
Enabled: true,
|
||||
Models: []Model{
|
||||
{ID: "zai/glm-5", Name: "GLM-5"},
|
||||
{ID: "zai/glm-4.7", Name: "GLM-4.7"},
|
||||
{ID: "zai/glm-4.7-flash", Name: "GLM-4.7-Flash"},
|
||||
{ID: "zai/glm-4.7-flashx", Name: "GLM-4.7-FlashX"},
|
||||
},
|
||||
},
|
||||
"minimax": {
|
||||
Key: "minimax",
|
||||
DisplayName: "MiniMax (CN)",
|
||||
Sort: 45,
|
||||
DefaultBaseURL: "https://api.minimaxi.com/anthropic",
|
||||
EnvKey: "MINIMAX_API_KEY",
|
||||
Enabled: true,
|
||||
Models: []Model{
|
||||
{ID: "minimax/MiniMax-M2.1", Name: "MiniMax M2.1"},
|
||||
{ID: "minimax/MiniMax-M2.1-lightning", Name: "MiniMax M2.1 Lightning"},
|
||||
},
|
||||
},
|
||||
"kimi": {
|
||||
Key: "kimi",
|
||||
DisplayName: "Kimi (CN)",
|
||||
Sort: 50,
|
||||
DefaultBaseURL: "https://api.moonshot.cn/v1",
|
||||
EnvKey: "KIMI_API_KEY",
|
||||
Enabled: true,
|
||||
Models: []Model{
|
||||
{ID: "kimi/kimi-k2.5", Name: "Kimi K2.5"},
|
||||
{ID: "kimi/kimi-k2-0905-preview", Name: "Kimi K2 0905 Preview"},
|
||||
{ID: "kimi/kimi-k2-thinking", Name: "Kimi K2 Thinking"},
|
||||
},
|
||||
},
|
||||
"kimi-coding": {
|
||||
Key: "kimi-coding",
|
||||
DisplayName: "Kimi Coding",
|
||||
Sort: 51,
|
||||
DefaultBaseURL: "https://api.kimi.com/coding/",
|
||||
EnvKey: "KIMI_API_KEY",
|
||||
Enabled: true,
|
||||
Models: []Model{
|
||||
{ID: "kimi-coding/k2p5", Name: "Kimi K2.5"},
|
||||
},
|
||||
},
|
||||
"openai": {
|
||||
Key: "openai",
|
||||
DisplayName: "OpenAI",
|
||||
Sort: 40,
|
||||
Sort: 55,
|
||||
DefaultBaseURL: "https://api.openai.com/v1",
|
||||
EnvKey: "OPENAI_API_KEY",
|
||||
Enabled: true,
|
||||
@@ -64,10 +157,22 @@ var catalog = map[string]Meta{
|
||||
{ID: "openai/gpt-5-mini", Name: "GPT-5 Mini"},
|
||||
},
|
||||
},
|
||||
"openrouter": {
|
||||
Key: "openrouter",
|
||||
DisplayName: "OpenRouter",
|
||||
Sort: 56,
|
||||
DefaultBaseURL: "https://openrouter.ai/api/v1",
|
||||
EnvKey: "OPENROUTER_API_KEY",
|
||||
Enabled: true,
|
||||
Models: []Model{
|
||||
{ID: "openrouter/free", Name: "openrouter/free"},
|
||||
{ID: "openrouter/auto", Name: "openrouter/auto"},
|
||||
},
|
||||
},
|
||||
"anthropic": {
|
||||
Key: "anthropic",
|
||||
DisplayName: "Anthropic",
|
||||
Sort: 50,
|
||||
Sort: 60,
|
||||
DefaultBaseURL: "https://api.anthropic.com",
|
||||
EnvKey: "ANTHROPIC_API_KEY",
|
||||
Enabled: true,
|
||||
@@ -82,7 +187,7 @@ var catalog = map[string]Meta{
|
||||
"gemini": {
|
||||
Key: "gemini",
|
||||
DisplayName: "Gemini",
|
||||
Sort: 60,
|
||||
Sort: 65,
|
||||
DefaultBaseURL: "https://generativelanguage.googleapis.com",
|
||||
EnvKey: "GEMINI_API_KEY",
|
||||
Enabled: true,
|
||||
@@ -95,22 +200,10 @@ var catalog = map[string]Meta{
|
||||
{ID: "google/gemini-3-flash-preview", Name: "Gemini 3 Flash Preview"},
|
||||
},
|
||||
},
|
||||
"minimax": {
|
||||
Key: "minimax",
|
||||
DisplayName: "MiniMax (CN)",
|
||||
Sort: 70,
|
||||
DefaultBaseURL: "https://api.minimaxi.com/anthropic",
|
||||
EnvKey: "MINIMAX_API_KEY",
|
||||
Enabled: true,
|
||||
Models: []Model{
|
||||
{ID: "minimax/MiniMax-M2.1", Name: "MiniMax M2.1"},
|
||||
{ID: "minimax/MiniMax-M2.1-lightning", Name: "MiniMax M2.1 Lightning"},
|
||||
},
|
||||
},
|
||||
"moonshot": {
|
||||
Key: "moonshot",
|
||||
DisplayName: "Moonshot (Global)",
|
||||
Sort: 80,
|
||||
Sort: 70,
|
||||
DefaultBaseURL: "https://api.moonshot.ai/v1",
|
||||
EnvKey: "MOONSHOT_API_KEY",
|
||||
Enabled: true,
|
||||
@@ -120,38 +213,6 @@ var catalog = map[string]Meta{
|
||||
{ID: "moonshot/kimi-k2-thinking", Name: "Kimi K2 Thinking"},
|
||||
},
|
||||
},
|
||||
"kimi": {
|
||||
Key: "kimi",
|
||||
DisplayName: "Kimi (CN)",
|
||||
Sort: 90,
|
||||
DefaultBaseURL: "https://api.moonshot.cn/v1",
|
||||
EnvKey: "KIMI_API_KEY",
|
||||
Enabled: true,
|
||||
Models: []Model{
|
||||
{ID: "kimi/kimi-k2.5", Name: "Kimi K2.5"},
|
||||
{ID: "kimi/kimi-k2-0905-preview", Name: "Kimi K2 0905 Preview"},
|
||||
{ID: "kimi/kimi-k2-thinking", Name: "Kimi K2 Thinking"},
|
||||
},
|
||||
},
|
||||
"kimi-coding": {
|
||||
Key: "kimi-coding",
|
||||
DisplayName: "Kimi Coding",
|
||||
Sort: 100,
|
||||
DefaultBaseURL: "https://api.moonshot.cn/anthropic/v1",
|
||||
EnvKey: "KIMI_API_KEY",
|
||||
Enabled: true,
|
||||
Models: []Model{
|
||||
{ID: "kimi-coding/k2p5", Name: "Kimi K2.5"},
|
||||
},
|
||||
},
|
||||
"qwen": {
|
||||
Key: "qwen",
|
||||
DisplayName: "Qwen",
|
||||
Sort: 110,
|
||||
DefaultBaseURL: "https://dashscope.aliyuncs.com/compatible-mode/v1",
|
||||
EnvKey: "QWEN_API_KEY",
|
||||
Enabled: false,
|
||||
},
|
||||
}
|
||||
|
||||
func Get(key string) (Meta, bool) {
|
||||
|
||||
+1102
-134
File diff suppressed because it is too large
Load Diff
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/email"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/xpack"
|
||||
"github.com/shirou/gopsutil/v4/disk"
|
||||
"mime"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -483,13 +484,14 @@ func (a AlertService) TestAlertConfig(req dto.AlertConfigTest) (bool, error) {
|
||||
if username == "" {
|
||||
username = req.Sender
|
||||
}
|
||||
encodedDisplayName := mime.BEncoding.Encode("UTF-8", req.DisplayName)
|
||||
cfg := email.SMTPConfig{
|
||||
Host: req.Host,
|
||||
Port: req.Port,
|
||||
Sender: req.Sender,
|
||||
Username: username,
|
||||
Password: req.Password,
|
||||
From: fmt.Sprintf(`"%s" <%s>`, req.DisplayName, req.Sender),
|
||||
From: fmt.Sprintf(`"%s" <%s>`, encodedDisplayName, req.Sender),
|
||||
Encryption: req.Encryption,
|
||||
Recipient: req.Recipient,
|
||||
}
|
||||
|
||||
@@ -416,7 +416,7 @@ func (a AppService) Install(req request.AppInstallCreate, executeScript bool) (a
|
||||
}
|
||||
} else {
|
||||
if appDetail.DockerCompose == "" {
|
||||
dockerComposeUrl := fmt.Sprintf("%s/%s/1panel/%s/%s/docker-compose.yml", global.CONF.RemoteURL.AppRepo, global.CONF.Base.Mode, app.Key, appDetail.Version)
|
||||
dockerComposeUrl := fmt.Sprintf("%s/%s/1panel/%s/%s/docker-compose.yml", global.AppRepoURL(), global.CONF.Base.Mode, app.Key, appDetail.Version)
|
||||
_, composeRes, err = req_helper.HandleRequest(dockerComposeUrl, http.MethodGet, constant.TimeOut20s)
|
||||
if err != nil {
|
||||
return
|
||||
@@ -516,6 +516,10 @@ func (a AppService) Install(req request.AppInstallCreate, executeScript bool) (a
|
||||
}
|
||||
appInstall.Env = string(paramByte)
|
||||
|
||||
var maxSort int
|
||||
global.DB.Model(&model.AppInstall{}).Where("favorite = ?", false).Select("COALESCE(MAX(sort_order),0)").Scan(&maxSort)
|
||||
appInstall.SortOrder = maxSort + 1
|
||||
|
||||
if err = appInstallRepo.Create(context.Background(), appInstall); err != nil {
|
||||
return
|
||||
}
|
||||
@@ -817,7 +821,7 @@ func (a AppService) GetAppUpdate() (*response.AppUpdateRes, error) {
|
||||
return res, nil
|
||||
}
|
||||
|
||||
versionUrl := fmt.Sprintf("%s/%s/1panel.json.version.txt", global.CONF.RemoteURL.AppRepo, global.CONF.Base.Mode)
|
||||
versionUrl := fmt.Sprintf("%s/%s/1panel.json.version.txt", global.AppRepoURL(), global.CONF.Base.Mode)
|
||||
_, versionRes, err := req_helper.HandleRequest(versionUrl, http.MethodGet, constant.TimeOut20s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -889,7 +893,7 @@ func getAppFromRepo(downloadPath string) error {
|
||||
|
||||
func getAppList() (*dto.AppList, error) {
|
||||
list := &dto.AppList{}
|
||||
if err := getAppFromRepo(fmt.Sprintf("%s/%s/1panel.json.zip", global.CONF.RemoteURL.AppRepo, global.CONF.Base.Mode)); err != nil {
|
||||
if err := getAppFromRepo(fmt.Sprintf("%s/%s/1panel.json.zip", global.AppRepoURL(), global.CONF.Base.Mode)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
listFile := filepath.Join(global.Dir.ResourceDir, "1panel.json")
|
||||
|
||||
@@ -57,6 +57,7 @@ type IAppInstallService interface {
|
||||
UpdateAppConfig(req request.AppConfigUpdate) error
|
||||
GetInstallList() ([]dto.AppInstallInfo, error)
|
||||
GetAppInstallInfo(appInstallID uint) (*response.AppInstallInfo, error)
|
||||
UpdateSort(req request.AppInstallSort) error
|
||||
}
|
||||
|
||||
func NewIAppInstalledService() IAppInstallService {
|
||||
@@ -83,6 +84,7 @@ func (a *AppInstallService) Page(req request.AppInstalledSearch) (int64, []respo
|
||||
err error
|
||||
)
|
||||
opts = append(opts, repo.WithOrderRuleBy("favorite", "descending"))
|
||||
opts = append(opts, repo.WithOrderRuleBy("sort_order", "ascending"))
|
||||
|
||||
if req.Name != "" {
|
||||
opts = append(opts, repo.WithByLikeName(req.Name))
|
||||
@@ -300,6 +302,9 @@ func (a *AppInstallService) Operate(req request.AppInstalledOperate) error {
|
||||
return opNginx(install.ContainerName, constant.NginxReload)
|
||||
case constant.Favorite:
|
||||
install.Favorite = req.Favorite
|
||||
var maxSort int
|
||||
global.DB.Model(&model.AppInstall{}).Where("favorite = ?", req.Favorite).Select("COALESCE(MAX(sort_order),0)").Scan(&maxSort)
|
||||
install.SortOrder = maxSort + 1
|
||||
return appInstallRepo.Save(context.Background(), &install)
|
||||
default:
|
||||
return errors.New("operate not support")
|
||||
@@ -318,6 +323,15 @@ func (a *AppInstallService) UpdateAppConfig(req request.AppConfigUpdate) error {
|
||||
return appInstallRepo.Save(context.Background(), &installed)
|
||||
}
|
||||
|
||||
func (a *AppInstallService) UpdateSort(req request.AppInstallSort) error {
|
||||
for _, item := range req.Items {
|
||||
if err := appInstallRepo.BatchUpdateBy(map[string]interface{}{"sort_order": item.SortOrder}, repo.WithByID(item.InstallID)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *AppInstallService) Update(req request.AppInstalledUpdate) error {
|
||||
installed, err := appInstallRepo.GetFirst(repo.WithByID(req.InstallId))
|
||||
if err != nil {
|
||||
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
@@ -81,7 +83,7 @@ func (a AppService) createSyncAppStoreTask(sharedCtx **appSyncContext) func(t *t
|
||||
ctx := &appSyncContext{
|
||||
task: t,
|
||||
httpClient: http.Client{Timeout: time.Duration(constant.TimeOut20s) * time.Second, Transport: xpack.LoadRequestTransport()},
|
||||
baseRemoteUrl: fmt.Sprintf("%s/%s/1panel", global.CONF.RemoteURL.AppRepo, global.CONF.Base.Mode),
|
||||
baseRemoteUrl: fmt.Sprintf("%s/%s/1panel", global.AppRepoURL(), global.CONF.Base.Mode),
|
||||
systemVersion: setting.SystemVersion,
|
||||
settingService: settingService,
|
||||
list: list,
|
||||
@@ -127,90 +129,197 @@ func (a AppService) createSyncAppStoreTask(sharedCtx **appSyncContext) func(t *t
|
||||
}
|
||||
}
|
||||
|
||||
type appWorkItem struct {
|
||||
appDef dto.AppDefine
|
||||
app model.App
|
||||
iconUrl string
|
||||
hadIcon bool
|
||||
}
|
||||
|
||||
type appWorkResult struct {
|
||||
appKey string
|
||||
app model.App
|
||||
iconStatus int
|
||||
hadIcon bool
|
||||
httpFailed bool
|
||||
}
|
||||
|
||||
func (c *appSyncContext) processOneApp(item appWorkItem) appWorkResult {
|
||||
app := item.app
|
||||
l := item.appDef
|
||||
result := appWorkResult{
|
||||
appKey: l.AppProperty.Key,
|
||||
hadIcon: item.hadIcon,
|
||||
}
|
||||
|
||||
if item.hadIcon {
|
||||
status, iconField := c.downloadAppIcon(item.iconUrl, l.AppProperty.Key, app.Icon)
|
||||
result.iconStatus = status
|
||||
switch status {
|
||||
case http.StatusOK:
|
||||
app.Icon = iconField
|
||||
case http.StatusNotModified:
|
||||
default:
|
||||
result.httpFailed = true
|
||||
}
|
||||
}
|
||||
|
||||
app.TagsKey = l.AppProperty.Tags
|
||||
if l.AppProperty.Recommend > 0 {
|
||||
app.Recommend = l.AppProperty.Recommend
|
||||
} else {
|
||||
app.Recommend = 9999
|
||||
}
|
||||
app.ReadMe = l.ReadMe
|
||||
app.LastModified = l.LastModified
|
||||
|
||||
versions := l.Versions
|
||||
detailsMap := getAppDetails(app.Details, versions)
|
||||
for _, v := range versions {
|
||||
version := v.Name
|
||||
detail := detailsMap[version]
|
||||
versionUrl := fmt.Sprintf("%s/%s/%s", c.baseRemoteUrl, app.Key, version)
|
||||
|
||||
paramByte, _ := json.Marshal(v.AppForm)
|
||||
var appForm dto.AppForm
|
||||
_ = json.Unmarshal(paramByte, &appForm)
|
||||
|
||||
if appForm.SupportVersion > 0 && common.CompareVersion(strconv.FormatFloat(appForm.SupportVersion, 'f', -1, 64), c.systemVersion) {
|
||||
delete(detailsMap, version)
|
||||
continue
|
||||
}
|
||||
|
||||
if _, ok := InitTypes[app.Type]; ok {
|
||||
dockerComposeUrl := fmt.Sprintf("%s/%s", versionUrl, "docker-compose.yml")
|
||||
_, composeRes, err := req_helper.HandleRequestWithClient(&c.httpClient, dockerComposeUrl, http.MethodGet, constant.TimeOut20s)
|
||||
if err == nil {
|
||||
detail.DockerCompose = string(composeRes)
|
||||
} else {
|
||||
result.httpFailed = true
|
||||
}
|
||||
} else {
|
||||
detail.DockerCompose = ""
|
||||
}
|
||||
|
||||
detail.Params = string(paramByte)
|
||||
detail.DownloadUrl = fmt.Sprintf("%s/%s", versionUrl, app.Key+"-"+version+".tar.gz")
|
||||
detail.DownloadCallBackUrl = v.DownloadCallBackUrl
|
||||
detail.Update = true
|
||||
detail.LastModified = v.LastModified
|
||||
detailsMap[version] = detail
|
||||
}
|
||||
|
||||
newDetails := make([]model.AppDetail, 0, len(detailsMap))
|
||||
for _, detail := range detailsMap {
|
||||
newDetails = append(newDetails, detail)
|
||||
}
|
||||
app.Details = newDetails
|
||||
|
||||
result.app = app
|
||||
return result
|
||||
}
|
||||
|
||||
func (c *appSyncContext) syncAppIconsAndDetails() error {
|
||||
total := len(c.list.Apps)
|
||||
global.LOG.Infof("[AppStore] sync app detail start, total apps: %d", total)
|
||||
|
||||
var (
|
||||
icon200Count = 0
|
||||
icon304Count = 0
|
||||
iconFailCount = 0
|
||||
)
|
||||
|
||||
for i, l := range c.list.Apps {
|
||||
if (i+1)%10 == 0 {
|
||||
c.task.LogWithProgress(i18n.GetMsgByKey("SyncAppDetail"), i+1, total)
|
||||
}
|
||||
|
||||
workItems := make([]appWorkItem, 0, total)
|
||||
for _, l := range c.list.Apps {
|
||||
app, ok := c.appsMap[l.AppProperty.Key]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
iconUrl, hasPending := c.pendingIcons[l.AppProperty.Key]
|
||||
if hasPending {
|
||||
status, iconField := c.downloadAppIcon(iconUrl, l.AppProperty.Key, app.Icon)
|
||||
switch status {
|
||||
workItems = append(workItems, appWorkItem{
|
||||
appDef: l,
|
||||
app: app,
|
||||
iconUrl: iconUrl,
|
||||
hadIcon: hasPending,
|
||||
})
|
||||
}
|
||||
|
||||
totalWork := len(workItems)
|
||||
if totalWork == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
const maxWorkers = 4
|
||||
var (
|
||||
failFlag atomic.Bool
|
||||
workCh = make(chan int, maxWorkers)
|
||||
resultCh = make(chan appWorkResult, maxWorkers)
|
||||
wg sync.WaitGroup
|
||||
)
|
||||
|
||||
wg.Add(maxWorkers)
|
||||
for range maxWorkers {
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for idx := range workCh {
|
||||
result := c.processOneApp(workItems[idx])
|
||||
resultCh <- result
|
||||
if result.httpFailed {
|
||||
failFlag.Store(true)
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
go func() { wg.Wait(); close(resultCh) }()
|
||||
|
||||
var fed atomic.Int32
|
||||
go func() {
|
||||
for i := range workItems {
|
||||
if failFlag.Load() {
|
||||
break
|
||||
}
|
||||
workCh <- i
|
||||
fed.Store(int32(i + 1))
|
||||
}
|
||||
close(workCh)
|
||||
}()
|
||||
|
||||
var (
|
||||
completed int
|
||||
icon200Count int
|
||||
icon304Count int
|
||||
iconFailCount int
|
||||
)
|
||||
milestones := [4]int{totalWork / 4, totalWork / 2, totalWork * 3 / 4, totalWork}
|
||||
nextMS := 0
|
||||
checkProgress := func() {
|
||||
if nextMS < len(milestones) && completed >= milestones[nextMS] {
|
||||
c.task.LogWithProgress(i18n.GetMsgByKey("SyncAppDetail"), completed, totalWork)
|
||||
nextMS++
|
||||
}
|
||||
}
|
||||
|
||||
applyResult := func(result appWorkResult) {
|
||||
c.appsMap[result.appKey] = result.app
|
||||
if result.hadIcon {
|
||||
switch result.iconStatus {
|
||||
case http.StatusOK:
|
||||
app.Icon = iconField
|
||||
icon200Count++
|
||||
case http.StatusNotModified:
|
||||
icon304Count++
|
||||
default:
|
||||
global.LOG.Warnf("[AppStore] download icon failed url=%s, appKey=%s", iconUrl, l.AppProperty.Key)
|
||||
iconFailCount++
|
||||
}
|
||||
}
|
||||
completed++
|
||||
checkProgress()
|
||||
}
|
||||
|
||||
app.TagsKey = l.AppProperty.Tags
|
||||
if l.AppProperty.Recommend > 0 {
|
||||
app.Recommend = l.AppProperty.Recommend
|
||||
} else {
|
||||
app.Recommend = 9999
|
||||
for result := range resultCh {
|
||||
applyResult(result)
|
||||
}
|
||||
|
||||
fedCount := int(fed.Load())
|
||||
if failFlag.Load() && fedCount < len(workItems) {
|
||||
global.LOG.Warnf("[AppStore] HTTP failure detected, falling back to serial for remaining %d apps", len(workItems)-fedCount)
|
||||
for i := fedCount; i < len(workItems); i++ {
|
||||
result := c.processOneApp(workItems[i])
|
||||
applyResult(result)
|
||||
}
|
||||
app.ReadMe = l.ReadMe
|
||||
app.LastModified = l.LastModified
|
||||
|
||||
versions := l.Versions
|
||||
detailsMap := getAppDetails(app.Details, versions)
|
||||
for _, v := range versions {
|
||||
version := v.Name
|
||||
detail := detailsMap[version]
|
||||
versionUrl := fmt.Sprintf("%s/%s/%s", c.baseRemoteUrl, app.Key, version)
|
||||
|
||||
paramByte, _ := json.Marshal(v.AppForm)
|
||||
var appForm dto.AppForm
|
||||
_ = json.Unmarshal(paramByte, &appForm)
|
||||
|
||||
if appForm.SupportVersion > 0 && common.CompareVersion(strconv.FormatFloat(appForm.SupportVersion, 'f', -1, 64), c.systemVersion) {
|
||||
delete(detailsMap, version)
|
||||
continue
|
||||
}
|
||||
|
||||
if _, ok := InitTypes[app.Type]; ok {
|
||||
dockerComposeUrl := fmt.Sprintf("%s/%s", versionUrl, "docker-compose.yml")
|
||||
_, composeRes, err := req_helper.HandleRequestWithClient(&c.httpClient, dockerComposeUrl, http.MethodGet, constant.TimeOut20s)
|
||||
if err == nil {
|
||||
detail.DockerCompose = string(composeRes)
|
||||
}
|
||||
} else {
|
||||
detail.DockerCompose = ""
|
||||
}
|
||||
|
||||
detail.Params = string(paramByte)
|
||||
detail.DownloadUrl = fmt.Sprintf("%s/%s", versionUrl, app.Key+"-"+version+".tar.gz")
|
||||
detail.DownloadCallBackUrl = v.DownloadCallBackUrl
|
||||
detail.Update = true
|
||||
detail.LastModified = v.LastModified
|
||||
detailsMap[version] = detail
|
||||
}
|
||||
|
||||
var newDetails []model.AppDetail
|
||||
for _, detail := range detailsMap {
|
||||
newDetails = append(newDetails, detail)
|
||||
}
|
||||
app.Details = newDetails
|
||||
c.appsMap[l.AppProperty.Key] = app
|
||||
}
|
||||
|
||||
global.LOG.Infof("[AppStore] icon download completed - total: %d, success(200): %d, cached(304): %d, failed: %d",
|
||||
|
||||
@@ -393,7 +393,7 @@ func deleteAppInstall(deleteReq request.AppInstallDelete) error {
|
||||
return err
|
||||
}
|
||||
appKey := install.App.Key
|
||||
if appKey == constant.AppOpenclaw {
|
||||
if appKey == constant.AppOpenclaw || appKey == constant.AppCopaw {
|
||||
_ = agentRepo.DeleteByAppInstallIDWithCtx(ctx, install.ID)
|
||||
}
|
||||
|
||||
@@ -1613,6 +1613,7 @@ func handleInstalled(appInstallList []model.AppInstall, updated, sync, checkUpda
|
||||
Document: installed.App.Document,
|
||||
},
|
||||
Favorite: installed.Favorite,
|
||||
SortOrder: installed.SortOrder,
|
||||
Container: installed.ContainerName,
|
||||
ServiceName: strings.ToLower(installed.ServiceName),
|
||||
}
|
||||
|
||||
+153
-39
@@ -11,6 +11,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/repo"
|
||||
"github.com/subosito/gotenv"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/task"
|
||||
"github.com/1Panel-dev/1Panel/agent/i18n"
|
||||
@@ -179,6 +180,9 @@ func handleAppRecover(install *model.AppInstall, parentTask *task.Task, recoverF
|
||||
return err
|
||||
}
|
||||
tmpPath := strings.ReplaceAll(recoverFile, ".tar.gz", "")
|
||||
if err := fileOp.TarGzExtractPro(tmpPath+"/app.tar.gz", tmpPath, ""); err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
_, _ = compose.Up(install.GetComposePath())
|
||||
_ = os.RemoveAll(strings.ReplaceAll(recoverFile, ".tar.gz", ""))
|
||||
@@ -187,19 +191,26 @@ func handleAppRecover(install *model.AppInstall, parentTask *task.Task, recoverF
|
||||
if !fileOp.Stat(tmpPath+"/app.json") || !fileOp.Stat(tmpPath+"/app.tar.gz") {
|
||||
return errors.New(i18n.GetMsgByKey("AppBackupFileIncomplete"))
|
||||
}
|
||||
var oldInstall model.AppInstall
|
||||
var backupInstall model.AppInstall
|
||||
appJson, err := os.ReadFile(tmpPath + "/app.json")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := json.Unmarshal(appJson, &oldInstall); err != nil {
|
||||
if err := json.Unmarshal(appJson, &backupInstall); err != nil {
|
||||
return fmt.Errorf("unmarshal app.json failed, err: %v", err)
|
||||
}
|
||||
if oldInstall.App.Key != install.App.Key || oldInstall.Name != install.Name {
|
||||
if backupInstall.App.Key != install.App.Key || backupInstall.Name != install.Name {
|
||||
return errors.New(i18n.GetMsgByKey("AppAttributesNotMatch"))
|
||||
}
|
||||
|
||||
newEnvFile := ""
|
||||
backupEnvMap, err := getEnvMapByPath(path.Join(tmpPath, install.Name, ".env"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
installedEnvMap, err := getEnvMapByPath(install.GetEnvPath())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var mergedEnvContent string
|
||||
resources, _ := appInstallResourceRepo.GetBy(appInstallResourceRepo.WithAppInstallId(install.ID))
|
||||
for _, resource := range resources {
|
||||
var database model.Database
|
||||
@@ -225,11 +236,20 @@ func handleAppRecover(install *model.AppInstall, parentTask *task.Task, recoverF
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newDB, err := reCreatePostgresqlDB(db.ID, database, backupEnvMap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
backupInstall.Env, mergedEnvContent, err = buildRecoverEnv(backupInstall.Env, backupEnvMap, installedEnvMap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_ = appInstallResourceRepo.BatchUpdateBy(map[string]interface{}{"resource_id": newDB.ID}, repo.WithByID(resource.ID))
|
||||
taskName := task.GetTaskName(db.Name, task.TaskRecover, task.TaskScopeDatabase)
|
||||
t.LogStart(taskName)
|
||||
if err := handlePostgresqlRecover(dto.CommonRecover{
|
||||
Name: database.Name,
|
||||
DetailName: db.Name,
|
||||
Name: newDB.PostgresqlName,
|
||||
DetailName: newDB.Name,
|
||||
File: fmt.Sprintf("%s/%s.sql.gz", tmpPath, install.Name),
|
||||
}, parentTask, true); err != nil {
|
||||
t.LogFailedWithErr(taskName, err)
|
||||
@@ -241,15 +261,11 @@ func handleAppRecover(install *model.AppInstall, parentTask *task.Task, recoverF
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newDB, envMap, err := reCreateDB(db.ID, database, oldInstall.Env)
|
||||
newDB, err := reCreateDB(db.ID, database, backupEnvMap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
oldHost := fmt.Sprintf("\"PANEL_DB_HOST\":\"%v\"", envMap["PANEL_DB_HOST"].(string))
|
||||
newHost := fmt.Sprintf("\"PANEL_DB_HOST\":\"%v\"", database.Address)
|
||||
oldInstall.Env = strings.ReplaceAll(oldInstall.Env, oldHost, newHost)
|
||||
envMap["PANEL_DB_HOST"] = database.Address
|
||||
newEnvFile, err = coverEnvJsonToStr(oldInstall.Env)
|
||||
backupInstall.Env, mergedEnvContent, err = buildRecoverEnv(backupInstall.Env, backupEnvMap, installedEnvMap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -284,22 +300,22 @@ func handleAppRecover(install *model.AppInstall, parentTask *task.Task, recoverF
|
||||
t.LogSuccess(deCompressName)
|
||||
_ = fileOp.DeleteDir(backPath)
|
||||
|
||||
if len(newEnvFile) != 0 {
|
||||
if len(mergedEnvContent) != 0 {
|
||||
envPath := fmt.Sprintf("%s/%s/.env", install.GetAppPath(), install.Name)
|
||||
file, err := os.OpenFile(envPath, os.O_WRONLY|os.O_TRUNC, 0640)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
_, _ = file.WriteString(newEnvFile)
|
||||
_, _ = file.WriteString(mergedEnvContent)
|
||||
}
|
||||
|
||||
oldInstall.ID = install.ID
|
||||
oldInstall.Status = constant.StatusRunning
|
||||
oldInstall.AppId = install.AppId
|
||||
oldInstall.AppDetailId = install.AppDetailId
|
||||
oldInstall.App.ID = install.AppId
|
||||
if err := appInstallRepo.Save(context.Background(), &oldInstall); err != nil {
|
||||
backupInstall.ID = install.ID
|
||||
backupInstall.Status = constant.StatusRunning
|
||||
backupInstall.AppId = install.AppId
|
||||
backupInstall.AppDetailId = install.AppDetailId
|
||||
backupInstall.App.ID = install.AppId
|
||||
if err := appInstallRepo.Save(context.Background(), &backupInstall); err != nil {
|
||||
global.LOG.Errorf("save db app install failed, err: %v", err)
|
||||
return err
|
||||
}
|
||||
@@ -373,33 +389,131 @@ func doAppBackup(install *model.AppInstall, parentTask *task.Task, backupDir, fi
|
||||
return nil
|
||||
}
|
||||
|
||||
func reCreateDB(dbID uint, database model.Database, oldEnv string) (*model.DatabaseMysql, map[string]interface{}, error) {
|
||||
func reCreateDB(dbID uint, database model.Database, envMap map[string]interface{}) (*model.DatabaseMysql, error) {
|
||||
mysqlService := NewIMysqlService()
|
||||
ctx := context.Background()
|
||||
_ = mysqlService.Delete(ctx, dto.MysqlDBDelete{ID: dbID, Database: database.Name, Type: database.Type, DeleteBackup: false, ForceDelete: true})
|
||||
|
||||
envMap := make(map[string]interface{})
|
||||
if err := json.Unmarshal([]byte(oldEnv), &envMap); err != nil {
|
||||
return nil, envMap, err
|
||||
}
|
||||
oldName, _ := envMap["PANEL_DB_NAME"].(string)
|
||||
oldUser, _ := envMap["PANEL_DB_USER"].(string)
|
||||
oldPassword, _ := envMap["PANEL_DB_USER_PASSWORD"].(string)
|
||||
dbInfo := getDBCreateInfoFromEnv(envMap, "utf8mb4")
|
||||
createDB, err := mysqlService.Create(context.Background(), dto.MysqlDBCreate{
|
||||
Name: oldName,
|
||||
Name: dbInfo.Name,
|
||||
From: database.From,
|
||||
Database: database.Name,
|
||||
Format: "utf8mb4",
|
||||
Username: oldUser,
|
||||
Password: oldPassword,
|
||||
Format: dbInfo.Format,
|
||||
Username: dbInfo.User,
|
||||
Password: dbInfo.Password,
|
||||
Permission: "%",
|
||||
})
|
||||
cronjobs, _ := cronjobRepo.List(cronjobRepo.WithByDbName(fmt.Sprintf("%v", dbID)))
|
||||
for _, job := range cronjobs {
|
||||
_ = cronjobRepo.Update(job.ID, map[string]interface{}{"db_name": fmt.Sprintf("%v", createDB.ID)})
|
||||
}
|
||||
if err != nil {
|
||||
return nil, envMap, err
|
||||
return nil, err
|
||||
}
|
||||
return createDB, envMap, nil
|
||||
updateCronjobsDBRef(dbID, createDB.ID)
|
||||
return createDB, nil
|
||||
}
|
||||
|
||||
func reCreatePostgresqlDB(dbID uint, database model.Database, envMap map[string]interface{}) (*model.DatabasePostgresql, error) {
|
||||
postgresqlService := NewIPostgresqlService()
|
||||
_ = postgresqlService.Delete(context.Background(), dto.PostgresqlDBDelete{
|
||||
ID: dbID,
|
||||
Type: database.Type,
|
||||
Database: database.Name,
|
||||
DeleteBackup: false,
|
||||
ForceDelete: true,
|
||||
})
|
||||
|
||||
dbInfo := getDBCreateInfoFromEnv(envMap, "UTF8")
|
||||
createDB, err := postgresqlService.Create(context.Background(), dto.PostgresqlDBCreate{
|
||||
Name: dbInfo.Name,
|
||||
From: database.From,
|
||||
Database: database.Name,
|
||||
Format: dbInfo.Format,
|
||||
Username: dbInfo.User,
|
||||
Password: dbInfo.Password,
|
||||
SuperUser: true,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
updateCronjobsDBRef(dbID, createDB.ID)
|
||||
return createDB, nil
|
||||
}
|
||||
|
||||
type dbRecreateInfo struct {
|
||||
Name string
|
||||
User string
|
||||
Password string
|
||||
Format string
|
||||
}
|
||||
|
||||
func getDBCreateInfoFromEnv(envMap map[string]interface{}, defaultFormat string) dbRecreateInfo {
|
||||
name, _ := envMap["PANEL_DB_NAME"].(string)
|
||||
user, _ := envMap["PANEL_DB_USER"].(string)
|
||||
password, _ := envMap["PANEL_DB_USER_PASSWORD"].(string)
|
||||
format, _ := envMap["format"].(string)
|
||||
if len(format) == 0 {
|
||||
format = defaultFormat
|
||||
}
|
||||
return dbRecreateInfo{
|
||||
Name: name,
|
||||
User: user,
|
||||
Password: password,
|
||||
Format: format,
|
||||
}
|
||||
}
|
||||
|
||||
func updateCronjobsDBRef(oldDBID, newDBID uint) {
|
||||
cronjobs, _ := cronjobRepo.List(cronjobRepo.WithByDbName(fmt.Sprintf("%v", oldDBID)))
|
||||
for _, job := range cronjobs {
|
||||
_ = cronjobRepo.Update(job.ID, map[string]interface{}{"db_name": fmt.Sprintf("%v", newDBID)})
|
||||
}
|
||||
}
|
||||
|
||||
func buildRecoverEnv(appEnv string, backupEnvMap, installedEnvMap map[string]interface{}) (string, string, error) {
|
||||
currentHostVal, hasCurrentHost := installedEnvMap["PANEL_DB_HOST"]
|
||||
if hasCurrentHost && fmt.Sprintf("%v", currentHostVal) != "" {
|
||||
backupHost := fmt.Sprintf("\"PANEL_DB_HOST\":\"%v\"", backupEnvMap["PANEL_DB_HOST"])
|
||||
currentHost := fmt.Sprintf("\"PANEL_DB_HOST\":\"%v\"", currentHostVal)
|
||||
appEnv = strings.ReplaceAll(appEnv, backupHost, currentHost)
|
||||
if _, ok := backupEnvMap["CASDOOR_DATASOURCE_NAME"]; ok {
|
||||
backupEnvMap["CASDOOR_DATASOURCE_NAME"] = strings.ReplaceAll(
|
||||
fmt.Sprintf("%v", backupEnvMap["CASDOOR_DATASOURCE_NAME"]),
|
||||
fmt.Sprintf("%v", backupEnvMap["PANEL_DB_HOST"]),
|
||||
fmt.Sprintf("%v", currentHostVal),
|
||||
)
|
||||
}
|
||||
backupEnvMap["PANEL_DB_HOST"] = currentHostVal
|
||||
}
|
||||
newEnvMap := make(map[string]string, len(backupEnvMap))
|
||||
handleMap(backupEnvMap, newEnvMap)
|
||||
mergedEnvContent, err := gotenv.Marshal(newEnvMap)
|
||||
if err != nil {
|
||||
return appEnv, "", err
|
||||
}
|
||||
return appEnv, mergedEnvContent, nil
|
||||
}
|
||||
|
||||
func getEnvMapByPath(envPath string) (map[string]interface{}, error) {
|
||||
envMap := make(map[string]interface{})
|
||||
envFile, err := os.ReadFile(envPath)
|
||||
if err != nil {
|
||||
return envMap, err
|
||||
}
|
||||
lines := strings.Split(string(envFile), "\n")
|
||||
for _, line := range lines {
|
||||
line = strings.TrimSpace(line)
|
||||
if line == "" || strings.HasPrefix(line, "#") {
|
||||
continue
|
||||
}
|
||||
parts := strings.SplitN(line, "=", 2)
|
||||
if len(parts) == 2 {
|
||||
value := strings.TrimSpace(parts[1])
|
||||
if len(value) >= 2 {
|
||||
if (value[0] == '"' && value[len(value)-1] == '"') || (value[0] == '\'' && value[len(value)-1] == '\'') {
|
||||
value = value[1 : len(value)-1]
|
||||
}
|
||||
}
|
||||
envMap[parts[0]] = value
|
||||
}
|
||||
}
|
||||
return envMap, nil
|
||||
}
|
||||
|
||||
@@ -43,7 +43,6 @@ import (
|
||||
"github.com/docker/go-connections/nat"
|
||||
"github.com/gin-gonic/gin"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/shirou/gopsutil/v4/cpu"
|
||||
"github.com/shirou/gopsutil/v4/mem"
|
||||
)
|
||||
@@ -69,7 +68,6 @@ type IContainerService interface {
|
||||
ComposeLogClean(req dto.ComposeLogClean) error
|
||||
|
||||
ContainerCreate(req dto.ContainerOperate, inThread bool) error
|
||||
ContainerCreateByCommand(req dto.ContainerCreateByCommand) error
|
||||
ContainerUpdate(req dto.ContainerOperate) error
|
||||
ContainerUpgrade(req dto.ContainerUpgrade) error
|
||||
ContainerInfo(req dto.OperationWithName) (*dto.ContainerOperate, error)
|
||||
@@ -104,7 +102,7 @@ func (u *ContainerService) Page(req dto.PageContainer) (int64, interface{}, erro
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
defer client.Close()
|
||||
defer func() { _ = client.Close() }()
|
||||
options := container.ListOptions{All: true}
|
||||
if len(req.Filters) != 0 {
|
||||
options.Filters = filters.NewArgs()
|
||||
@@ -302,42 +300,6 @@ func (u *ContainerService) ContainerListStats() ([]dto.ContainerListStats, error
|
||||
return datas, nil
|
||||
}
|
||||
|
||||
func (u *ContainerService) ContainerCreateByCommand(req dto.ContainerCreateByCommand) error {
|
||||
if cmd.CheckIllegal(req.Command) {
|
||||
return buserr.New("ErrCmdIllegal")
|
||||
}
|
||||
if !strings.HasPrefix(strings.TrimSpace(req.Command), "docker run ") {
|
||||
return errors.New("error command format")
|
||||
}
|
||||
containerName := ""
|
||||
commands := strings.Split(req.Command, " ")
|
||||
for index, val := range commands {
|
||||
if val == "--name" && len(commands) > index+1 {
|
||||
containerName = commands[index+1]
|
||||
}
|
||||
}
|
||||
if !strings.Contains(req.Command, " -d ") {
|
||||
req.Command = strings.ReplaceAll(req.Command, "docker run", "docker run -d")
|
||||
}
|
||||
if len(containerName) == 0 {
|
||||
containerName = fmt.Sprintf("1Panel-%s-%s", common.RandStr(5), common.RandStrAndNum(4))
|
||||
req.Command += fmt.Sprintf(" --name %s", containerName)
|
||||
}
|
||||
taskItem, err := task.NewTaskWithOps(containerName, task.TaskCreate, task.TaskScopeContainer, req.TaskID, 1)
|
||||
if err != nil {
|
||||
global.LOG.Errorf("new task for create container failed, err: %v", err)
|
||||
return err
|
||||
}
|
||||
go func() {
|
||||
taskItem.AddSubTask(i18n.GetWithName("ContainerCreate", containerName), func(t *task.Task) error {
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTask(*taskItem), cmd.WithTimeout(5*time.Minute))
|
||||
return cmdMgr.RunBashC(req.Command)
|
||||
}, nil)
|
||||
_ = taskItem.Execute()
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *ContainerService) Inspect(req dto.InspectReq) (string, error) {
|
||||
client, err := docker.NewDockerClient()
|
||||
if err != nil {
|
||||
@@ -621,6 +583,16 @@ func (u *ContainerService) ContainerInfo(req dto.OperationWithName) (*dto.Contai
|
||||
data.ExposedPorts = loadContainerPortForInfo(exposePorts)
|
||||
data.Hostname = oldContainer.Config.Hostname
|
||||
data.DNS = oldContainer.HostConfig.DNS
|
||||
for _, item := range oldContainer.HostConfig.ExtraHosts {
|
||||
parts := strings.SplitN(item, ":", 2)
|
||||
if len(parts) != 2 || len(parts[0]) == 0 || len(parts[1]) == 0 {
|
||||
continue
|
||||
}
|
||||
data.ExtraHosts = append(data.ExtraHosts, dto.ExtraHost{
|
||||
Hostname: parts[0],
|
||||
IP: parts[1],
|
||||
})
|
||||
}
|
||||
data.DomainName = oldContainer.Config.Domainname
|
||||
|
||||
data.Cmd = oldContainer.Config.Cmd
|
||||
@@ -1181,7 +1153,7 @@ func (u *ContainerService) ContainerStats(id string) (*dto.ContainerStats, error
|
||||
|
||||
func (u *ContainerService) LoadUsers(req dto.OperationWithName) []string {
|
||||
var users []string
|
||||
std, err := cmd.RunDefaultWithStdoutBashCf("docker exec %s cat /etc/passwd", req.Name)
|
||||
std, err := cmd.NewCommandMgr(cmd.WithTimeout(20*time.Second)).RunWithStdout("docker", "exec", req.Name, "cat", "/etc/passwd")
|
||||
if err != nil {
|
||||
return users
|
||||
}
|
||||
@@ -1488,6 +1460,13 @@ func loadConfigInfo(isCreate bool, req dto.ContainerOperate, oldContainer *conta
|
||||
hostConf.Binds = []string{}
|
||||
hostConf.Mounts = []mount.Mount{}
|
||||
hostConf.DNS = req.DNS
|
||||
hostConf.ExtraHosts = []string{}
|
||||
for _, item := range req.ExtraHosts {
|
||||
if len(item.Hostname) == 0 || len(item.IP) == 0 {
|
||||
continue
|
||||
}
|
||||
hostConf.ExtraHosts = append(hostConf.ExtraHosts, fmt.Sprintf("%s:%s", item.Hostname, item.IP))
|
||||
}
|
||||
config.Volumes = make(map[string]struct{})
|
||||
for _, volume := range req.Volumes {
|
||||
item := mount.Mount{
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
@@ -43,6 +44,10 @@ func (u *DBCommonService) LoadBaseInfo(req dto.OperationWithNameAndType) (*dto.D
|
||||
|
||||
func (u *DBCommonService) LoadDatabaseFile(req dto.OperationWithNameAndType) (string, error) {
|
||||
filePath := ""
|
||||
safeName := filepath.Base(req.Name)
|
||||
if safeName != req.Name || strings.Contains(safeName, "..") {
|
||||
return "", buserr.New("ErrInvalidParams")
|
||||
}
|
||||
switch req.Type {
|
||||
case "mysql-cluster-conf":
|
||||
filePath = path.Join(global.Dir.DataDir, fmt.Sprintf("apps/mysql-cluster/%s/conf/my.cnf", req.Name))
|
||||
|
||||
@@ -109,7 +109,7 @@ func (u *DeviceService) CheckDNS(key, value string) (bool, error) {
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer conn.Close()
|
||||
defer func() { _ = conn.Close() }()
|
||||
|
||||
return true, nil
|
||||
}
|
||||
@@ -132,7 +132,7 @@ func (u *DeviceService) Update(key, value string) error {
|
||||
if cmd.CheckIllegal(value) {
|
||||
return buserr.New("ErrCmdIllegal")
|
||||
}
|
||||
if err := cmd.RunDefaultBashCf("%s hostnamectl set-hostname %s", cmd.SudoHandleCmd(), value); err != nil {
|
||||
if err := cmd.NewCommandMgr(cmd.WithTimeout(20*time.Second)).Run("hostnamectl", "set-hostname", value); err != nil {
|
||||
return err
|
||||
}
|
||||
_, _ = psutil.HOST.GetHostInfo(true)
|
||||
@@ -245,7 +245,7 @@ func (u *DeviceService) UpdateSwap(req dto.SwapHelper) error {
|
||||
}
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTask(*taskItem))
|
||||
if !req.IsNew {
|
||||
if err := cmdMgr.RunBashCf("%s swapoff %s", cmd.SudoHandleCmd(), req.Path); err != nil {
|
||||
if err := cmdMgr.Run("swapoff", req.Path); err != nil {
|
||||
return fmt.Errorf("handle swapoff %s failed, %v", req.Path, err)
|
||||
}
|
||||
}
|
||||
@@ -256,22 +256,22 @@ func (u *DeviceService) UpdateSwap(req dto.SwapHelper) error {
|
||||
return operateSwapWithFile(true, req)
|
||||
}
|
||||
taskItem.LogStart(i18n.GetMsgByKey("CreateSwap"))
|
||||
if err := cmdMgr.RunBashCf("%s dd if=/dev/zero of=%s bs=1024 count=%d", cmd.SudoHandleCmd(), req.Path, req.Size); err != nil {
|
||||
if err := cmdMgr.Run("dd", "if=/dev/zero", fmt.Sprintf("of=%s", req.Path), "bs=1024", fmt.Sprintf("count=%d", req.Size)); err != nil {
|
||||
return fmt.Errorf("handle dd %s failed, %v", req.Path, err)
|
||||
}
|
||||
|
||||
taskItem.Log("chmod 0600 " + req.Path)
|
||||
if err := cmdMgr.RunBashCf("%s chmod 0600 %s", cmd.SudoHandleCmd(), req.Path); err != nil {
|
||||
if err := cmdMgr.Run("chmod", "0600", req.Path); err != nil {
|
||||
return fmt.Errorf("handle chmod 0600 %s failed, %v", req.Path, err)
|
||||
}
|
||||
taskItem.LogStart(i18n.GetMsgByKey("FormatSwap"))
|
||||
if err := cmdMgr.RunBashCf("%s mkswap -f %s", cmd.SudoHandleCmd(), req.Path); err != nil {
|
||||
if err := cmdMgr.Run("mkswap", "-f", req.Path); err != nil {
|
||||
return fmt.Errorf("handle mkswap -f %s failed, %v", req.Path, err)
|
||||
}
|
||||
|
||||
taskItem.LogStart(i18n.GetMsgByKey("EnableSwap"))
|
||||
if err := cmdMgr.RunBashCf("%s swapon %s", cmd.SudoHandleCmd(), req.Path); err != nil {
|
||||
_ = cmdMgr.RunBashCf("%s swapoff %s", cmd.SudoHandleCmd(), req.Path)
|
||||
if err := cmdMgr.Run("swapon", req.Path); err != nil {
|
||||
_ = cmdMgr.Run("swapoff", req.Path)
|
||||
return fmt.Errorf("handle swapoff %s failed, %v", req.Path, err)
|
||||
}
|
||||
return operateSwapWithFile(false, req)
|
||||
|
||||
@@ -2,13 +2,14 @@ package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/agent/buserr"
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto/request"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto/response"
|
||||
@@ -65,19 +66,19 @@ func (s *DiskService) PartitionDisk(req request.DiskPartitionRequest) (string, e
|
||||
}
|
||||
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(10 * time.Second))
|
||||
if err := cmdMgr.RunBashC(fmt.Sprintf("partprobe %s", req.Device)); err != nil {
|
||||
if err := cmdMgr.Run("partprobe", req.Device); err != nil {
|
||||
return "", buserr.WithErr("PartitionDiskErr", err)
|
||||
}
|
||||
|
||||
if err := cmdMgr.RunBashC(fmt.Sprintf("parted -s %s mklabel gpt", req.Device)); err != nil {
|
||||
if err := cmdMgr.Run("parted", "-s", req.Device, "mklabel", "gpt"); err != nil {
|
||||
return "", buserr.WithErr("PartitionDiskErr", err)
|
||||
}
|
||||
|
||||
if err := cmdMgr.RunBashC(fmt.Sprintf("parted -s %s mkpart primary 1MiB 100%%", req.Device)); err != nil {
|
||||
if err := cmdMgr.Run("parted", "-s", req.Device, "mkpart", "primary", "1MiB", "100%"); err != nil {
|
||||
return "", buserr.WithErr("PartitionDiskErr", err)
|
||||
}
|
||||
|
||||
if err := cmdMgr.RunBashC(fmt.Sprintf("partprobe %s", req.Device)); err != nil {
|
||||
if err := cmdMgr.Run("partprobe", req.Device); err != nil {
|
||||
return "", buserr.WithErr("PartitionDiskErr", err)
|
||||
}
|
||||
partition := req.Device + "1"
|
||||
@@ -133,7 +134,7 @@ func (s *DiskService) MountDisk(req request.DiskMountRequest) error {
|
||||
}
|
||||
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(1 * time.Minute))
|
||||
if err := cmdMgr.RunBashC(fmt.Sprintf("mount -t %s %s %s", req.Filesystem, req.Device, req.MountPoint)); err != nil {
|
||||
if err := cmdMgr.Run("mount", "-t", req.Filesystem, req.Device, req.MountPoint); err != nil {
|
||||
return buserr.WithErr("MountDiskErr", err)
|
||||
}
|
||||
if req.AutoMount {
|
||||
@@ -156,7 +157,7 @@ func (s *DiskService) UnmountDisk(req request.DiskUnmountRequest) error {
|
||||
if !isPointMounted(req.MountPoint) {
|
||||
return buserr.New("MountDiskErr")
|
||||
}
|
||||
if err := cmd.RunDefaultBashC(fmt.Sprintf("umount -f %s", req.MountPoint)); err != nil {
|
||||
if err := cmd.NewCommandMgr(cmd.WithTimeout(20*time.Second)).Run("umount", "-f", req.MountPoint); err != nil {
|
||||
return buserr.WithErr("MountDiskErr", err)
|
||||
}
|
||||
if err := removeFromFstab(req.MountPoint); err != nil {
|
||||
|
||||
@@ -263,7 +263,7 @@ func (f *FileService) Create(op request.FileCreate) error {
|
||||
func (f *FileService) Delete(op request.FileDelete) error {
|
||||
if op.IsDir {
|
||||
excludeDir := global.Dir.DataDir
|
||||
if filepath.Base(op.Path) == ".1panel_clash" || op.Path == excludeDir {
|
||||
if path.Base(op.Path) == ".1panel_clash" || op.Path == excludeDir {
|
||||
return buserr.New("ErrPathNotDelete")
|
||||
}
|
||||
}
|
||||
@@ -592,6 +592,12 @@ func (f *FileService) DepthDirSize(req request.DirSizeReq) ([]response.DepthDirS
|
||||
func (f *FileService) ReadLogByLine(req request.FileReadByLineReq) (*response.FileLineContent, error) {
|
||||
logFilePath := ""
|
||||
taskStatus := ""
|
||||
if len(req.Name) != 0 {
|
||||
safeName := path.Base(req.Name)
|
||||
if safeName != req.Name || strings.Contains(safeName, "..") {
|
||||
return nil, buserr.New("ErrInvalidParams")
|
||||
}
|
||||
}
|
||||
switch req.Type {
|
||||
case constant.TypeWebsite:
|
||||
website, err := websiteRepo.GetFirst(repo.WithByID(req.ID))
|
||||
@@ -649,9 +655,9 @@ func (f *FileService) ReadLogByLine(req request.FileReadByLineReq) (*response.Fi
|
||||
logFilePath = taskModel.LogFile
|
||||
taskStatus = taskModel.Status
|
||||
case "mysql-slow-logs":
|
||||
logFilePath = path.Join(global.Dir.DataDir, fmt.Sprintf("apps/mysql/%s/data/1Panel-slow.log", req.Name))
|
||||
logFilePath = path.Join(global.Dir.DataDir, "apps", "mysql", req.Name, "data", "1Panel-slow.log")
|
||||
case "mariadb-slow-logs":
|
||||
logFilePath = path.Join(global.Dir.DataDir, fmt.Sprintf("apps/mariadb/%s/db/data/1Panel-slow.log", req.Name))
|
||||
logFilePath = path.Join(global.Dir.DataDir, "apps", "mariadb", req.Name, "db", "data", "1Panel-slow.log")
|
||||
case "php-fpm-slow-logs":
|
||||
php, err := runtimeRepo.GetFirst(context.Background(), repo.WithByID(req.ID))
|
||||
if err != nil {
|
||||
@@ -666,8 +672,7 @@ func (f *FileService) ReadLogByLine(req request.FileReadByLineReq) (*response.Fi
|
||||
}
|
||||
logFilePath, _ = ini_conf.GetIniValue(configPath, "supervisord", "logfile")
|
||||
case constant.Supervisor:
|
||||
logDir := path.Join(global.Dir.DataDir, "tools", "supervisord", "log")
|
||||
logFilePath = path.Join(logDir, req.Name)
|
||||
logFilePath = path.Join(global.Dir.DataDir, "tools", "supervisord", "log", req.Name)
|
||||
}
|
||||
|
||||
file, err := os.Open(logFilePath)
|
||||
|
||||
@@ -278,6 +278,10 @@ func (h *HostToolService) OperateSupervisorProcess(req request.SupervisorProcess
|
||||
}
|
||||
|
||||
func handleProcess(supervisordDir string, req request.SupervisorProcessConfig, containerName string) error {
|
||||
safeName := path.Base(req.Name)
|
||||
if safeName != req.Name || strings.Contains(safeName, "..") {
|
||||
return buserr.New("ErrInvalidParams")
|
||||
}
|
||||
var (
|
||||
fileOp = files.NewFileOp()
|
||||
logDir = path.Join(supervisordDir, "log")
|
||||
|
||||
@@ -4,6 +4,10 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"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/response"
|
||||
@@ -23,9 +27,6 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/nginx/parser"
|
||||
"github.com/subosito/gotenv"
|
||||
"gopkg.in/yaml.v3"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type McpServerService struct{}
|
||||
|
||||
@@ -677,7 +677,7 @@ func (r *RuntimeService) GetPHPExtensions(runtimeID uint) (response.PHPExtension
|
||||
return res, err
|
||||
}
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(20 * time.Second))
|
||||
out, err := cmdMgr.RunWithStdoutBashCf("docker exec -i %s php -m", runtime.ContainerName)
|
||||
out, err := cmdMgr.RunWithStdout("docker", "exec", "-i", runtime.ContainerName, "php", "-m")
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
@@ -722,7 +722,7 @@ func (r *RuntimeService) InstallPHPExtension(req request.PHPExtensionInstallReq)
|
||||
}
|
||||
installTask.AddSubTask("", func(t *task.Task) error {
|
||||
err = cmd.NewCommandMgr(cmd.WithTask(*installTask), cmd.WithTimeout(20*time.Minute)).
|
||||
RunBashCf("docker exec -i %s install-ext %s", runtime.ContainerName, req.Name)
|
||||
Run("docker", "exec", "-i", runtime.ContainerName, "install-ext", req.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -736,7 +736,7 @@ func (r *RuntimeService) InstallPHPExtension(req request.PHPExtensionInstallReq)
|
||||
return err
|
||||
}
|
||||
err = cmd.NewCommandMgr(cmd.WithTask(*installTask), cmd.WithTimeout(15*time.Minute)).
|
||||
RunBashCf("docker commit %s %s", runtime.ContainerName, runtime.Image)
|
||||
Run("docker", "commit", runtime.ContainerName, runtime.Image)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ func (u *SnapshotService) SnapshotRecover(req dto.SnapshotRecover) error {
|
||||
|
||||
var snapJson SnapshotJson
|
||||
taskItem.AddSubTaskWithAliasAndOps(
|
||||
"Readjson",
|
||||
"ReadJson",
|
||||
func(t *task.Task) error {
|
||||
snapJson, err = readFromJson(path.Join(rootDir, snap.Name), &itemHelper)
|
||||
return err
|
||||
@@ -156,14 +156,6 @@ func (u *SnapshotService) SnapshotRecover(req dto.SnapshotRecover) error {
|
||||
)
|
||||
req.IsNew = true
|
||||
}
|
||||
if req.IsNew || snap.InterruptStep == "RecoverDBData" {
|
||||
taskItem.AddSubTaskWithAliasAndOps(
|
||||
"RecoverDBData",
|
||||
func(t *task.Task) error { return recoverDBData(path.Join(rootDir, snap.Name, "db"), &itemHelper) },
|
||||
nil, 0, 90*time.Minute,
|
||||
)
|
||||
req.IsNew = true
|
||||
}
|
||||
if req.IsNew || snap.InterruptStep == "RecoverBackups" {
|
||||
taskItem.AddSubTaskWithAliasAndOps(
|
||||
"RecoverBackups",
|
||||
@@ -222,13 +214,24 @@ func (u *SnapshotService) SnapshotRecover(req dto.SnapshotRecover) error {
|
||||
)
|
||||
req.IsNew = true
|
||||
}
|
||||
taskItem.AddSubTaskWithAliasAndOps(
|
||||
"RecoverDBData",
|
||||
func(t *task.Task) error {
|
||||
return restartCompose(path.Join(snapJson.BaseDir, "1panel/docker/compose"), &itemHelper)
|
||||
},
|
||||
nil, 0, 90*time.Minute,
|
||||
)
|
||||
if req.IsNew || snap.InterruptStep == "RecoverCompose" {
|
||||
taskItem.AddSubTaskWithAliasAndOps(
|
||||
"RecoverCompose",
|
||||
func(t *task.Task) error {
|
||||
return restartCompose(path.Join(snapJson.BaseDir, "1panel/docker/compose"), &itemHelper)
|
||||
},
|
||||
nil, 0, 90*time.Minute,
|
||||
)
|
||||
req.IsNew = true
|
||||
}
|
||||
if req.IsNew || snap.InterruptStep == "RecoverDBData" {
|
||||
taskItem.AddSubTaskWithAliasAndOps(
|
||||
"RecoverDBData",
|
||||
func(t *task.Task) error { return recoverDBData(path.Join(rootDir, snap.Name, "db"), &itemHelper) },
|
||||
nil, 0, 90*time.Minute,
|
||||
)
|
||||
req.IsNew = true
|
||||
}
|
||||
|
||||
if err := taskItem.Execute(); err != nil {
|
||||
_ = settingRepo.Update("SystemStatus", "Free")
|
||||
@@ -343,22 +346,22 @@ func backupBeforeRecover(name string, itemHelper *snapRecoverHelper) error {
|
||||
|
||||
func readFromJson(rootDir string, itemHelper *snapRecoverHelper) (SnapshotJson, error) {
|
||||
itemHelper.Task.Log("---------------------- 4 / 11 ----------------------")
|
||||
itemHelper.Task.LogStart(i18n.GetMsgByKey("Readjson"))
|
||||
itemHelper.Task.LogStart(i18n.GetMsgByKey("ReadJson"))
|
||||
|
||||
snapJsonPath := path.Join(rootDir, "base/snapshot.json")
|
||||
var snap SnapshotJson
|
||||
_, err := os.Stat(snapJsonPath)
|
||||
itemHelper.Task.LogWithStatus(i18n.GetMsgByKey("ReadjsonPath"), err)
|
||||
itemHelper.Task.LogWithStatus(i18n.GetMsgByKey("ReadJsonPath"), err)
|
||||
if err != nil {
|
||||
return snap, err
|
||||
}
|
||||
fileByte, err := os.ReadFile(snapJsonPath)
|
||||
itemHelper.Task.LogWithStatus(i18n.GetMsgByKey("ReadjsonContent"), err)
|
||||
itemHelper.Task.LogWithStatus(i18n.GetMsgByKey("ReadJsonContent"), err)
|
||||
if err != nil {
|
||||
return snap, err
|
||||
}
|
||||
err = json.Unmarshal(fileByte, &snap)
|
||||
itemHelper.Task.LogWithStatus(i18n.GetMsgByKey("ReadjsonMarshal"), err)
|
||||
itemHelper.Task.LogWithStatus(i18n.GetMsgByKey("ReadJsonMarshal"), err)
|
||||
if err != nil {
|
||||
return snap, err
|
||||
}
|
||||
@@ -439,17 +442,8 @@ func recoverBaseData(src string, itemHelper *snapRecoverHelper) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func recoverDBData(src string, itemHelper *snapRecoverHelper) error {
|
||||
itemHelper.Task.Log("---------------------- 7 / 11 ----------------------")
|
||||
itemHelper.Task.LogStart(i18n.GetMsgByKey("RecoverDBData"))
|
||||
err := itemHelper.FileOp.CopyDirWithExclude(src, global.Dir.DataDir, nil)
|
||||
|
||||
itemHelper.Task.LogWithStatus(i18n.GetMsgByKey("RecoverDBData"), err)
|
||||
return err
|
||||
}
|
||||
|
||||
func restartCompose(composePath string, itemHelper *snapRecoverHelper) error {
|
||||
itemHelper.Task.Log("---------------------- 11 / 11 ----------------------")
|
||||
itemHelper.Task.Log("---------------------- 7 / 11 ----------------------")
|
||||
itemHelper.Task.LogStart(i18n.GetMsgByKey("RecoverCompose"))
|
||||
|
||||
composes, err := composeRepo.ListRecord()
|
||||
@@ -472,3 +466,64 @@ func restartCompose(composePath string, itemHelper *snapRecoverHelper) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func recoverDBData(src string, itemHelper *snapRecoverHelper) error {
|
||||
itemHelper.Task.Log("---------------------- 11 / 11 ----------------------")
|
||||
itemHelper.Task.LogStart(i18n.GetMsgByKey("RecoverDBData"))
|
||||
dbDir := path.Join(global.Dir.DataDir, "db")
|
||||
if err := os.RemoveAll(dbDir); err != nil {
|
||||
itemHelper.Task.LogWithStatus(i18n.GetMsgByKey("RecoverDBData"), err)
|
||||
return err
|
||||
}
|
||||
|
||||
err := itemHelper.FileOp.CopyDirWithExclude(src, global.Dir.DataDir, nil)
|
||||
if err != nil {
|
||||
itemHelper.Task.LogWithStatus(i18n.GetMsgByKey("RecoverDBData"), err)
|
||||
return err
|
||||
}
|
||||
if cleanErr := cleanOrphanSQLiteSidecars(dbDir); cleanErr != nil {
|
||||
itemHelper.Task.LogWithStatus(i18n.GetMsgByKey("RecoverDBData"), cleanErr)
|
||||
return cleanErr
|
||||
}
|
||||
|
||||
itemHelper.Task.LogWithStatus(i18n.GetMsgByKey("RecoverDBData"), nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
func cleanOrphanSQLiteSidecars(dbDir string) error {
|
||||
entries, err := os.ReadDir(dbDir)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
for _, entry := range entries {
|
||||
if entry.IsDir() {
|
||||
continue
|
||||
}
|
||||
|
||||
name := entry.Name()
|
||||
var mainDB string
|
||||
switch {
|
||||
case strings.HasSuffix(name, ".db-wal"):
|
||||
mainDB = strings.TrimSuffix(name, "-wal")
|
||||
case strings.HasSuffix(name, ".db-shm"):
|
||||
mainDB = strings.TrimSuffix(name, "-shm")
|
||||
default:
|
||||
continue
|
||||
}
|
||||
|
||||
if _, statErr := os.Stat(path.Join(dbDir, mainDB)); statErr != nil {
|
||||
if !os.IsNotExist(statErr) {
|
||||
return statErr
|
||||
}
|
||||
if removeErr := os.Remove(path.Join(dbDir, name)); removeErr != nil && !os.IsNotExist(removeErr) {
|
||||
return removeErr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
+49
-13
@@ -269,16 +269,26 @@ func (u *SSHService) CreateRootCert(req dto.RootCertOperate) error {
|
||||
publicPath := fmt.Sprintf("%s/.ssh/%s.pub", currentUser.HomeDir, req.Name)
|
||||
authFilePath := currentUser.HomeDir + "/.ssh/authorized_keys"
|
||||
|
||||
authFileItem, _ := os.ReadFile(authFilePath)
|
||||
authFile := string(authFileItem)
|
||||
if authFile != "" && !strings.HasSuffix(authFile, "\n") {
|
||||
file, err := os.OpenFile(authFilePath, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644)
|
||||
if info, err := os.Stat(authFilePath); err == nil && info.Size() > 0 {
|
||||
f, err := os.Open(authFilePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
if _, err := file.WriteString("\n"); err != nil {
|
||||
return err
|
||||
defer func() { _ = f.Close() }()
|
||||
|
||||
if _, err := f.Seek(-1, 2); err == nil {
|
||||
buf := make([]byte, 1)
|
||||
if _, err := f.Read(buf); err == nil && buf[0] != '\n' {
|
||||
appendFile, err := os.OpenFile(authFilePath, os.O_APPEND|os.O_WRONLY, 0600)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := appendFile.Write([]byte("\n")); err != nil {
|
||||
_ = appendFile.Close()
|
||||
return err
|
||||
}
|
||||
_ = appendFile.Close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -290,17 +300,43 @@ func (u *SSHService) CreateRootCert(req dto.RootCertOperate) error {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
command := fmt.Sprintf("ssh-keygen -t %s -f %s/.ssh/%s -N ''", req.EncryptionMode, currentUser.HomeDir, req.Name)
|
||||
if len(req.PassPhrase) != 0 {
|
||||
command = fmt.Sprintf("ssh-keygen -t %s -P %s -f %s/.ssh/%s | echo y", req.EncryptionMode, req.PassPhrase, currentUser.HomeDir, req.Name)
|
||||
tmpPrivatePath := privatePath + ".tmp"
|
||||
tmpPublicPath := privatePath + ".tmp.pub"
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(2 * time.Minute))
|
||||
args := []string{
|
||||
"-t", req.EncryptionMode,
|
||||
"-f", tmpPrivatePath,
|
||||
"-N", req.PassPhrase,
|
||||
"-q",
|
||||
}
|
||||
if err := cmd.RunDefaultBashC(command); err != nil {
|
||||
|
||||
if err := cmdMgr.Run("ssh-keygen", args...); err != nil {
|
||||
_ = os.Remove(tmpPrivatePath)
|
||||
_ = os.Remove(tmpPublicPath)
|
||||
return fmt.Errorf("generate failed, %v", err)
|
||||
}
|
||||
if err := os.Rename(tmpPrivatePath, privatePath); err != nil {
|
||||
return fmt.Errorf("replace private key failed, %v", err)
|
||||
}
|
||||
if err := os.Rename(tmpPublicPath, publicPath); err != nil {
|
||||
return fmt.Errorf("replace public key failed, %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := cmd.RunDefaultBashCf("cat %s >> %s", publicPath, authFilePath); err != nil {
|
||||
return fmt.Errorf("generate failed, %v", err)
|
||||
publicKeyBytes, err := os.ReadFile(publicPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("read public key failed, %v", err)
|
||||
}
|
||||
|
||||
cleanKey := strings.TrimRight(string(publicKeyBytes), "\n") + "\n"
|
||||
authFile, err := os.OpenFile(authFilePath, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
|
||||
if err != nil {
|
||||
return fmt.Errorf("open authorized_keys failed, %v", err)
|
||||
}
|
||||
defer func() { _ = authFile.Close() }()
|
||||
|
||||
if _, err := authFile.Write([]byte(cleanKey)); err != nil {
|
||||
return fmt.Errorf("append authorized_keys failed, %v", err)
|
||||
}
|
||||
|
||||
cert.PrivateKeyPath = privatePath
|
||||
|
||||
@@ -110,6 +110,7 @@ type IWebsiteService interface {
|
||||
GetProxyCache(id uint) (res response.NginxProxyCache, err error)
|
||||
ClearProxyCache(req request.NginxCommonReq) error
|
||||
DeleteProxy(req request.WebsiteProxyDel) (err error)
|
||||
UpdateProxyStatus(req request.WebsiteProxyStatusUpdate) (err error)
|
||||
|
||||
CreateWebsiteDomain(create request.WebsiteDomainCreate) ([]model.WebsiteDomain, error)
|
||||
GetWebsiteDomain(websiteId uint) ([]model.WebsiteDomain, error)
|
||||
@@ -173,11 +174,10 @@ func (w WebsiteService) PageWebsite(req request.WebsiteSearch) (int64, []respons
|
||||
switch web.Type {
|
||||
case constant.Deployment:
|
||||
appInstall, err := appInstallRepo.GetFirst(repo.WithByID(web.AppInstallID))
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
if err == nil {
|
||||
appName = appInstall.Name
|
||||
appInstallID = appInstall.ID
|
||||
}
|
||||
appName = appInstall.Name
|
||||
appInstallID = appInstall.ID
|
||||
case constant.Runtime:
|
||||
runtime, _ := runtimeRepo.GetFirst(context.Background(), repo.WithByID(web.RuntimeID))
|
||||
if runtime != nil {
|
||||
@@ -1325,7 +1325,7 @@ func (w WebsiteService) UpdateSitePermission(req request.WebsiteUpdateDirPermiss
|
||||
}
|
||||
absoluteIndexPath := GetSitePath(website, SiteIndexDir)
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(10 * time.Second))
|
||||
if err := cmdMgr.RunBashCf("%s chown -R %s:%s %s", cmd.SudoHandleCmd(), req.User, req.Group, absoluteIndexPath); err != nil {
|
||||
if err := cmdMgr.Run("chown", "-R", fmt.Sprintf("%s:%s", req.User, req.Group), absoluteIndexPath); err != nil {
|
||||
return err
|
||||
}
|
||||
website.User = req.User
|
||||
@@ -1906,6 +1906,10 @@ func (w WebsiteService) UpdateRedirectFile(req request.NginxRedirectUpdate) (err
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
safeName := path.Base(req.Name)
|
||||
if safeName != req.Name || strings.Contains(safeName, "..") {
|
||||
return buserr.New("ErrInvalidParams")
|
||||
}
|
||||
absolutePath := path.Join(GetSitePath(website, SiteRedirectDir), req.Name+".conf")
|
||||
fileOp := files.NewFileOp()
|
||||
oldRewriteContent, err = fileOp.GetContent(absolutePath)
|
||||
@@ -2333,9 +2337,25 @@ func (w WebsiteService) ExecComposer(req request.ExecComposerReq) error {
|
||||
siteDir, _ := settingRepo.Get(settingRepo.WithByKey("WEBSITE_DIR"))
|
||||
execDir := strings.ReplaceAll(req.Dir, siteDir.Value, "/www")
|
||||
composerTask.AddSubTask("", func(t *task.Task) error {
|
||||
cmdStr := fmt.Sprintf("docker exec -u %s %s sh -c 'composer config -g repo.packagist composer %s && composer %s --working-dir=%s'", req.User, runtime.ContainerName, req.Mirror, command, execDir)
|
||||
err = cmdMgr.RunBashC(cmdStr)
|
||||
if err != nil {
|
||||
if err := cmdMgr.Run("docker", "exec",
|
||||
"-u", req.User,
|
||||
runtime.ContainerName,
|
||||
"composer",
|
||||
"config", "-g",
|
||||
"repo.packagist",
|
||||
"composer",
|
||||
req.Mirror,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := cmdMgr.Run("docker", "exec",
|
||||
"-u", req.User,
|
||||
runtime.ContainerName,
|
||||
"composer",
|
||||
command,
|
||||
"--working-dir="+execDir,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -3,6 +3,10 @@ package service
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"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/response"
|
||||
@@ -16,9 +20,6 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/nginx/components"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/nginx/parser"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (w WebsiteService) GetAuthBasics(req request.NginxAuthReq) (res response.NginxAuthRes, err error) {
|
||||
@@ -260,6 +261,10 @@ func (w WebsiteService) UpdatePathAuthBasic(req request.NginxPathAuthUpdate) err
|
||||
if !fileOp.Stat(passDir) {
|
||||
_ = fileOp.CreateDir(passDir, constant.DirPerm)
|
||||
}
|
||||
safeName := path.Base(req.Name)
|
||||
if safeName != req.Name || strings.Contains(safeName, "..") {
|
||||
return buserr.New("ErrInvalidParams")
|
||||
}
|
||||
confPath := path.Join(authDir, fmt.Sprintf("%s.conf", req.Name))
|
||||
passPath := path.Join(passDir, fmt.Sprintf("%s.pass", req.Name))
|
||||
var config *components.Config
|
||||
@@ -306,7 +311,7 @@ func (w WebsiteService) UpdatePathAuthBasic(req request.NginxPathAuthUpdate) err
|
||||
}
|
||||
nginxInclude := fmt.Sprintf("/www/sites/%s/path_auth/*.conf", website.Alias)
|
||||
if err = updateNginxConfig(constant.NginxScopeServer, []dto.NginxParam{{Name: "include", Params: []string{nginxInclude}}}, &website); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -3,6 +3,10 @@ package service
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto/request"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/repo"
|
||||
@@ -13,9 +17,6 @@ import (
|
||||
"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/parser"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (w WebsiteService) GetLoadBalances(id uint) ([]dto.NginxUpstream, error) {
|
||||
@@ -87,6 +88,10 @@ func (w WebsiteService) CreateLoadBalance(req request.WebsiteLBCreate) error {
|
||||
if !fileOp.Stat(includeDir) {
|
||||
_ = fileOp.CreateDir(includeDir, constant.DirPerm)
|
||||
}
|
||||
safeName := path.Base(req.Name)
|
||||
if safeName != req.Name || strings.Contains(safeName, "..") {
|
||||
return buserr.New("ErrInvalidParams")
|
||||
}
|
||||
filePath := path.Join(includeDir, fmt.Sprintf("%s.conf", req.Name))
|
||||
if fileOp.Stat(filePath) {
|
||||
return buserr.New("ErrNameIsExist")
|
||||
@@ -133,6 +138,10 @@ func (w WebsiteService) UpdateLoadBalance(req request.WebsiteLBUpdate) error {
|
||||
}
|
||||
includeDir := GetSitePath(website, SiteUpstreamDir)
|
||||
fileOp := files.NewFileOp()
|
||||
safeName := path.Base(req.Name)
|
||||
if safeName != req.Name || strings.Contains(safeName, "..") {
|
||||
return buserr.New("ErrInvalidParams")
|
||||
}
|
||||
filePath := path.Join(includeDir, fmt.Sprintf("%s.conf", req.Name))
|
||||
if !fileOp.Stat(filePath) {
|
||||
return nil
|
||||
@@ -191,6 +200,10 @@ func (w WebsiteService) DeleteLoadBalance(req request.WebsiteLBDelete) error {
|
||||
|
||||
includeDir := GetSitePath(website, SiteUpstreamDir)
|
||||
fileOp := files.NewFileOp()
|
||||
safeName := path.Base(req.Name)
|
||||
if safeName != req.Name || strings.Contains(safeName, "..") {
|
||||
return buserr.New("ErrInvalidParams")
|
||||
}
|
||||
filePath := path.Join(includeDir, fmt.Sprintf("%s.conf", req.Name))
|
||||
if !fileOp.Stat(filePath) {
|
||||
return nil
|
||||
@@ -211,6 +224,10 @@ func (w WebsiteService) UpdateLoadBalanceFile(req request.WebsiteLBUpdateFile) e
|
||||
return err
|
||||
}
|
||||
includeDir := GetSitePath(website, SiteUpstreamDir)
|
||||
safeName := path.Base(req.Name)
|
||||
if safeName != req.Name || strings.Contains(safeName, "..") {
|
||||
return buserr.New("ErrInvalidParams")
|
||||
}
|
||||
filePath := path.Join(includeDir, fmt.Sprintf("%s.conf", req.Name))
|
||||
fileOp := files.NewFileOp()
|
||||
oldContent, err := fileOp.GetContent(filePath)
|
||||
|
||||
@@ -24,6 +24,21 @@ import (
|
||||
)
|
||||
|
||||
func (w WebsiteService) OperateProxy(req request.WebsiteProxyConfig) (err error) {
|
||||
switch req.Operate {
|
||||
case "delete":
|
||||
return w.DeleteProxy(request.WebsiteProxyDel{
|
||||
ID: req.ID,
|
||||
Name: req.Name,
|
||||
})
|
||||
case "disable":
|
||||
fallthrough
|
||||
case "enable":
|
||||
return w.UpdateProxyStatus(request.WebsiteProxyStatusUpdate{
|
||||
ID: req.ID,
|
||||
Name: req.Name,
|
||||
Status: req.Operate,
|
||||
})
|
||||
}
|
||||
var (
|
||||
website model.Website
|
||||
par *parser.Parser
|
||||
@@ -81,16 +96,8 @@ func (w WebsiteService) OperateProxy(req request.WebsiteProxyConfig) (err error)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
case "delete":
|
||||
_ = fileOp.DeleteFile(includePath)
|
||||
_ = fileOp.DeleteFile(backPath)
|
||||
return updateNginxConfig(constant.NginxScopeServer, nil, &website)
|
||||
case "disable":
|
||||
_ = fileOp.Rename(includePath, backPath)
|
||||
return updateNginxConfig(constant.NginxScopeServer, nil, &website)
|
||||
case "enable":
|
||||
_ = fileOp.Rename(backPath, includePath)
|
||||
return updateNginxConfig(constant.NginxScopeServer, nil, &website)
|
||||
default:
|
||||
return errors.New("unknown operate")
|
||||
}
|
||||
|
||||
config.FilePath = includePath
|
||||
@@ -391,24 +398,47 @@ func (w WebsiteService) ClearProxyCache(req request.NginxCommonReq) error {
|
||||
}
|
||||
|
||||
func (w WebsiteService) DeleteProxy(req request.WebsiteProxyDel) (err error) {
|
||||
fileOp := files.NewFileOp()
|
||||
website, err := websiteRepo.GetFirst(repo.WithByID(req.ID))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
includeDir := path.Join(nginxInstall.GetPath(), "www", "sites", website.Alias, "proxy")
|
||||
includeDir := GetSitePath(website, SiteProxyDir)
|
||||
fileOp := files.NewFileOp()
|
||||
if !fileOp.Stat(includeDir) {
|
||||
_ = fileOp.CreateDir(includeDir, 0755)
|
||||
return
|
||||
}
|
||||
fileName := fmt.Sprintf("%s.conf", req.Name)
|
||||
includePath := path.Join(includeDir, fileName)
|
||||
backName := fmt.Sprintf("%s.bak", req.Name)
|
||||
backPath := path.Join(includeDir, backName)
|
||||
|
||||
_ = fileOp.DeleteFile(includePath)
|
||||
_ = fileOp.DeleteFile(backPath)
|
||||
return updateNginxConfig(constant.NginxScopeServer, nil, &website)
|
||||
}
|
||||
|
||||
func (w WebsiteService) UpdateProxyStatus(req request.WebsiteProxyStatusUpdate) (err error) {
|
||||
website, err := websiteRepo.GetFirst(repo.WithByID(req.ID))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
includeDir := GetSitePath(website, SiteProxyDir)
|
||||
fileOp := files.NewFileOp()
|
||||
if !fileOp.Stat(includeDir) {
|
||||
return
|
||||
}
|
||||
fileName := fmt.Sprintf("%s.conf", req.Name)
|
||||
includePath := path.Join(includeDir, fileName)
|
||||
backName := fmt.Sprintf("%s.bak", req.Name)
|
||||
backPath := path.Join(includeDir, backName)
|
||||
|
||||
switch req.Status {
|
||||
case "disable":
|
||||
_ = fileOp.Rename(includePath, backPath)
|
||||
return updateNginxConfig(constant.NginxScopeServer, nil, &website)
|
||||
case "enable":
|
||||
_ = fileOp.Rename(backPath, includePath)
|
||||
return updateNginxConfig(constant.NginxScopeServer, nil, &website)
|
||||
}
|
||||
return errors.New("unknown status")
|
||||
}
|
||||
|
||||
@@ -4,6 +4,10 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"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/response"
|
||||
@@ -12,9 +16,6 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/agent/cmd/server/nginx_conf"
|
||||
"github.com/1Panel-dev/1Panel/agent/constant"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/files"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (w WebsiteService) UpdateRewriteConfig(req request.NginxRewriteUpdate) error {
|
||||
@@ -73,6 +74,10 @@ func (w WebsiteService) GetRewriteConfig(req request.NginxRewriteReq) (*response
|
||||
contentByte, _ = nginx_conf.Rewrites.ReadFile(rewriteFile)
|
||||
if contentByte == nil {
|
||||
customRewriteDir := GetOpenrestyDir(DefaultRewriteDir)
|
||||
safeName := path.Base(req.Name)
|
||||
if safeName != req.Name || strings.Contains(safeName, "..") {
|
||||
return nil, buserr.New("ErrInvalidParams")
|
||||
}
|
||||
customRewriteFile := path.Join(customRewriteDir, fmt.Sprintf("%s.conf", strings.ToLower(req.Name)))
|
||||
contentByte, err = files.NewFileOp().GetContent(customRewriteFile)
|
||||
}
|
||||
@@ -90,6 +95,10 @@ func (w WebsiteService) OperateCustomRewrite(req request.CustomRewriteOperate) e
|
||||
return err
|
||||
}
|
||||
}
|
||||
safeName := path.Base(req.Name)
|
||||
if safeName != req.Name || strings.Contains(safeName, "..") {
|
||||
return buserr.New("ErrInvalidParams")
|
||||
}
|
||||
rewriteFile := path.Join(rewriteDir, fmt.Sprintf("%s.conf", req.Name))
|
||||
switch req.Operate {
|
||||
case "create":
|
||||
|
||||
@@ -1048,6 +1048,31 @@ func opWebsite(website *model.Website, operate string) error {
|
||||
proxy := fmt.Sprintf("http://%s", website.Proxy)
|
||||
server.UpdateRootProxy([]string{proxy})
|
||||
}
|
||||
case constant.Subsite:
|
||||
parentWebsite, err := websiteRepo.GetFirst(repo.WithByID(website.ParentWebsiteID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
website.Proxy = parentWebsite.Proxy
|
||||
rootIndex = path.Join("/www/sites", parentWebsite.Alias, "index", website.SiteDir)
|
||||
if parentWebsite.Type == constant.Runtime {
|
||||
parentRuntime, err := runtimeRepo.GetFirst(context.Background(), repo.WithByID(parentWebsite.RuntimeID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
website.RuntimeID = parentRuntime.ID
|
||||
if parentRuntime.Type == constant.RuntimePHP {
|
||||
server.UpdateRoot(rootIndex)
|
||||
localPath := ""
|
||||
if parentRuntime.Resource == constant.ResourceLocal {
|
||||
localPath = path.Join(rootIndex, "index.php")
|
||||
}
|
||||
server.UpdatePHPProxy([]string{website.Proxy}, localPath)
|
||||
}
|
||||
}
|
||||
if parentWebsite.Type == constant.Static {
|
||||
server.UpdateRoot(rootIndex)
|
||||
}
|
||||
}
|
||||
website.Status = constant.WebRunning
|
||||
now := time.Now()
|
||||
|
||||
@@ -4,11 +4,6 @@ base:
|
||||
is_demo: false
|
||||
is_offline: false
|
||||
|
||||
remote_url:
|
||||
app_repo: https://apps-assets.fit2cloud.com
|
||||
repo_url: https://resource.fit2cloud.com/1panel/package/v2
|
||||
resource_url: https://resource.fit2cloud.com/1panel/resource/v2
|
||||
|
||||
log:
|
||||
level: debug
|
||||
time_zone: Asia/Shanghai
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
package docs
|
||||
|
||||
import _ "embed"
|
||||
|
||||
//go:embed x-log.json
|
||||
var XLogJson []byte
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,6 +8,7 @@ const (
|
||||
|
||||
AppOpenresty = "openresty"
|
||||
AppOpenclaw = "openclaw"
|
||||
AppCopaw = "copaw"
|
||||
AppMysql = "mysql"
|
||||
AppMariaDB = "mariadb"
|
||||
AppPostgresql = "postgresql"
|
||||
|
||||
+13
-2
@@ -1,8 +1,9 @@
|
||||
package cron
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
mathRand "math/rand"
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/model"
|
||||
@@ -43,7 +44,17 @@ func Run() {
|
||||
if _, err := global.Cron.AddJob("@daily", job.NewSSLJob()); err != nil {
|
||||
global.LOG.Errorf("can not add ssl corn job: %s", err.Error())
|
||||
}
|
||||
if _, err := global.Cron.AddJob(fmt.Sprintf("%v %v * * *", mathRand.Intn(60), mathRand.Intn(3)), job.NewAppStoreJob()); err != nil {
|
||||
minuteRand, err := rand.Int(rand.Reader, big.NewInt(60))
|
||||
if err != nil {
|
||||
global.LOG.Errorf("generate random minute failed: %v", err)
|
||||
minuteRand = big.NewInt(0)
|
||||
}
|
||||
hourRand, err := rand.Int(rand.Reader, big.NewInt(3))
|
||||
if err != nil {
|
||||
global.LOG.Errorf("generate random hour failed: %v", err)
|
||||
hourRand = big.NewInt(0)
|
||||
}
|
||||
if _, err := global.Cron.AddJob(fmt.Sprintf("%v %v * * *", minuteRand.Int64(), hourRand.Int64()), job.NewAppStoreJob()); err != nil {
|
||||
global.LOG.Errorf("can not add appstore corn job: %s", err.Error())
|
||||
}
|
||||
if _, err := global.Cron.AddJob("0 3 */31 * *", job.NewBackupJob()); err != nil {
|
||||
|
||||
@@ -2,13 +2,13 @@ package global
|
||||
|
||||
type ServerConfig struct {
|
||||
Base Base `mapstructure:"base"`
|
||||
RemoteURL RemoteURL `mapstructure:"remote_url"`
|
||||
Log LogConfig `mapstructure:"log"`
|
||||
DockerConfig DockerConfig
|
||||
}
|
||||
|
||||
type Base struct {
|
||||
Port string `mapstructure:"port"`
|
||||
Edition string `mapstructure:"edition"` // [ cn / intl]
|
||||
Version string `mapstructure:"version"`
|
||||
EncryptKey string `mapstructure:"encrypt_key"`
|
||||
Mode string `mapstructure:"mode"` // xpack [ Enable / Disable ]
|
||||
@@ -17,12 +17,6 @@ type Base struct {
|
||||
IsOffLine bool `mapstructure:"is_offline"`
|
||||
}
|
||||
|
||||
type RemoteURL struct {
|
||||
AppRepo string `mapstructure:"app_repo"`
|
||||
RepoUrl string `mapstructure:"repo_url"`
|
||||
ResourceUrl string `mapstructure:"resource_url"`
|
||||
}
|
||||
|
||||
type SystemDir struct {
|
||||
BaseDir string
|
||||
DbDir string
|
||||
|
||||
@@ -40,3 +40,22 @@ var (
|
||||
|
||||
TaskCtxMap = make(map[string]context.CancelFunc)
|
||||
)
|
||||
|
||||
func RepoURL() string {
|
||||
if CONF.Base.Edition != "intl" {
|
||||
return "https://resource.fit2cloud.com/1panel/package/v2"
|
||||
}
|
||||
return "https://resource.1panel.pro/v2"
|
||||
}
|
||||
func ResourceURL() string {
|
||||
if CONF.Base.Edition != "intl" {
|
||||
return "https://resource.fit2cloud.com/1panel/resource/v2"
|
||||
}
|
||||
return "https://resource.1panel.pro/v2/resource"
|
||||
}
|
||||
func AppRepoURL() string {
|
||||
if CONF.Base.Edition != "intl" {
|
||||
return "https://apps-assets.fit2cloud.com"
|
||||
}
|
||||
return "https://apps.1panel.pro"
|
||||
}
|
||||
|
||||
+8
-7
@@ -50,7 +50,7 @@ require (
|
||||
golang.org/x/crypto v0.46.0
|
||||
golang.org/x/net v0.48.0
|
||||
golang.org/x/oauth2 v0.34.0
|
||||
golang.org/x/sys v0.39.0
|
||||
golang.org/x/sys v0.40.0
|
||||
golang.org/x/text v0.32.0
|
||||
google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38
|
||||
gopkg.in/ini.v1 v1.67.0
|
||||
@@ -59,7 +59,7 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
filippo.io/edwards25519 v1.1.1 // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
|
||||
github.com/BurntSushi/toml v1.5.0 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
@@ -94,6 +94,7 @@ require (
|
||||
github.com/bytedance/sonic/loader v0.1.1 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/clbanning/mxj v1.8.4 // indirect
|
||||
github.com/clbanning/mxj/v2 v2.7.0 // indirect
|
||||
github.com/cloudwego/base64x v0.1.4 // indirect
|
||||
@@ -236,14 +237,14 @@ require (
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.60.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
|
||||
go.opentelemetry.io/otel v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel v1.40.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk/metric v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.40.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.40.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk/metric v1.40.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.40.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
|
||||
+14
-15
@@ -31,8 +31,8 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl
|
||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
filippo.io/edwards25519 v1.1.1 h1:YpjwWWlNmGIDyXOn8zLzqiD+9TyIlPhGFG96P39uBpw=
|
||||
filippo.io/edwards25519 v1.1.1/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=
|
||||
@@ -189,7 +189,6 @@ github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyY
|
||||
github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
|
||||
github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
@@ -1025,8 +1024,8 @@ go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.60.0/go.mod h1:CosX/aS4eHnG9D7nESYpV753l4j9q5j3SL/PUYd2lR8=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q=
|
||||
go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=
|
||||
go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM=
|
||||
go.opentelemetry.io/otel v1.40.0 h1:oA5YeOcpRTXq6NN7frwmwFR0Cn3RhTVZvXsP4duvCms=
|
||||
go.opentelemetry.io/otel v1.40.0/go.mod h1:IMb+uXZUKkMXdPddhwAHm6UfOwJyh4ct1ybIlV14J0g=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0 h1:QcFwRrZLc82r8wODjvyCbP7Ifp3UANaBSmhDSFjnqSc=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0/go.mod h1:CXIWhUomyWBG/oY2/r/kLp6K/cmx9e/7DLpBuuGdLCA=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 h1:1fTNlAIJZGWLP5FVu0fikVry1IsiUnXjf7QFvoNN3Xw=
|
||||
@@ -1035,14 +1034,14 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 h1:m639+
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0/go.mod h1:LjReUci/F4BUyv+y4dwnq3h/26iNOeC3wAIqgvTIZVo=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 h1:xJ2qHD0C1BeYVTLLR9sX12+Qb95kfeD/byKj6Ky1pXg=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0/go.mod h1:u5BF1xyjstDowA1R5QAO9JHzqK+ublenEW/dyqTjBVk=
|
||||
go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA=
|
||||
go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI=
|
||||
go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E=
|
||||
go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA=
|
||||
go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=
|
||||
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
|
||||
go.opentelemetry.io/otel/metric v1.40.0 h1:rcZe317KPftE2rstWIBitCdVp89A2HqjkxR3c11+p9g=
|
||||
go.opentelemetry.io/otel/metric v1.40.0/go.mod h1:ib/crwQH7N3r5kfiBZQbwrTge743UDc7DTFVZrrXnqc=
|
||||
go.opentelemetry.io/otel/sdk v1.40.0 h1:KHW/jUzgo6wsPh9At46+h4upjtccTmuZCFAc9OJ71f8=
|
||||
go.opentelemetry.io/otel/sdk v1.40.0/go.mod h1:Ph7EFdYvxq72Y8Li9q8KebuYUr2KoeyHx0DRMKrYBUE=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.40.0 h1:mtmdVqgQkeRxHgRv4qhyJduP3fYJRMX4AtAlbuWdCYw=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.40.0/go.mod h1:4Z2bGMf0KSK3uRjlczMOeMhKU2rhUqdWNoKcYrtcBPg=
|
||||
go.opentelemetry.io/otel/trace v1.40.0 h1:WA4etStDttCSYuhwvEa8OP8I5EWu24lkOzp+ZYblVjw=
|
||||
go.opentelemetry.io/otel/trace v1.40.0/go.mod h1:zeAhriXecNGP/s2SEG3+Y8X9ujcJOTqQ5RgdEJcawiA=
|
||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||
go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4=
|
||||
go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4=
|
||||
@@ -1308,8 +1307,8 @@ golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
|
||||
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
|
||||
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
|
||||
+286
-295
@@ -1,115 +1,116 @@
|
||||
ErrInvalidParams: 'Request parameter error: {{ .detail }}'
|
||||
ErrTokenParse: 'Token generation error: {{ .detail }}'
|
||||
ErrInvalidParams: 'Bad request: {{ .detail }}'
|
||||
ErrTokenParse: 'Token error: {{ .detail }}'
|
||||
ErrInitialPassword: 'Original password is incorrect'
|
||||
ErrInternalServer: 'Internal server error: {{ .detail }}'
|
||||
ErrRecordExist: 'Record already exists'
|
||||
ErrRecordNotFound: 'Record not found'
|
||||
ErrStructTransform: 'Type conversion failed: {{ .err }}'
|
||||
ErrNotLogin: 'User not logged in: {{ .detail }}'
|
||||
ErrPasswordExpired: 'The current password has expired: {{ .detail }}'
|
||||
ErrNotSupportType: 'The system does not support the current type: {{ .name }}'
|
||||
ErrProxy: 'Request error, please check the node status: {{ .detail }}'
|
||||
ErrApiConfigStatusInvalid: 'Access to the API interface is prohibited: {{ .detail }}'
|
||||
ErrApiConfigKeyInvalid: 'API interface key error: {{ .detail }}'
|
||||
ErrApiConfigIPInvalid: 'The IP used to call the API interface is not in the whitelist: {{ .detail }}'
|
||||
ErrApiConfigDisable: 'This interface prohibits the use of API interface calls: {{ .detail }}'
|
||||
ErrApiConfigKeyTimeInvalid: 'API interface timestamp error: {{ .detail }}'
|
||||
ErrShutDown: "Command manually terminated!"
|
||||
ErrNotLogin: 'Not logged in: {{ .detail }}'
|
||||
ErrPasswordExpired: 'Password expired: {{ .detail }}'
|
||||
ErrNotSupportType: 'Unsupported type: {{ .name }}'
|
||||
ErrProxy: 'Request failed: {{ .detail }}'
|
||||
ErrApiConfigStatusInvalid: 'API access disabled: {{ .detail }}'
|
||||
ErrApiConfigKeyInvalid: 'Invalid API key: {{ .detail }}'
|
||||
ErrApiConfigIPInvalid: 'IP not in API allowlist: {{ .detail }}'
|
||||
ErrApiConfigDisable: 'Endpoint not allowed via API: {{ .detail }}'
|
||||
ErrApiConfigKeyTimeInvalid: 'Invalid API timestamp: {{ .detail }}'
|
||||
ErrShutDown: 'Command stopped manually'
|
||||
|
||||
ErrMinQuickJump: "Please set at least one quick jump entry!"
|
||||
ErrMaxQuickJump: "You can set up to four quick jump entries!"
|
||||
ErrMinQuickJump: 'Set at least one quick jump entry'
|
||||
ErrMaxQuickJump: 'At most 4 quick jump entries'
|
||||
|
||||
#common
|
||||
ErrUsernameIsExist: 'Username already exists'
|
||||
ErrNameIsExist: 'Name already exists'
|
||||
ErrDemoEnvironment: 'Demo server, this operation is forbidden!'
|
||||
ErrCmdTimeout: 'Command execution timed out!'
|
||||
ErrCmdIllegal: 'There are illegal characters in the execution command, please modify it and try again!'
|
||||
ErrDemoEnvironment: 'Disabled in demo environment'
|
||||
ErrCmdTimeout: 'Command timed out'
|
||||
ErrCmdIllegal: 'Command has invalid characters'
|
||||
ErrPortExist: '{{ .port }} port is already occupied by {{ .type }} [{{ .name }}]'
|
||||
TYPE_APP: 'Application'
|
||||
TYPE_RUNTIME: 'Runtime environment'
|
||||
TYPE_DOMAIN: 'Domain Name'
|
||||
ErrTypePort: 'Port {{ .name }} format is incorrect'
|
||||
ErrTypePortRange: 'The port range needs to be between 1-65535'
|
||||
TYPE_RUNTIME: 'Runtime'
|
||||
TYPE_DOMAIN: 'Domain'
|
||||
ErrTypePort: 'Invalid port format: {{ .name }}'
|
||||
ErrTypePortRange: 'Port range must be 1-65535'
|
||||
Success: 'Success'
|
||||
Failed: 'Failed'
|
||||
SystemRestart: 'Task interrupted due to system restart'
|
||||
SystemRestart: 'Task interrupted by system restart'
|
||||
ErrGroupIsDefault: 'Default group, cannot be deleted'
|
||||
ErrGroupIsInWebsiteUse: 'The group is being used by another website and cannot be deleted.'
|
||||
ErrGroupIsInWebsiteUse: 'Group is in use by a website'
|
||||
Decrypt: "Decrypt"
|
||||
|
||||
#agent
|
||||
ErrAgentAccountBound: 'This account is bound to an agent and cannot be deleted. Please check and try again!'
|
||||
ErrAgentAccountUnavailable: 'The account connection information is unavailable. Error: {{ .err }}. Please check and try again!'
|
||||
ErrAgentProviderNotSupported: 'This agent provider is not supported. Please check and try again!'
|
||||
ErrAgentAccountRequired: 'Please select an agent account and try again.'
|
||||
ErrAgentAccountNotVerified: 'The account has not been verified. Please check and try again!'
|
||||
ErrAgentProviderMismatch: 'The account provider does not match. Please check and try again!'
|
||||
ErrAgentBaseURLRequired: 'Base URL cannot be empty. Please check and try again!'
|
||||
ErrAgentApiKeyRequired: 'API Key cannot be empty. Please check and try again!'
|
||||
ErrAgentComposeRequired: 'Custom compose content cannot be empty. Please check and try again!'
|
||||
ErrAgentIDRequired: 'Agent ID cannot be empty. Please check and try again!'
|
||||
ErrAgentAccountIDRequired: 'Account ID cannot be empty. Please check and try again!'
|
||||
ErrAgentAccountBound: 'Account is bound to an agent and cannot be deleted'
|
||||
ErrAgentAccountUnavailable: 'Account connection unavailable: {{ .err }}'
|
||||
ErrAgentProviderNotSupported: 'Unsupported agent provider'
|
||||
ErrAgentAccountRequired: 'Select an agent account first'
|
||||
ErrAgentAccountNotVerified: 'Agent account not verified'
|
||||
ErrAgentProviderMismatch: 'Agent provider mismatch'
|
||||
ErrAgentBaseURLRequired: 'Base URL is required'
|
||||
ErrAgentApiKeyRequired: 'API key is required'
|
||||
ErrAgentComposeRequired: 'Compose content is required'
|
||||
ErrAgentIDRequired: 'Agent ID is required'
|
||||
ErrAgentAccountIDRequired: 'Account ID is required'
|
||||
ErrAgentLimitReached: 'Community Edition supports up to {{ .max }} AI agents. Upgrade to Professional Edition for unlimited agents'
|
||||
|
||||
#backup
|
||||
Localhost: 'Local Machine'
|
||||
ErrBackupInUsed: 'The backup account has been used in the scheduled task and cannot be deleted.'
|
||||
ErrBackupCheck: 'Backup account test connection failed {{ .err }}'
|
||||
ErrBackupLocalDelete: 'Deleting the local server backup account is not supported yet'
|
||||
ErrBackupLocalCreate: 'Creating local server backup accounts is not supported yet'
|
||||
Localhost: 'Local'
|
||||
ErrBackupInUsed: 'Backup account is in use by a scheduled task'
|
||||
ErrBackupCheck: 'Backup account connectivity test failed: {{ .err }}'
|
||||
ErrBackupLocalDelete: 'Local backup accounts cannot be deleted'
|
||||
ErrBackupLocalCreate: 'Local backup accounts cannot be created'
|
||||
|
||||
#app
|
||||
ErrPortInUsed: '{{ .detail }} port is already occupied!'
|
||||
ErrAppLimit: 'The number of applications installed has exceeded the limit'
|
||||
ErrAppLimit: 'App install limit reached'
|
||||
ErrNotInstall: 'Application not installed'
|
||||
ErrPortInOtherApp: '{{ .port }} port is already occupied by application {{ .apps }}!'
|
||||
ErrDbUserNotValid: 'Existing database, username and password do not match!'
|
||||
ErrUpdateBuWebsite: 'The application was updated successfully, but the website configuration file modification failed. Please check the configuration! '
|
||||
ErrDbUserNotValid: 'Database username/password mismatch'
|
||||
ErrUpdateBuWebsite: 'App updated, but website config update failed'
|
||||
Err1PanelNetworkFailed: 'Default container network creation failed! {{ .detail }}'
|
||||
ErrFileParse: 'Application docker-compose file parsing failed!'
|
||||
ErrInstallDirNotFound: 'The installation directory does not exist. If you need to uninstall, please select Force Uninstall'
|
||||
ErrFileParse: 'Failed to parse app docker-compose file'
|
||||
ErrInstallDirNotFound: 'Install directory not found; use Force Uninstall'
|
||||
AppStoreIsUpToDate: 'The app store is already the latest version'
|
||||
LocalAppVersionNull: '{{ .name }} application is not synchronized to the version! Cannot be added to the application list'
|
||||
LocalAppVersionErr: '{{ .name }} sync version {{ .version }} failed! {{ .err }}'
|
||||
LocalAppVersionNull: 'App {{ .name }} has no synced version'
|
||||
LocalAppVersionErr: 'Failed to sync {{ .name }} version {{ .version }}: {{ .err }}'
|
||||
ErrFileNotFound: '{{ .name }} file does not exist'
|
||||
ErrFileParseApp: '{{ .name }} file parsing failed {{ .err }}'
|
||||
ErrFileParseApp: 'Failed to parse {{ .name }}: {{ .err }}'
|
||||
ErrAppDirNull: 'The version folder does not exist'
|
||||
LocalAppErr: 'Application {{ .name }} sync failed! {{ .err }}'
|
||||
LocalAppErr: 'Failed to sync app {{ .name }}: {{ .err }}'
|
||||
ErrContainerName: 'Container name already exists'
|
||||
ErrCreateHttpClient: 'Failed to create request {{ .err }}'
|
||||
ErrHttpReqTimeOut: 'Request timed out {{ .err }}'
|
||||
ErrHttpReqFailed: 'Request failed {{ .err }}'
|
||||
ErrNoSuchHost: 'Unable to find the requested server {{ .err }}'
|
||||
ErrHttpReqNotFound: 'The requested resource {{ .err }} could not be found'
|
||||
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'
|
||||
ErrContainerMsg: '{{ .name }} container is abnormal. Please check the log on the container page for details'
|
||||
ErrAppBackup: '{{ .name }} application backup failed {{ .err }}'
|
||||
ErrVersionTooLow: 'The current 1Panel version is too low to update the App Store. Please upgrade the version before operating.'
|
||||
ErrContainerMsg: 'Container {{ .name }} is abnormal; check logs'
|
||||
ErrAppBackup: 'App backup failed: {{ .name }} {{ .err }}'
|
||||
ErrVersionTooLow: '1Panel version too low to update App Store'
|
||||
ErrAppNameExist: 'The application name already exists'
|
||||
AppStoreIsSyncing: 'The App Store is syncing, please try again later'
|
||||
ErrGetCompose: 'Failed to obtain the docker-compose.yml file! {{ .detail }}'
|
||||
ErrAppWarn: 'Abnormal status, please check the log'
|
||||
ErrAppParamKey: 'Parameter {{ .name }} field is abnormal'
|
||||
ErrAppUpgrade: 'Application {{ .name }} upgrade failed {{ .err }}'
|
||||
AppStoreIsSyncing: 'App Store is syncing; try again later'
|
||||
ErrGetCompose: 'Failed to read docker-compose.yml: {{ .detail }}'
|
||||
ErrAppWarn: 'App status abnormal; check logs'
|
||||
ErrAppParamKey: 'Invalid app parameter: {{ .name }}'
|
||||
ErrAppUpgrade: 'App upgrade failed: {{ .name }} {{ .err }}'
|
||||
AppRecover: 'Rollback application {{ .name }}'
|
||||
PullImageStart: 'Start pulling image [{{ .name }}]'
|
||||
PullImageSuccess: 'Image pull successful'
|
||||
AppStoreIsLastVersion: 'The App Store is already the latest version'
|
||||
AppStoreSyncSuccess: 'App Store synchronization successful'
|
||||
SyncAppDetail: 'Synchronize application configuration'
|
||||
AppVersionNotMatch: '{{ .name }} application requires a higher 1Panel version, skipping synchronization'
|
||||
MoveSiteDir: "Detected website directory change. Need to migrate OpenResty website directory to {{ .name }}"
|
||||
MoveSiteDirSuccess: 'Successful migration of website directory'
|
||||
PullImageStart: 'Pull image [{{ .name }}]'
|
||||
PullImageSuccess: 'Image pulled'
|
||||
AppStoreSyncSuccess: 'App Store synced'
|
||||
SyncAppDetail: 'Sync app config'
|
||||
AppVersionNotMatch: 'Skip {{ .name }}: requires newer 1Panel'
|
||||
MoveSiteDir: 'Website dir changed; migrate OpenResty dir to {{ .name }}'
|
||||
MoveSiteDirSuccess: 'Website dir migrated'
|
||||
DeleteRuntimePHP: 'Delete PHP runtime'
|
||||
CustomAppStoreFileValid: 'App store packages need to be in .tar.gz format'
|
||||
PullImageTimeout: 'Pull image timeout, please try to increase the image acceleration or change to another image acceleration'
|
||||
ErrAppIsDown: '{{ .name }} application status is abnormal, please check'
|
||||
ErrCustomApps: 'There is an installed application, please uninstall it first'
|
||||
ErrCustomRuntimes: 'There is an installed runtime environment, please delete it first'
|
||||
CustomAppStoreFileValid: 'App Store package must be .tar.gz'
|
||||
PullImageTimeout: 'Image pull timed out; try another mirror'
|
||||
ErrAppIsDown: 'App {{ .name }} is abnormal'
|
||||
ErrCustomApps: 'Installed apps detected; uninstall first'
|
||||
ErrCustomRuntimes: 'Installed runtimes detected; delete first'
|
||||
ErrAppVersionDeprecated: "The {{ .name }} application is not compatible with the current 1Panel version, skipped"
|
||||
ErrDockerFailed: "The state of Docker is abnormal, please check the service status"
|
||||
ErrDockerComposeCmdNotFound: "The Docker Compose command does not exist, please install this command on the host machine first"
|
||||
UseExistImage: 'Failed to pull image, using existing image'
|
||||
ErrDockerFailed: 'Docker is abnormal; check service status'
|
||||
ErrDockerComposeCmdNotFound: 'Docker Compose not found on host'
|
||||
UseExistImage: 'Image exists; using existing image'
|
||||
ErrDatabaseNotFound: 'Database not found: {{ .name }}'
|
||||
|
||||
#ssh
|
||||
ExportIP: "Login IP"
|
||||
@@ -121,42 +122,42 @@ ExportStatus: "Login Status"
|
||||
ExportDate: "Time"
|
||||
|
||||
#file
|
||||
ErrFileCanNotRead: 'This file does not support preview'
|
||||
ErrFileToLarge: 'The file is larger than 10M and cannot be opened'
|
||||
ErrFileCanNotRead: 'File preview is not supported'
|
||||
ErrFileToLarge: 'File is larger than 10 MB'
|
||||
ErrPathNotFound: 'Directory does not exist'
|
||||
ErrMovePathFailed: 'The target path cannot contain the original path!'
|
||||
ErrMovePathFailed: 'Target path cannot include source path'
|
||||
ErrLinkPathNotFound: 'The target path does not exist!'
|
||||
ErrFileIsExist: 'The file or folder already exists!'
|
||||
ErrFileUpload: '{{ .name }} failed to upload file {{ .detail }}'
|
||||
ErrFileDownloadDir: 'Download folder is not supported'
|
||||
ErrCmdNotFound: '{{ .name}} command does not exist, please install this command on the host first'
|
||||
ErrFileUpload: 'Upload failed: {{ .name }} {{ .detail }}'
|
||||
ErrFileDownloadDir: 'Directory download is not supported'
|
||||
ErrCmdNotFound: 'Command not found: {{ .name }}'
|
||||
ErrSourcePathNotFound: 'Source directory does not exist'
|
||||
ErrFavoriteExist: 'This path has already been favorited'
|
||||
ErrFavoriteExist: 'Path already in favorites'
|
||||
ErrInvalidChar: 'Illegal characters are not allowed'
|
||||
ErrPathNotDelete: 'The selected directory cannot be deleted'
|
||||
ErrLogFileToLarge: "The log file exceeds 500MB and cannot be opened"
|
||||
FileDropFailed: "Failed to clean up file {{ .name }}: {{ .err }}"
|
||||
FileDropSuccess: "Successfully cleaned up file {{ .name }}, cleaned {{ .count }} files, freed {{ .size }} disk space"
|
||||
FileDropSum: "File cleanup completed successfully, total {{ .count }} files cleaned, total {{ .size }} disk space freed"
|
||||
ErrBadDecrypt: "Compressed package decryption password error, decompression failed, please check and try again!"
|
||||
ErrLogFileToLarge: 'Log file exceeds 500 MB'
|
||||
FileDropFailed: 'File cleanup failed: {{ .name }} {{ .err }}'
|
||||
FileDropSuccess: 'Cleaned {{ .name }}; files: {{ .count }}, freed: {{ .size }}'
|
||||
FileDropSum: 'Cleanup done; files: {{ .count }}, freed: {{ .size }}'
|
||||
ErrBadDecrypt: 'Wrong archive password; extract failed'
|
||||
|
||||
#website
|
||||
ErrAliasIsExist: 'Alias already exists'
|
||||
ErrBackupMatch: 'The backup file does not match some of the current website data {{ .detail }}'
|
||||
ErrBackupExist: 'The corresponding part of the source data in the backup file does not exist {{ .detail }}'
|
||||
ErrPHPResource: 'The local operating environment does not support switching! '
|
||||
ErrPathPermission: 'A folder with non-1000:1000 permissions was detected in the index directory, which may cause an Access denied error on the website. Please click the Save button above'
|
||||
ErrBackupMatch: 'Backup data mismatch: {{ .detail }}'
|
||||
ErrBackupExist: 'Backup source data missing: {{ .detail }}'
|
||||
ErrPHPResource: 'Switching local runtime is not supported'
|
||||
ErrPathPermission: 'Non-1000:1000 folder in index dir may cause Access denied'
|
||||
ErrDomainIsUsed: 'The domain name is already used by the website [{{ .name }}]'
|
||||
ErrDomainFormat: '{{ .name }} domain name format is incorrect'
|
||||
ErrDefaultAlias: 'default is a reserved code, please use another code'
|
||||
ErrParentWebsite: 'You need to delete the subsite {{ .name }} first'
|
||||
ErrDomainFormat: 'Invalid domain format: {{ .name }}'
|
||||
ErrDefaultAlias: 'default is reserved; use another alias'
|
||||
ErrParentWebsite: 'Delete subsite {{ .name }} first'
|
||||
ErrBuildDirNotFound: 'The build directory does not exist'
|
||||
ErrImageNotExist: 'The operating environment {{ .name }} image does not exist, please re-edit the operating environment'
|
||||
ErrProxyIsUsed: "Load balancing has been used by reverse proxy, cannot be deleted"
|
||||
ErrSSLValid: 'Certificate file is abnormal, please check the certificate status!'
|
||||
ErrWebsiteDir: "Please select a directory within the website directory."
|
||||
ErrImageNotExist: 'Runtime image not found: {{ .name }}'
|
||||
ErrProxyIsUsed: 'Load balancer is used by reverse proxy'
|
||||
ErrSSLValid: 'Certificate file is invalid'
|
||||
ErrWebsiteDir: 'Select a subdirectory under the website directory'
|
||||
ErrComposerFileNotFound: "composer.json file does not exist"
|
||||
ErrRuntimeNoPort: "The runtime environment is not set with a port, please edit the runtime environment first."
|
||||
ErrRuntimeNoPort: 'Runtime port is not set'
|
||||
Status: 'Status'
|
||||
start: 'Start'
|
||||
stop: 'Stop'
|
||||
@@ -166,157 +167,157 @@ pause: 'Pause'
|
||||
unpause: 'Resume'
|
||||
remove: 'Delete'
|
||||
delete: 'Delete'
|
||||
ErrDefaultWebsite: 'Default website has been set, please cancel it before setting!'
|
||||
ErrDefaultWebsite: 'Default website already set; unset it first'
|
||||
SSL: 'Certificate'
|
||||
Set: 'Settings'
|
||||
|
||||
#ssl
|
||||
ErrSSLCannotDelete: 'The {{ .name }} certificate is being used by a website and cannot be deleted'
|
||||
ErrAccountCannotDelete: 'The account is associated with a certificate and cannot be deleted'
|
||||
ErrSSLApply: 'Certificate renewal successful, openresty reload failed, please check the configuration!'
|
||||
ErrEmailIsExist: 'The mailbox already exists'
|
||||
ErrSSLCannotDelete: 'Certificate {{ .name }} is in use by a website'
|
||||
ErrAccountCannotDelete: 'Account is linked to a certificate and cannot be deleted'
|
||||
ErrSSLApply: 'Certificate renewed; OpenResty reload failed'
|
||||
ErrEmailIsExist: 'Email already exists'
|
||||
ErrSSLKeyNotFound: 'The private key file does not exist'
|
||||
ErrSSLCertificateNotFound: 'The certificate file does not exist'
|
||||
ErrSSLKeyFormat: 'Private key file verification failed'
|
||||
ErrSSLCertificateFormat: 'The certificate file format is incorrect, please use pem format'
|
||||
ErrSSLCertificateFormat: 'Invalid certificate format; use PEM'
|
||||
ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid or EabHmacKey cannot be blank'
|
||||
ErrOpenrestyNotFound: 'Http mode requires Openresty to be installed first'
|
||||
ApplySSLStart: 'Start applying for a certificate, domain name [{{ .domain }}] application method [{{ .type }}] '
|
||||
ErrOpenrestyNotFound: 'HTTP mode requires OpenResty'
|
||||
ApplySSLStart: 'Starting certificate request. Domain: [{{ .domain }}], method: [{{ .type }}]'
|
||||
dnsAccount: 'DNS Auto'
|
||||
dnsManual: 'DNS Manual'
|
||||
http: 'HTTP'
|
||||
ApplySSLFailed: 'Application for [{{ .domain }}] certificate failed, {{ .detail }} '
|
||||
ApplySSLSuccess: 'Apply for [{{ .domain }}] certificate successfully! !'
|
||||
DNSAccountName: 'DNS account [{{ .name }}] vendor [{{ .type }}]'
|
||||
ApplySSLFailed: 'Failed to request certificate for [{{ .domain }}]: {{ .detail }}'
|
||||
ApplySSLSuccess: 'Certificate issued for [{{ .domain }}]'
|
||||
DNSAccountName: 'DNS account [{{ .name }}], provider [{{ .type }}]'
|
||||
PushDirLog: 'Certificate pushed to directory [{{ .path }}] {{ .status }}'
|
||||
ErrDeleteCAWithSSL: 'The current organization has a certificate that has been issued and cannot be deleted.'
|
||||
ErrDeleteWithPanelSSL: 'Panel SSL configuration uses this certificate and cannot be deleted'
|
||||
ErrDeleteCAWithSSL: 'CA has issued certificates; cannot delete'
|
||||
ErrDeleteWithPanelSSL: 'Certificate is in use by Panel SSL settings'
|
||||
ErrDefaultCA: 'The default authority cannot be deleted'
|
||||
ApplyWebSiteSSLLog: 'Starting to renew the {{ .name }} website certificate'
|
||||
ApplyWebSiteSSLLog: 'Updating website certificate: {{ .name }}'
|
||||
ErrUpdateWebsiteSSL: '{{ .name }} website certificate update failed: {{ .err }}'
|
||||
ApplyWebSiteSSLSuccess: 'Update website certificate successfully'
|
||||
ApplyWebSiteSSLSuccess: 'Website certificate updated'
|
||||
ErrExecShell: 'Failed to execute script {{ .err }}'
|
||||
ExecShellStart: 'Start executing the script'
|
||||
ExecShellSuccess: 'Script execution successful'
|
||||
StartUpdateSystemSSL: 'Start updating system certificate'
|
||||
UpdateSystemSSLSuccess: 'Update system certificate successfully'
|
||||
ErrWildcardDomain: 'Unable to apply for wildcard domain name certificate in HTTP mode'
|
||||
ErrApplySSLCanNotDelete: "The certificate {{.name}} being applied for cannot be deleted, please try again later."
|
||||
StartPushSSLToNode: "Starting to push certificate to node"
|
||||
ExecShellStart: 'Run script'
|
||||
ExecShellSuccess: 'Script succeeded'
|
||||
StartUpdateSystemSSL: 'Update system certificate'
|
||||
UpdateSystemSSLSuccess: 'System certificate updated'
|
||||
ErrWildcardDomain: 'Wildcard certificates are not supported in HTTP mode'
|
||||
ErrApplySSLCanNotDelete: 'Certificate {{ .name }} is being issued and cannot be deleted yet'
|
||||
StartPushSSLToNode: 'Push certificate to node'
|
||||
PushSSLToNodeFailed: "Failed to push certificate to node: {{ .err }}"
|
||||
PushSSLToNodeSuccess: "Successfully pushed certificate to node"
|
||||
PushSSLToNodeSuccess: 'Certificate pushed to node'
|
||||
|
||||
#mysql
|
||||
ErrUserIsExist: 'The current user already exists, please re-enter'
|
||||
ErrDatabaseIsExist: 'The current database already exists, please re-enter'
|
||||
ErrExecTimeOut: 'SQL execution timed out, please check the database'
|
||||
ErrRemoteExist: 'The remote database already exists with this name, please modify it and try again'
|
||||
ErrLocalExist: 'The name already exists in the local database, please modify it and try again'
|
||||
RemoteBackup: "To back up the remote database, the local container database service needs to be started first using the image {{ .name }}, please wait..."
|
||||
RemoteRecover: "To restore the remote database, the local container database service needs to be started first using the image {{ .name }}, please wait..."
|
||||
ErrUserIsExist: 'User already exists'
|
||||
ErrDatabaseIsExist: 'Database already exists'
|
||||
ErrExecTimeOut: 'SQL execution timed out'
|
||||
ErrRemoteExist: 'Remote database name already exists'
|
||||
ErrLocalExist: 'Local database name already exists'
|
||||
RemoteBackup: 'Start local DB container with image {{ .name }} before backing up remote DB'
|
||||
RemoteRecover: 'Start local DB container with image {{ .name }} before restoring remote DB'
|
||||
Arg: "Argument"
|
||||
|
||||
#redis
|
||||
ErrTypeOfRedis: 'The recovery file type does not match the current persistence method, please modify it and try again'
|
||||
ErrTypeOfRedis: 'Backup file type does not match current persistence mode'
|
||||
|
||||
#container
|
||||
ErrInUsed: "{{ .detail }} is in use and cannot be deleted!"
|
||||
ErrObjectInUsed: "This object is in use and cannot be deleted!"
|
||||
ErrObjectBeDependent: "This image is depended on by other images and cannot be deleted!"
|
||||
ErrPortRules: 'Port number does not match, please re-enter!'
|
||||
ErrPgImagePull: 'Image pull timed out, please configure image acceleration or manually pull the {{ .name }} image and try again'
|
||||
PruneHelper: "This cleanup {{ .name }} freed disk space {{ .size }}"
|
||||
ImageRemoveHelper: "Deleted image {{ .name }}, freeing {{ .size }} disk space"
|
||||
BuildCache: "Build cache"
|
||||
Volume: "Storage volume"
|
||||
ErrObjectBeDependent: "This image is referenced by other images and cannot be deleted!"
|
||||
ErrPortRules: 'Port count does not match'
|
||||
ErrPgImagePull: 'Image pull timed out; configure acceleration or pull {{ .name }} manually'
|
||||
PruneHelper: "Cleanup {{ .name }} released {{ .size }} disk space"
|
||||
ImageRemoveHelper: "Removed image {{ .name }}, released {{ .size }} disk space"
|
||||
BuildCache: 'Build Cache'
|
||||
Volume: 'Volume'
|
||||
Network: "Network"
|
||||
PruneStart: "Cleaning in progress, please wait..."
|
||||
PruneStart: 'Cleaning in progress'
|
||||
|
||||
#runtime
|
||||
ErrFileNotExist: '{{ .detail }} file does not exist! Please check the integrity of the source file!'
|
||||
ErrFileNotExist: 'Source file not found: {{ .detail }}'
|
||||
ErrImageBuildErr: 'Image build failed'
|
||||
ErrImageExist: "Image already exists! Please modify the image name."
|
||||
ErrDelWithWebsite: 'The operating environment is already associated with a website and cannot be deleted'
|
||||
ErrImageExist: "Image already exists. Use a different image name."
|
||||
ErrDelWithWebsite: 'Runtime is linked to a website and cannot be deleted'
|
||||
ErrRuntimeStart: 'Startup failed'
|
||||
ErrPackageJsonNotFound: 'package.json file does not exist'
|
||||
ErrScriptsNotFound: 'The scripts configuration item was not found in package.json'
|
||||
ErrContainerNameNotFound: 'Unable to get container name, please check .env file'
|
||||
ErrNodeModulesNotFound: 'The node_modules folder does not exist! Please edit the runtime environment or wait for the runtime environment to start successfully'
|
||||
ErrContainerNameIsNull: 'Container name does not exist'
|
||||
ErrPHPPortIsDefault: "Port 9000 is the default port, please modify and try again"
|
||||
ErrPHPRuntimePortFailed: "The port {{ .name }} is already used by the current runtime environment, please modify and try again"
|
||||
ErrScriptsNotFound: 'No scripts section found in package.json'
|
||||
ErrContainerNameNotFound: 'Container name not found; check .env'
|
||||
ErrNodeModulesNotFound: 'node_modules not found; edit runtime or wait for startup'
|
||||
ErrContainerNameIsNull: 'Container name is empty'
|
||||
ErrPHPPortIsDefault: 'Port 9000 is reserved as default; use another port'
|
||||
ErrPHPRuntimePortFailed: 'Port {{ .name }} is already used by this runtime'
|
||||
|
||||
#tool
|
||||
ErrConfigNotFound: 'Configuration file does not exist'
|
||||
ErrConfigParse: 'The configuration file format is incorrect'
|
||||
ErrConfigParse: 'Invalid configuration file format'
|
||||
ErrConfigIsNull: 'Configuration file cannot be empty'
|
||||
ErrConfigDirNotFound: 'The running directory does not exist'
|
||||
ErrConfigAlreadyExist: 'A configuration file with the same name already exists'
|
||||
ErrUserFindErr: 'User {{ .name }} search failed {{ .err }}'
|
||||
ErrConfigDirNotFound: 'Run directory not found'
|
||||
ErrConfigAlreadyExist: 'Configuration file with the same name already exists'
|
||||
ErrUserFindErr: 'Failed to find user {{ .name }}: {{ .err }}'
|
||||
|
||||
#cronjob
|
||||
CutWebsiteLogSuccess: '{{ .name }} website log cut successfully, backup path {{ .path }}'
|
||||
HandleShell: 'Execute script {{ .name }}'
|
||||
HandleCurl: "Access URL {{ .name }}"
|
||||
HandleNtpSync: 'System time synchronization'
|
||||
HandleSystemClean: 'System cache cleanup'
|
||||
CutWebsiteLogSuccess: 'Website log rotated: {{ .name }} (backup: {{ .path }})'
|
||||
HandleShell: 'Run script {{ .name }}'
|
||||
HandleCurl: 'Request URL {{ .name }}'
|
||||
HandleNtpSync: 'Sync system time'
|
||||
HandleSystemClean: 'Clean system cache'
|
||||
SystemLog: 'System Log'
|
||||
CutWebsiteLog: 'Rotate Website Log'
|
||||
FileOrDir: 'Directory / File'
|
||||
UploadFile: 'Uploading backup file {{ .file }} to {{ .backup }}'
|
||||
UploadFile: 'Upload backup {{ .file }} to {{ .backup }}'
|
||||
Upload: "Upload"
|
||||
IgnoreBackupErr: "Backup failed, error: {{ .detail }}, ignoring this error..."
|
||||
IgnoreUploadErr: "Upload failed, error: {{ .detail }}, ignoring this error..."
|
||||
LoadBackupFailed: "Failed to get backup account connection, error: {{ .detail }}"
|
||||
InExecuting: "The current task is being executed, please do not repeat the execution!"
|
||||
NoSuchResource: "No backup content found in the database, skipping..."
|
||||
CleanLog: "Clean Log"
|
||||
CleanLogByName: "Clean {{.name}} Log"
|
||||
WafIpGroupNotFound: "WAF IP group not found. Please go to [Advanced Features - WAF - Black/White List - IP Group] to add an IP group via remote download method."
|
||||
IgnoreBackupErr: 'Backup failed: {{ .detail }} (ignored)'
|
||||
IgnoreUploadErr: 'Upload failed: {{ .detail }} (ignored)'
|
||||
LoadBackupFailed: 'Failed to get backup account connection info: {{ .detail }}'
|
||||
InExecuting: 'Task is already running'
|
||||
NoSuchResource: 'No backup records found; skipped'
|
||||
CleanLog: 'Clean 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."
|
||||
|
||||
#toolbox
|
||||
ErrNotExistUser: 'The current user does not exist, please modify and try again!'
|
||||
ErrBanAction: 'Setting failed. The current {{ .name }} service is unavailable. Please check and try again!'
|
||||
ErrClamdscanNotFound: 'The clamdscan command was not detected, please refer to the documentation to install it!'
|
||||
TaskSwapSet: "Set Swap"
|
||||
ErrNotExistUser: 'User does not exist'
|
||||
ErrBanAction: 'Config failed: service {{ .name }} unavailable'
|
||||
ErrClamdscanNotFound: 'clamdscan command not found'
|
||||
TaskSwapSet: 'Set swap'
|
||||
SetSwap: "Set Swap {{ .path }} - {{ .size }}"
|
||||
CreateSwap: "Create Swap File"
|
||||
FormatSwap: "Format Swap File"
|
||||
EnableSwap: "Enable Swap"
|
||||
CreateSwap: 'Create swap file'
|
||||
FormatSwap: 'Format swap file'
|
||||
EnableSwap: 'Enable swap'
|
||||
|
||||
#tamper
|
||||
CleanTamperSetting: "Clean up historical protection settings"
|
||||
SetTamperWithRules: "Start directory protection according to rules"
|
||||
CleanTamperSetting: 'Clean historical protection settings'
|
||||
SetTamperWithRules: 'Enable directory protection by rules'
|
||||
ProtectDir: "Protect directory {{ .name }}"
|
||||
IgnoreFile: "Protect file {{ .name }}"
|
||||
TamperSetSuccessful: "Protection settings completed, start monitoring the following directories:"
|
||||
TamperSetSuccessful: 'Protection set. Monitoring these directories:'
|
||||
|
||||
#waf
|
||||
ErrScope: 'Modifying this configuration is not supported'
|
||||
ErrStateChange: 'State change failed'
|
||||
ErrScope: 'This config cannot be changed'
|
||||
ErrStateChange: 'Failed to change state'
|
||||
ErrRuleExist: 'Rule already exists'
|
||||
ErrRuleNotExist: 'Rule does not exist'
|
||||
ErrParseIP: 'Wrong IP format'
|
||||
ErrDefaultIP: 'default is a reserved name, please change it to another name'
|
||||
ErrGroupInUse: 'IP group is used by blacklist/whitelist and cannot be deleted'
|
||||
ErrIPGroupAclUse: "IP group is used by custom rules of website {{ .name }}, cannot be deleted"
|
||||
ErrParseIP: 'Invalid IP format'
|
||||
ErrDefaultIP: 'default is reserved; use another name'
|
||||
ErrGroupInUse: 'IP group is used by blacklist/whitelist rules'
|
||||
ErrIPGroupAclUse: 'IP group is used by website {{ .name }} custom rules'
|
||||
ErrGroupExist: 'IP group name already exists'
|
||||
ErrIPRange: 'Wrong IP range'
|
||||
ErrIPRange: 'Invalid IP range'
|
||||
ErrIPExist: 'IP already exists'
|
||||
urlDefense: 'URL rules'
|
||||
urlHelper: 'Prohibited URL'
|
||||
urlHelper: 'Blocked URL'
|
||||
dirFilter: 'Directory filter'
|
||||
xss: 'XSS'
|
||||
phpExec: 'PHP script execution'
|
||||
oneWordTrojan: 'One Word Trojan'
|
||||
appFilter: 'Apply dangerous directory filtering'
|
||||
webshell: 'Webshell'
|
||||
appFilter: 'App dangerous directory filtering'
|
||||
webShell: 'WebShell'
|
||||
args: 'Parameter rules'
|
||||
protocolFilter: 'Protocol filtering'
|
||||
javaFileter: 'Java dangerous file filter'
|
||||
javaFilter: 'Java dangerous file filtering'
|
||||
scannerFilter: 'Scanner filter'
|
||||
escapeFilter: 'escape filter'
|
||||
customRule: 'Custom rule'
|
||||
escapeFilter: 'Escape filtering'
|
||||
customRule: 'Custom rules'
|
||||
httpMethod: 'HTTP method filtering'
|
||||
fileExt: 'File upload restrictions'
|
||||
defaultIpBlack: 'Malicious IP group'
|
||||
@@ -331,8 +332,8 @@ notFoundCount: '404 Rate Limit'
|
||||
headerDefense: 'Header rules'
|
||||
defaultUaBlack: 'User-Agent rules'
|
||||
methodWhite: 'HTTP rules'
|
||||
captcha: 'human-machine verification'
|
||||
fiveSeconds: '5 seconds verification'
|
||||
captcha: 'Human verification'
|
||||
fiveSeconds: '5-second verification'
|
||||
vulnCheck: 'Supplementary rules'
|
||||
acl: 'Custom rules'
|
||||
sql: 'SQL injection'
|
||||
@@ -340,19 +341,20 @@ cc: 'Access frequency limit'
|
||||
defaultUrlBlack: 'URL rules'
|
||||
sqlInject: 'SQL injection'
|
||||
ErrDBNotExist: 'Database does not exist'
|
||||
allow: 'allow'
|
||||
deny: 'deny'
|
||||
OpenrestyNotFound: 'Openresty is not installed'
|
||||
allow: 'Allow'
|
||||
deny: 'Deny'
|
||||
OpenrestyNotFound: 'OpenResty is not installed'
|
||||
remoteIpIsNull: "IP list is empty"
|
||||
OpenrestyVersionErr: "Openresty version is too low, please upgrade Openresty 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'
|
||||
|
||||
#task
|
||||
TaskStart: '{{ .name }} task starts [START]'
|
||||
TaskEnd: '{{ .name }} Task completed [COMPLETED]'
|
||||
TaskStart: '{{ .name }} [START]'
|
||||
TaskEnd: '{{ .name }} [DONE]'
|
||||
TaskFailed: '{{ .name }} task failed'
|
||||
TaskTimeout: '{{ .name }} timed out'
|
||||
TaskSuccess: '{{ .name }} Task succeeded'
|
||||
TaskRetry: 'Start {{ .name }}th retry'
|
||||
TaskSuccess: '{{ .name }} succeeded'
|
||||
TaskRetry: 'Retry #{{ .name }}'
|
||||
SubTaskSuccess: '{{ .name }} succeeded'
|
||||
SubTaskFailed: '{{ .name }} failed: {{ .err }}'
|
||||
TaskInstall: 'Install'
|
||||
@@ -376,34 +378,34 @@ TaskImport: "Import"
|
||||
TaskExport: "Export"
|
||||
Website: 'Website'
|
||||
App: 'Application'
|
||||
Runtime: 'Runtime environment'
|
||||
Runtime: 'Runtime'
|
||||
Database: 'Database'
|
||||
ConfigFTP: 'Create FTP user {{ .name }}'
|
||||
ConfigOpenresty: 'Create Openresty configuration file'
|
||||
InstallAppSuccess: 'Application {{ .name }} installed successfully'
|
||||
ConfigRuntime: 'Configure the runtime environment'
|
||||
ConfigApp: 'Configuration Application'
|
||||
ConfigOpenresty: 'Create OpenResty config file'
|
||||
InstallAppSuccess: 'App {{ .name }} installed'
|
||||
ConfigRuntime: 'Configure runtime'
|
||||
ConfigApp: 'Configure app'
|
||||
SuccessStatus: '{{ .name }} succeeded'
|
||||
FailedStatus: '{{ .name }} failed {{ .err }}'
|
||||
HandleLink: 'Handle application association'
|
||||
HandleDatabaseApp: 'Handling application parameters'
|
||||
ExecShell: 'Execute {{ .name }} script'
|
||||
FailedStatus: '{{ .name }} failed: {{ .err }}'
|
||||
HandleLink: 'Process app links'
|
||||
HandleDatabaseApp: 'Process app parameters'
|
||||
ExecShell: 'Run script {{ .name }}'
|
||||
PullImage: 'Pull image'
|
||||
Start: 'Start'
|
||||
Run: 'Start'
|
||||
Stop: 'Stop'
|
||||
Image: 'Mirror'
|
||||
Compose: 'Orchestration'
|
||||
Image: 'Image'
|
||||
Compose: 'Compose'
|
||||
Container: 'Container'
|
||||
AppLink: 'Linked Application'
|
||||
EnableSSL: 'Enable HTTPS'
|
||||
AppStore: 'App Store'
|
||||
TaskSync: 'Synchronize'
|
||||
TaskSync: 'Sync'
|
||||
LocalApp: 'Local Application'
|
||||
SubTask: 'Subtask'
|
||||
RuntimeExtension: 'Runtime Environment Extension'
|
||||
RuntimeExtension: 'Runtime extension'
|
||||
TaskIsExecuting: 'Task is running'
|
||||
CustomAppstore: 'Custom application warehouse'
|
||||
CustomAppstore: 'Custom application repository'
|
||||
TaskExec: 'Execute'
|
||||
TaskBatch: "Batch Operation"
|
||||
FileConvert: 'File Conversion'
|
||||
@@ -414,130 +416,119 @@ TaskScan: "Scan"
|
||||
|
||||
# task - ai
|
||||
OllamaModelPull: 'Pull Ollama model {{ .name }}'
|
||||
OllamaModelSize: 'Get the size of Ollama model {{ .name }}'
|
||||
OllamaModelSize: 'Get Ollama model size: {{ .name }}'
|
||||
|
||||
# task-snapshot
|
||||
Snapshot: 'Snapshot'
|
||||
SnapDBInfo: 'Write 1Panel database information'
|
||||
SnapCopy: 'Copy files & directories {{ .name }}'
|
||||
SnapNewDB: 'Initialize database {{ .name }} connection'
|
||||
SnapDeleteOperationLog: 'Delete operation log'
|
||||
SnapDeleteLoginLog: 'Delete access log'
|
||||
SnapDBInfo: 'Write 1Panel DB info'
|
||||
SnapCopy: 'Copy files/directories {{ .name }}'
|
||||
SnapNewDB: 'Init DB connection {{ .name }}'
|
||||
SnapDeleteOperationLog: 'Delete operation logs'
|
||||
SnapDeleteLoginLog: 'Delete access logs'
|
||||
SnapDeleteMonitor: 'Delete monitoring data'
|
||||
SnapRemoveSystemIP: 'Remove system IP'
|
||||
SnapBaseInfo: 'Write 1Panel basic information'
|
||||
SnapInstallAppImageEmpty: 'No application images selected, skipping...'
|
||||
SnapInstallApp: 'Backup 1Panel installed applications'
|
||||
SnapBaseInfo: 'Write 1Panel base info'
|
||||
SnapInstallAppImageEmpty: 'No app images selected; skipped'
|
||||
SnapInstallApp: 'Backup installed apps'
|
||||
SnapDockerSave: 'Compress installed applications'
|
||||
SnapLocalBackup: 'Backup 1Panel local backup directory'
|
||||
SnapLocalBackup: 'Backup local backup directory'
|
||||
SnapCompressBackup: 'Compress local backup directory'
|
||||
SnapPanelData: 'Backup 1Panel data directory'
|
||||
SnapCompressPanel: 'Compressed Data Directory'
|
||||
SnapWebsite: 'Backup 1Panel website directory'
|
||||
SnapCloseDBConn: 'Close the database connection'
|
||||
SnapCompress: 'Make snapshot files'
|
||||
SnapCompressPanel: 'Compress data directory'
|
||||
SnapWebsite: 'Backup website directory'
|
||||
SnapCloseDBConn: 'Close DB connection'
|
||||
SnapCompress: 'Create snapshot file'
|
||||
SnapCompressFile: 'Compress snapshot file'
|
||||
SnapCheckCompress: 'Check snapshot compression file'
|
||||
SnapCompressSize: 'Snapshot file size {{ .name }}'
|
||||
SnapCheckCompress: 'Check snapshot archive'
|
||||
SnapCompressSize: 'Snapshot size {{ .name }}'
|
||||
SnapUpload: 'Upload snapshot file'
|
||||
SnapUploadTo: 'Upload snapshot file to {{ .name }}'
|
||||
SnapUploadRes: 'Upload snapshot file to {{ .name }}'
|
||||
SnapUploadTo: 'Upload snapshot to {{ .name }}'
|
||||
SnapUploadRes: 'Upload snapshot to {{ .name }}'
|
||||
|
||||
SnapshotRecover: 'Snapshot Restore'
|
||||
SnapshotRecover: 'Recover snapshot'
|
||||
RecoverDownload: 'Download snapshot file'
|
||||
Download: 'Download'
|
||||
RecoverDownloadAccount: 'Get snapshot download backup account {{ .name }}'
|
||||
RecoverDecompress: 'Decompress snapshot compressed files'
|
||||
RecoverDownloadAccount: 'Get snapshot download account {{ .name }}'
|
||||
RecoverDecompress: 'Decompress snapshot archive'
|
||||
Decompress: 'Decompression'
|
||||
BackupBeforeRecover: 'Backup system-related data before snapshot'
|
||||
Readjson: 'Read the Json file in the snapshot'
|
||||
ReadjsonPath: 'Get the Json file path in the snapshot'
|
||||
ReadjsonContent: 'Read Json file'
|
||||
ReadjsonMarshal: 'Json escape processing'
|
||||
BackupBeforeRecover: 'Backup system data before recovery'
|
||||
ReadJson: 'Read snapshot JSON file'
|
||||
ReadJsonPath: 'Get snapshot JSON path'
|
||||
ReadJsonContent: 'Read JSON content'
|
||||
ReadJsonMarshal: 'Json escape processing'
|
||||
RecoverApp: 'Restore installed apps'
|
||||
RecoverWebsite: 'Recover website directory'
|
||||
RecoverWebsite: 'Restore website directory'
|
||||
RecoverAppImage: 'Restore snapshot image backup'
|
||||
RecoverCompose: 'Restore other composer content'
|
||||
RecoverComposeList: 'Get all composers to be restored'
|
||||
RecoverCompose: 'Restore other compose projects'
|
||||
RecoverComposeList: 'Get all compose projects to restore'
|
||||
RecoverComposeItem: 'Recover compose {{ .name }}'
|
||||
RecoverAppEmpty: 'No application image backup was found in the snapshot file'
|
||||
RecoverBaseData: 'Recover base data and files'
|
||||
RecoverDaemonJsonEmpty: 'Both the snapshot file and the current machine do not have the container configuration daemon.json file'
|
||||
RecoverDaemonJson: 'Restore container configuration daemon.json file'
|
||||
RecoverAppEmpty: 'No app image backup found in snapshot'
|
||||
RecoverBaseData: 'Restore base data and files'
|
||||
RecoverDaemonJsonEmpty: 'daemon.json not found in snapshot or current host'
|
||||
RecoverDaemonJson: 'Restore daemon.json'
|
||||
RecoverDBData: 'Recover database data'
|
||||
RecoverBackups: 'Restore local backup directory'
|
||||
RecoverPanelData: 'Recovery data directory'
|
||||
RecoverPanelData: 'Restore data directory'
|
||||
|
||||
# task - container
|
||||
ContainerNewCliet: 'Initialize Docker Client'
|
||||
ContainerImagePull: 'Pull container image {{ .name }}'
|
||||
ContainerRemoveOld: 'Remove the original container {{ .name }}'
|
||||
ContainerImageCheck: 'Check if the image is pulled normally'
|
||||
ContainerLoadInfo: 'Get basic container information'
|
||||
ContainerRecreate: 'Container update failed, now starting to restore the original container'
|
||||
ContainerImageCheck: 'Check image pull result'
|
||||
ContainerLoadInfo: 'Load container info'
|
||||
ContainerRecreate: 'Container update failed; restoring original container'
|
||||
ContainerCreate: 'Create a new container {{ .name }}'
|
||||
ContainerCreateFailed: 'Container creation failed, delete the failed container'
|
||||
ContainerStartCheck: 'Check if the container has been started'
|
||||
ContainerCreateFailed: 'Container create failed; deleting failed container'
|
||||
ContainerStartCheck: 'Check container started'
|
||||
|
||||
# task - image
|
||||
ImageBuild: 'Image Build'
|
||||
ImageBuildStdoutCheck: 'Parse image output content'
|
||||
ImageBuildRes: 'Image build output: {{ .name }}'
|
||||
ImageBuild: 'Build image'
|
||||
ImagePull: 'Pull image'
|
||||
ImageRepoAuthFromDB: 'Get repository authentication information from the database'
|
||||
ImaegPullRes: 'Image pull output: {{ .name }}'
|
||||
ImageRepoAuthFromDB: 'Load registry auth from DB'
|
||||
ImagePush: 'Push image'
|
||||
ImageRenameTag: 'Modify image tag'
|
||||
ImageRenameTag: 'Update image tag'
|
||||
ImageNewTag: 'New image tag {{ .name }}'
|
||||
ImaegPushRes: 'Image push output: {{ .name }}'
|
||||
ComposeCreate: 'Create a composition'
|
||||
ComposeCreateRes: 'Compose create output: {{ .name }}'
|
||||
ComposeCreate: 'Create compose project'
|
||||
|
||||
# task - website
|
||||
BackupNginxConfig: 'Backup website OpenResty configuration file'
|
||||
CompressFileSuccess: 'Compress directory successfully, compressed to {{ .name }}'
|
||||
CompressDir: 'Compression directory'
|
||||
BackupNginxConfig: 'Backup website OpenResty config'
|
||||
CompressFileSuccess: 'Directory compressed to {{ .name }}'
|
||||
CompressDir: 'Compress directory'
|
||||
DeCompressFile: 'Decompress file {{ .name }}'
|
||||
ErrCheckValid: 'Backup file verification failed, {{ .name }}'
|
||||
ErrCheckValid: 'Backup file validation failed: {{ .name }}'
|
||||
Rollback: 'Rollback'
|
||||
websiteDir: 'Website Directory'
|
||||
RecoverFailedStartRollBack: 'Recovery failed, start rollback'
|
||||
AppBackupFileIncomplete: 'The backup file is incomplete and lacks app.json or app.tar.gz files'
|
||||
websiteDir: 'Website directory'
|
||||
RecoverFailedStartRollBack: 'Recovery failed; starting rollback'
|
||||
AppBackupFileIncomplete: 'Backup is incomplete: missing app.json or app.tar.gz'
|
||||
AppAttributesNotMatch: 'Application type or name does not match'
|
||||
|
||||
#alert
|
||||
ErrAlert: 'The format of the warning message is incorrect, please check and try again!'
|
||||
ErrAlertPush: 'Error in pushing alert information, please check and try again!'
|
||||
ErrAlertSave: 'Error saving the alarm information, please check and try again!'
|
||||
ErrAlertSync: 'Alarm information synchronization error, please check and try again!'
|
||||
ErrAlertRemote: 'Alarm message remote error, please check and try again!'
|
||||
ErrAlertSync: 'Failed to sync alert message'
|
||||
|
||||
#task - runtime
|
||||
ErrInstallExtension: "An installation task is already in progress, please wait for the task to finish"
|
||||
ErrInstallExtension: 'Another extension install task is running'
|
||||
|
||||
# alert mail template
|
||||
PanelAlertTitle: "Panel Alert Notification"
|
||||
TestAlertTitle: "Test Email - Verify Email Connectivity"
|
||||
TestAlert: "This is a test email to verify that your email sending configuration is correct."
|
||||
LicenseExpirationAlert: "Your {{ .node }}{{ .ip }} Panel, the license will expire in {{ .day }} days. Please log in to the panel for details."
|
||||
CronJobFailedAlert: "Your {{ .node }}{{ .ip }} Panel, scheduled task - {{ .name }} execution failed. Please log in to the panel for details."
|
||||
ClamAlert: "Your {{ .node }}{{ .ip }} Panel, the virus scan task detected {{ .num }} infected files. Please log in to the panel for details."
|
||||
WebSiteAlert: "Your {{ .node }}{{ .ip }} Panel, {{ .num }} websites will expire in {{ .day }} days. Please log in to the panel for details."
|
||||
SSLAlert: "Your {{ .node }}{{ .ip }} Panel, {{ .num }} SSL certificates will expire in {{ .day }} days. Please log in to the panel for details."
|
||||
DiskUsedAlert: "Your {{ .node }}{{ .ip }} Panel, disk {{ .name }} usage has reached {{ .used }}. Please log in to the panel for details."
|
||||
ResourceAlert: "Your {{ .node }}{{ .ip }} Panel, the average {{ .name }} usage rate in {{ .time }} minutes is {{ .used }}. Please log in to the panel for details."
|
||||
PanelVersionAlert: "Your {{ .node }}{{ .ip }} Panel, the latest panel version is available for upgrade. Please log in to the panel for details."
|
||||
PanelPwdExpirationAlert: "Your {{ .node }}{{ .ip }} Panel, the panel password will expire in {{ .day }} days. Please log in to the panel for details."
|
||||
CommonAlert: "Your {{ .node }}{{ .ip }} Panel, {{ .msg }}. Please log in to the panel for details."
|
||||
NodeExceptionAlert: "Your {{ .node }}{{ .ip }} Panel, {{ .num }} nodes are abnormal. Please log in to the panel for details."
|
||||
LicenseExceptionAlert: "Your {{ .node }}{{ .ip }} Panel, {{ .num }} licenses are abnormal. Please log in to the panel for details."
|
||||
SSHAndPanelLoginAlert: "Your {{ .node }}{{ .ip }} Panel, {{ .name }} login from {{ .loginIp }} is abnormal. Please log in to the panel for details."
|
||||
LicenseExpirationAlert: "Panel {{ .node }}{{ .ip }}: license expires in {{ .day }} days. Log in to view details."
|
||||
CronJobFailedAlert: "Panel {{ .node }}{{ .ip }}: scheduled task {{ .name }} failed. Log in to view details."
|
||||
ClamAlert: "Panel {{ .node }}{{ .ip }}: virus scan found {{ .num }} infected files. Log in to view details."
|
||||
WebSiteAlert: "Panel {{ .node }}{{ .ip }}: {{ .num }} websites expire in {{ .day }} days. Log in to view details."
|
||||
SSLAlert: "Panel {{ .node }}{{ .ip }}: {{ .num }} SSL certificates expire in {{ .day }} days. Log in to view details."
|
||||
DiskUsedAlert: "Panel {{ .node }}{{ .ip }}: disk {{ .name }} usage reached {{ .used }}. Log in to view details."
|
||||
ResourceAlert: "Panel {{ .node }}{{ .ip }}: average {{ .name }} usage in {{ .time }} minutes is {{ .used }}. Log in to view details."
|
||||
PanelVersionAlert: "Panel {{ .node }}{{ .ip }}: a new panel version is available. Log in to view details."
|
||||
PanelPwdExpirationAlert: "Panel {{ .node }}{{ .ip }}: panel password expires in {{ .day }} days. Log in to view details."
|
||||
CommonAlert: "Panel {{ .node }}{{ .ip }}: {{ .msg }}. Log in to view details."
|
||||
NodeExceptionAlert: "Panel {{ .node }}{{ .ip }}: {{ .num }} nodes 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."
|
||||
|
||||
#disk
|
||||
DeviceNotFound: "Device {{ .name }} not found"
|
||||
DeviceIsMounted: "Device {{ .name }} is mounted, please unmount first"
|
||||
PartitionDiskErr: "Failed to partition, {{ .err }}"
|
||||
FormatDiskErr: "Failed to format disk, {{ .err }}"
|
||||
MountDiskErr: "Failed to mount disk, {{ .err }}"
|
||||
UnMountDiskErr: "Failed to unmount disk, {{ .err }}"
|
||||
XfsNotFound: "xfs filesystem not detected, please install xfsprogs first"
|
||||
DeviceIsMounted: 'Device {{ .name }} is mounted; unmount first'
|
||||
PartitionDiskErr: 'Partition failed: {{ .err }}'
|
||||
FormatDiskErr: 'Format failed: {{ .err }}'
|
||||
MountDiskErr: 'Mount failed: {{ .err }}'
|
||||
XfsNotFound: 'xfs not found; install xfsprogs first'
|
||||
|
||||
+166
-231
@@ -1,30 +1,27 @@
|
||||
ErrInvalidParams: 'Error en los parámetros de la solicitud: {{ .detail }}'
|
||||
ErrTokenParse: 'Error al generar el token: {{ .detail }}'
|
||||
ErrInitialPassword: 'La contraseña original es incorrecta'
|
||||
ErrInternalServer: 'Error interno del servidor: {{ .detail }}'
|
||||
ErrRecordExist: 'El registro ya existe'
|
||||
ErrInvalidParams: 'Solicitud inválida: {{ .detail }}'
|
||||
ErrTokenParse: 'Token inválido: {{ .detail }}'
|
||||
ErrInitialPassword: 'Contraseña original incorrecta'
|
||||
ErrInternalServer: 'Error interno: {{ .detail }}'
|
||||
ErrRecordExist: 'Registro ya existe'
|
||||
ErrRecordNotFound: 'Registro no encontrado'
|
||||
ErrStructTransform: 'Error de conversión de tipo: {{ .err }}'
|
||||
ErrNotLogin: 'Usuario no ha iniciado sesión: {{ .detail }}'
|
||||
ErrPasswordExpired: 'La contraseña actual ha expirado: {{ .detail }}'
|
||||
ErrNotSupportType: 'El sistema no admite el tipo actual: {{ .name }}'
|
||||
ErrProxy: 'Error en la solicitud, por favor revise el estado del nodo: {{ .detail }}'
|
||||
ErrApiConfigStatusInvalid: 'Se prohíbe el acceso a la interfaz API: {{ .detail }}'
|
||||
ErrApiConfigKeyInvalid: 'Error en la clave de la interfaz API: {{ .detail }}'
|
||||
ErrApiConfigIPInvalid: 'La IP usada para llamar a la API no está en la lista blanca: {{ .detail }}'
|
||||
ErrApiConfigDisable: 'Esta interfaz prohíbe el uso de llamadas a la API: {{ .detail }}'
|
||||
ErrApiConfigKeyTimeInvalid: 'Error en la marca de tiempo de la interfaz API: {{ .detail }}'
|
||||
ErrShutDown: "¡Comando terminado manualmente!"
|
||||
|
||||
ErrMinQuickJump: "¡Por favor configure al menos una entrada de acceso rápido!"
|
||||
ErrMaxQuickJump: "¡Puede configurar hasta cuatro entradas de acceso rápido!"
|
||||
|
||||
#común
|
||||
ErrUsernameIsExist: 'El nombre de usuario ya existe'
|
||||
ErrNameIsExist: 'El nombre ya existe'
|
||||
ErrDemoEnvironment: '¡Servidor de demostración, esta operación está prohibida!'
|
||||
ErrCmdTimeout: '¡Tiempo de espera excedido en la ejecución del comando!'
|
||||
ErrCmdIllegal: 'Hay caracteres ilegales en el comando, ¡modifíquelo e intente de nuevo!'
|
||||
ErrStructTransform: 'Error de conversión: {{ .err }}'
|
||||
ErrNotLogin: 'No has iniciado sesión: {{ .detail }}'
|
||||
ErrPasswordExpired: 'Contraseña expirada: {{ .detail }}'
|
||||
ErrNotSupportType: 'Tipo no soportado: {{ .name }}'
|
||||
ErrProxy: 'Solicitud fallida: {{ .detail }}'
|
||||
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 }}'
|
||||
ErrShutDown: 'Comando detenido manualmente'
|
||||
ErrMinQuickJump: 'Agrega al menos una entrada rápida'
|
||||
ErrMaxQuickJump: 'Máximo 4 entradas rápidas'
|
||||
ErrUsernameIsExist: 'Usuario ya existe'
|
||||
ErrNameIsExist: 'Nombre ya existe'
|
||||
ErrDemoEnvironment: 'No disponible en demo'
|
||||
ErrCmdTimeout: 'Comando agotó tiempo'
|
||||
ErrCmdIllegal: 'Comando contiene caracteres inválidos'
|
||||
ErrPortExist: 'El puerto {{ .port }} ya está ocupado por {{ .type }} [{{ .name }}]'
|
||||
TYPE_APP: 'Aplicación'
|
||||
TYPE_RUNTIME: 'Entorno de ejecución'
|
||||
@@ -36,45 +33,40 @@ Failed: 'Error'
|
||||
SystemRestart: 'La tarea fue interrumpida debido a un reinicio del sistema'
|
||||
ErrGroupIsDefault: 'Grupo predeterminado, no se puede eliminar'
|
||||
ErrGroupIsInWebsiteUse: 'El grupo está siendo usado por otro sitio web y no se puede eliminar.'
|
||||
Decrypt: "Descifrar"
|
||||
|
||||
#agent
|
||||
ErrAgentAccountBound: 'Esta cuenta está vinculada a un agente y no se puede eliminar. Verifique e inténtelo de nuevo!'
|
||||
ErrAgentAccountUnavailable: 'La información de conexión de la cuenta no está disponible. Error: {{ .err }}. Verifique e inténtelo de nuevo!'
|
||||
ErrAgentProviderNotSupported: 'Este proveedor de agente no es compatible. Verifique e inténtelo de nuevo!'
|
||||
ErrAgentAccountRequired: 'Seleccione una cuenta de agente y vuelva a intentarlo.'
|
||||
ErrAgentAccountNotVerified: 'La cuenta no está verificada. Verifique e inténtelo de nuevo!'
|
||||
ErrAgentProviderMismatch: 'El proveedor de la cuenta no coincide. Verifique e inténtelo de nuevo!'
|
||||
ErrAgentBaseURLRequired: 'Base URL no puede estar vacío. Verifique e inténtelo de nuevo!'
|
||||
ErrAgentApiKeyRequired: 'API Key no puede estar vacío. Verifique e inténtelo de nuevo!'
|
||||
ErrAgentComposeRequired: 'El contenido personalizado de compose no puede estar vacío. Verifique e inténtelo de nuevo!'
|
||||
ErrAgentIDRequired: 'El ID del agente no puede estar vacío. Verifique e inténtelo de nuevo!'
|
||||
ErrAgentAccountIDRequired: 'El ID de la cuenta no puede estar vacío. Verifique e inténtelo de nuevo!'
|
||||
|
||||
#backup
|
||||
ErrBackupInUsed: 'La cuenta de respaldo está siendo utilizada en una tarea programada y no se puede eliminar.'
|
||||
ErrBackupCheck: 'Error al probar la conexión de la cuenta de respaldo {{ .err }}'
|
||||
ErrBackupLocalDelete: 'No se admite aún la eliminación de la cuenta de respaldo del servidor local'
|
||||
ErrBackupLocalCreate: 'No se admite aún la creación de cuentas de respaldo del servidor local'
|
||||
Localhost: "Máquina local"
|
||||
|
||||
#app
|
||||
ErrPortInUsed: '¡El puerto {{ .detail }} ya está ocupado!'
|
||||
Decrypt: 'Descifrar'
|
||||
ErrAgentAccountBound: 'Cuenta vinculada a agente'
|
||||
ErrAgentAccountUnavailable: 'Conexión de cuenta no disponible: {{ .err }}'
|
||||
ErrAgentProviderNotSupported: 'Proveedor de agente no soportado'
|
||||
ErrAgentAccountRequired: 'Elige una cuenta de agente primero'
|
||||
ErrAgentAccountNotVerified: 'Cuenta de agente no verificada'
|
||||
ErrAgentProviderMismatch: 'Proveedor de agente no coincide'
|
||||
ErrAgentBaseURLRequired: 'URL base requerida'
|
||||
ErrAgentApiKeyRequired: 'Clave API requerida'
|
||||
ErrAgentComposeRequired: 'Contenido compose requerido'
|
||||
ErrAgentIDRequired: 'ID de agente requerido'
|
||||
ErrAgentAccountIDRequired: 'ID de cuenta requerido'
|
||||
ErrAgentLimitReached: 'La edición Community admite hasta {{ .max }} agentes de IA. Actualice a la edición Professional para eliminar el límite'
|
||||
Localhost: 'Máquina local'
|
||||
ErrBackupInUsed: 'Cuenta de respaldo en uso por tarea programada'
|
||||
ErrBackupCheck: 'Conexión de respaldo falló: {{ .err }}'
|
||||
ErrBackupLocalDelete: 'No se puede eliminar cuentas de respaldo locales'
|
||||
ErrBackupLocalCreate: 'No se pueden crear cuentas de respaldo locales'
|
||||
ErrPortInUsed: 'El puerto {{ .detail }} ya está ocupado'
|
||||
ErrAppLimit: 'El número de aplicaciones instaladas ha superado el límite'
|
||||
ErrNotInstall: 'Aplicación no instalada'
|
||||
ErrPortInOtherApp: '¡El puerto {{ .port }} ya está ocupado por la aplicación {{ .apps }}!'
|
||||
ErrDbUserNotValid: '¡Base de datos existente, usuario y contraseña no coinciden!'
|
||||
ErrUpdateBuWebsite: 'La aplicación se actualizó correctamente, pero falló la modificación del archivo de configuración del sitio web. ¡Por favor revise la configuración!'
|
||||
Err1PanelNetworkFailed: '¡Fallo la creación de la red por defecto del contenedor! {{ .detail }}'
|
||||
ErrFileParse: '¡Fallo al analizar el archivo docker-compose de la aplicación!'
|
||||
ErrPortInOtherApp: 'El puerto {{ .port }} ya está ocupado por la aplicación {{ .apps }}'
|
||||
ErrDbUserNotValid: 'Base de datos existente, usuario y contraseña no coinciden'
|
||||
ErrUpdateBuWebsite: 'La aplicación se actualizó correctamente, pero falló la modificación del archivo de configuración del sitio web. revise la configuración'
|
||||
Err1PanelNetworkFailed: 'Fallo la creación de la red por defecto del contenedor {{ .detail }}'
|
||||
ErrFileParse: 'Fallo al analizar el archivo docker-compose de la aplicación'
|
||||
ErrInstallDirNotFound: 'El directorio de instalación no existe. Si desea desinstalar, seleccione Desinstalación forzada'
|
||||
AppStoreIsUpToDate: 'La tienda de aplicaciones ya está en la última versión'
|
||||
LocalAppVersionNull: '¡La aplicación {{ .name }} no está sincronizada a la versión! No se puede agregar a la lista de aplicaciones'
|
||||
LocalAppVersionErr: '¡La sincronización de la versión {{ .version }} de {{ .name }} falló! {{ .err }}'
|
||||
LocalAppVersionNull: 'La aplicación {{ .name }} no está sincronizada a la versión No se puede agregar a la lista de aplicaciones'
|
||||
LocalAppVersionErr: 'La sincronización de la versión {{ .version }} de {{ .name }} falló {{ .err }}'
|
||||
ErrFileNotFound: 'El archivo {{ .name }} no existe'
|
||||
ErrFileParseApp: '¡El archivo {{ .name }} falló al analizarse! {{ .err }}'
|
||||
ErrFileParseApp: 'El archivo {{ .name }} falló al analizarse {{ .err }}'
|
||||
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'
|
||||
ErrCreateHttpClient: 'Fallo al crear la solicitud {{ .err }}'
|
||||
ErrHttpReqTimeOut: 'La solicitud superó el tiempo de espera {{ .err }}'
|
||||
@@ -87,46 +79,42 @@ 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.'
|
||||
ErrAppNameExist: 'El nombre de la aplicación ya existe'
|
||||
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'
|
||||
ErrAppParamKey: 'El campo de parámetro {{ .name }} es anómalo'
|
||||
ErrAppUpgrade: 'La actualización de la aplicación {{ .name }} falló {{ .err }}'
|
||||
AppRecover: 'Revertir la aplicación {{ .name }}'
|
||||
PullImageStart: 'Iniciar descarga de la imagen [{{ .name }}]'
|
||||
PullImageSuccess: 'Descarga de imagen exitosa'
|
||||
AppStoreIsLastVersion: 'La tienda de aplicaciones ya está en la última versión'
|
||||
AppStoreSyncSuccess: 'Sincronización de la tienda de aplicaciones exitosa'
|
||||
SyncAppDetail: 'Sincronizar configuración de la aplicación'
|
||||
AppVersionNotMatch: 'La aplicación {{ .name }} requiere una versión superior de 1Panel, se omite la sincronización'
|
||||
MoveSiteDir: 'La actualización actual requiere migrar el directorio del sitio web OpenResty'
|
||||
MoveSiteDirSuccess: 'Migración del directorio del sitio exitosa'
|
||||
DeleteRuntimePHP: 'Eliminar entorno de ejecución PHP'
|
||||
CustomAppStoreFileValid: 'Los paquetes de la tienda de aplicaciones deben estar en formato .tar.gz'
|
||||
CustomAppStoreFileValid: 'Los paquetes de la tienda de aplicaciones deben estar en formato.tar.gz'
|
||||
PullImageTimeout: 'Tiempo de espera al descargar la imagen, intente aumentar la aceleración o use otra'
|
||||
ErrAppIsDown: 'El estado de la aplicación {{ .name }} es anómalo, revise'
|
||||
ErrCustomApps: 'Hay una aplicación instalada, desinstálela primero'
|
||||
ErrCustomRuntimes: 'Hay un entorno de ejecución instalado, elimínelo primero'
|
||||
ErrAppVersionDeprecated: "La aplicación {{ .name }} no es compatible con la versión actual de 1Panel, omitida"
|
||||
ErrDockerFailed: "El estado de Docker es anómalo, revise el servicio"
|
||||
ErrDockerComposeCmdNotFound: "El comando Docker Compose no existe, por favor instálelo primero en el host"
|
||||
UseExistImage: 'Error al extraer la imagen, usando imagen existente'
|
||||
|
||||
#ssh
|
||||
ExportIP: "IP de inicio de sesión"
|
||||
ExportArea: "Ubicación"
|
||||
ExportPort: "Puerto"
|
||||
ExportAuthMode: "Método de inicio de sesión"
|
||||
ExportUser: "Usuario"
|
||||
ExportStatus: "Estado de inicio de sesión"
|
||||
ExportDate: "Fecha y hora"
|
||||
|
||||
#file
|
||||
ErrAppVersionDeprecated: 'La aplicación {{ .name }} no es compatible con la versión actual de 1Panel, omitida'
|
||||
ErrDockerFailed: 'El estado de Docker es anómalo, revise el servicio'
|
||||
ErrDockerComposeCmdNotFound: 'El comando Docker Compose no existe instálelo primero en el host'
|
||||
UseExistImage: 'La imagen ya existe, usando imagen existente'
|
||||
ErrDatabaseNotFound: 'La base de datos {{ .name }} no existe'
|
||||
ExportIP: 'IP de inicio de sesión'
|
||||
ExportArea: 'Ubicación'
|
||||
ExportPort: 'Puerto'
|
||||
ExportAuthMode: 'Método de inicio de sesión'
|
||||
ExportUser: 'Usuario'
|
||||
ExportStatus: 'Estado de inicio de sesión'
|
||||
ExportDate: 'Fecha y hora'
|
||||
ErrFileCanNotRead: 'Este archivo no soporta vista previa'
|
||||
ErrFileToLarge: 'El archivo es mayor a 10M y no puede abrirse'
|
||||
ErrPathNotFound: 'El directorio no existe'
|
||||
ErrMovePathFailed: '¡La ruta de destino no puede contener la ruta original!'
|
||||
ErrLinkPathNotFound: '¡La ruta de destino no existe!'
|
||||
ErrFileIsExist: '¡El archivo o carpeta ya existe!'
|
||||
ErrMovePathFailed: 'La ruta de destino no puede contener la ruta original'
|
||||
ErrLinkPathNotFound: 'La ruta de destino no existe'
|
||||
ErrFileIsExist: 'El archivo o carpeta ya existe'
|
||||
ErrFileUpload: '{{ .name }} falló al subir archivo {{ .detail }}'
|
||||
ErrFileDownloadDir: 'No se admite la descarga de carpetas'
|
||||
ErrCmdNotFound: 'El comando {{ .name }} no existe, instálelo primero en el host'
|
||||
@@ -134,16 +122,15 @@ ErrSourcePathNotFound: 'El directorio fuente no existe'
|
||||
ErrFavoriteExist: 'Esta ruta ya ha sido marcada como favorita'
|
||||
ErrInvalidChar: 'No se permiten caracteres ilegales'
|
||||
ErrPathNotDelete: 'No se puede eliminar el directorio seleccionado'
|
||||
FileDropFailed: "Error al limpiar el archivo {{ .name }}: {{ .err }}"
|
||||
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"
|
||||
ErrBadDecrypt: "Error de contraseña de descifrado del paquete comprimido, descompresión fallida, ¡compruebe e inténtelo de nuevo!"
|
||||
|
||||
#website
|
||||
ErrLogFileToLarge: 'Log file exceeds 500 MB'
|
||||
FileDropFailed: 'Error al limpiar el archivo {{ .name }}: {{ .err }}'
|
||||
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'
|
||||
ErrBadDecrypt: 'Error de contraseña de descifrado del paquete comprimido, descompresión fallida, compruebe e inténtelo de nuevo'
|
||||
ErrAliasIsExist: 'El alias ya existe'
|
||||
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 }}'
|
||||
ErrPHPResource: '¡El entorno local no soporta cambio!'
|
||||
ErrPHPResource: 'El entorno local no soporta cambio'
|
||||
ErrPathPermission: 'Se detectó una carpeta con permisos distintos a 1000:1000 en el directorio index, lo cual puede causar errores de acceso denegado. Haga clic en Guardar arriba'
|
||||
ErrDomainIsUsed: 'El dominio ya está en uso por el sitio web [{{ .name }}]'
|
||||
ErrDomainFormat: 'El formato del dominio {{ .name }} es incorrecto'
|
||||
@@ -151,11 +138,11 @@ ErrDefaultAlias: 'default es un código reservado, use otro'
|
||||
ErrParentWebsite: 'Primero debe eliminar el sub-sitio {{ .name }}'
|
||||
ErrBuildDirNotFound: 'El directorio de compilación no existe'
|
||||
ErrImageNotExist: 'La imagen del entorno {{ .name }} no existe, edítela de nuevo'
|
||||
ErrProxyIsUsed: "El balanceo de carga ya está usado por un proxy reverso, no se puede eliminar"
|
||||
ErrSSLValid: 'Archivo de certificado anómalo, ¡revise el estado del certificado!'
|
||||
ErrWebsiteDir: "Por favor seleccione un directorio dentro del directorio del sitio web"
|
||||
ErrComposerFileNotFound: "El archivo composer.json no existe"
|
||||
ErrRuntimeNoPort: "El entorno de ejecución no tiene configurado un puerto, edítelo primero"
|
||||
ErrProxyIsUsed: 'El balanceo de carga ya está usado por un proxy reverso, no se puede eliminar'
|
||||
ErrSSLValid: 'Archivo de certificado anómalo, revise el estado del certificado'
|
||||
ErrWebsiteDir: 'seleccione un directorio dentro del directorio del sitio web'
|
||||
ErrComposerFileNotFound: 'El archivo composer.json no existe'
|
||||
ErrRuntimeNoPort: 'El entorno de ejecución no tiene configurado un puerto, edítelo primero'
|
||||
Status: 'Estado'
|
||||
start: 'Iniciar'
|
||||
stop: 'Detener'
|
||||
@@ -165,14 +152,12 @@ pause: 'Pausar'
|
||||
unpause: 'Reanudar'
|
||||
remove: 'Eliminar'
|
||||
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'
|
||||
Set: 'Configuración'
|
||||
|
||||
#ssl
|
||||
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'
|
||||
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'
|
||||
ErrEmailIsExist: 'El correo ya existe'
|
||||
ErrSSLKeyNotFound: 'El archivo de clave privada no existe'
|
||||
ErrSSLCertificateNotFound: 'El archivo de certificado no existe'
|
||||
@@ -185,9 +170,10 @@ dnsAccount: 'DNS Automático'
|
||||
dnsManual: 'DNS Manual'
|
||||
http: 'HTTP'
|
||||
ApplySSLFailed: 'Solicitud de certificado para [{{ .domain }}] fallida, {{ .detail }}'
|
||||
ApplySSLSuccess: '¡Solicitud de certificado para [{{ .domain }}] exitosa!'
|
||||
ApplySSLSuccess: 'Solicitud de certificado para [{{ .domain }}] exitosa'
|
||||
DNSAccountName: 'Cuenta DNS [{{ .name }}] proveedor [{{ .type }}]'
|
||||
PushDirLog: 'Certificado empujado al directorio [{{ .path }}] {{ .status }}'
|
||||
ErrDeleteCAWithSSL: 'La organización actual tiene un certificado emitido y no puede eliminarse.'
|
||||
ErrDeleteWithPanelSSL: 'La configuración SSL del panel utiliza este certificado y no puede eliminarse'
|
||||
ErrDefaultCA: 'La autoridad por defecto no puede eliminarse'
|
||||
ApplyWebSiteSSLLog: 'Iniciando renovación del certificado del sitio web {{ .name }}'
|
||||
@@ -199,98 +185,79 @@ ExecShellSuccess: 'Ejecución de script exitosa'
|
||||
StartUpdateSystemSSL: 'Iniciando actualización del certificado del sistema'
|
||||
UpdateSystemSSLSuccess: 'Certificado del sistema actualizado correctamente'
|
||||
ErrWildcardDomain: 'No se puede solicitar certificado de dominio wildcard en modo HTTP'
|
||||
ErrDeleteCAWithSSL: "La organización actual tiene un certificado emitido y no puede eliminarse."
|
||||
ErrApplySSLCanNotDelete: "El certificado {{ .name }} en proceso de solicitud no puede eliminarse, inténtelo más tarde"
|
||||
StartPushSSLToNode: "Iniciando envío de certificado al nodo"
|
||||
PushSSLToNodeFailed: "Error al enviar el certificado al nodo: {{ .err }}"
|
||||
PushSSLToNodeSuccess: "Certificado enviado correctamente al nodo"
|
||||
|
||||
#mysql
|
||||
ErrApplySSLCanNotDelete: 'El certificado {{ .name }} en proceso de solicitud no puede eliminarse, inténtelo más tarde'
|
||||
StartPushSSLToNode: 'Iniciando envío de certificado al nodo'
|
||||
PushSSLToNodeFailed: 'Error al enviar el certificado al nodo: {{ .err }}'
|
||||
PushSSLToNodeSuccess: 'Certificado enviado correctamente al nodo'
|
||||
ErrUserIsExist: 'El usuario actual ya existe, intente con otro'
|
||||
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'
|
||||
ErrRemoteExist: 'La base de datos remota ya existe con ese nombre, modifíquelo e intente de nuevo'
|
||||
ErrLocalExist: 'El nombre ya existe en la base de datos local, modifíquelo e intente de nuevo'
|
||||
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 por favor..."
|
||||
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 por favor..."
|
||||
Arg: "Argumento"
|
||||
|
||||
#redis
|
||||
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...'
|
||||
Arg: 'Argumento'
|
||||
ErrTypeOfRedis: 'El tipo de archivo de recuperación no coincide con el método de persistencia actual, modifíquelo e intente'
|
||||
|
||||
#container
|
||||
ErrInUsed: "{{ .detail }} 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!"
|
||||
ErrInUsed: '{{ .detail }} 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'
|
||||
ErrPortRules: 'El número de puerto no coincide, ingrese de nuevo'
|
||||
ErrPgImagePull: 'Tiempo de espera al descargar la imagen, configure la aceleración o descárguela manualmente ({{ .name }}) e intente de nuevo'
|
||||
PruneHelper: "Esta limpieza {{ .name }} liberó espacio en disco {{ .size }}"
|
||||
ImageRemoveHelper: "Imagen {{ .name }} eliminada, liberando {{ .size }} de espacio en disco"
|
||||
BuildCache: "Caché de compilación"
|
||||
Volume: "Volumen de almacenamiento"
|
||||
Network: "Red"
|
||||
PruneStart: "Limpiando en progreso, por favor espere..."
|
||||
|
||||
#runtime
|
||||
ErrFileNotExist: 'El archivo {{ .detail }} no existe, ¡verifique la integridad!'
|
||||
PruneHelper: 'Esta limpieza {{ .name }} liberó espacio en disco {{ .size }}'
|
||||
ImageRemoveHelper: 'Imagen {{ .name }} eliminada, liberando {{ .size }} de espacio en disco'
|
||||
BuildCache: 'Caché de compilación'
|
||||
Volume: 'Volumen de almacenamiento'
|
||||
Network: 'Red'
|
||||
PruneStart: 'Limpiando en progreso espere...'
|
||||
ErrFileNotExist: 'El archivo {{ .detail }} no existe, verifique la integridad'
|
||||
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.'
|
||||
ErrDelWithWebsite: 'El entorno de ejecución ya está asociado a un sitio web y no puede eliminarse'
|
||||
ErrRuntimeStart: 'Fallo al iniciar'
|
||||
ErrPackageJsonNotFound: 'El archivo package.json no existe'
|
||||
ErrScriptsNotFound: 'No se encontró la configuración de scripts en package.json'
|
||||
ErrContainerNameNotFound: 'No se puede obtener el nombre del contenedor, revise el archivo .env'
|
||||
ErrContainerNameNotFound: 'No se puede obtener el nombre del contenedor, revise el archivo.env'
|
||||
ErrNodeModulesNotFound: 'La carpeta node_modules no existe, edite o espere a que inicie'
|
||||
ErrContainerNameIsNull: 'El nombre del contenedor no existe'
|
||||
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"
|
||||
|
||||
#tool
|
||||
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'
|
||||
ErrConfigNotFound: 'El archivo de configuración no existe'
|
||||
ErrConfigParse: 'El formato del archivo de configuración es incorrecto'
|
||||
ErrConfigIsNull: 'El archivo de configuración no puede estar vacío'
|
||||
ErrConfigDirNotFound: 'El directorio de ejecución no existe'
|
||||
ErrConfigAlreadyExist: 'Ya existe un archivo de configuración con ese nombre'
|
||||
ErrUserFindErr: 'Búsqueda del usuario {{ .name }} fallida {{ .err }}'
|
||||
|
||||
#cronjob
|
||||
CutWebsiteLogSuccess: 'Log del sitio web {{ .name }} cortado con éxito, ruta de respaldo {{ .path }}'
|
||||
HandleShell: 'Ejecutar script {{ .name }}'
|
||||
HandleCurl: "URL {{ .name }} にアクセス"
|
||||
HandleCurl: 'URL {{ .name }} にアクセス'
|
||||
HandleNtpSync: 'Sincronizar hora del sistema'
|
||||
HandleSystemClean: 'Limpiar caché del sistema'
|
||||
SystemLog: 'Log del sistema'
|
||||
CutWebsiteLog: 'Rotar log del sitio web'
|
||||
FileOrDir: 'Directorio / Archivo'
|
||||
UploadFile: 'Subiendo archivo de respaldo {{ .file }} a {{ .backup }}'
|
||||
Upload: 'Subir'
|
||||
IgnoreBackupErr: 'Fallo en el respaldo, error: {{ .detail }}, se ignora este error...'
|
||||
IgnoreUploadErr: 'Fallo en la subida, error: {{ .detail }}, se ignora este error...'
|
||||
Upload: "Subir"
|
||||
LoadBackupFailed: "Error al obtener la conexión de la cuenta de respaldo, error: {{ .detail }}"
|
||||
InExecuting: "La tarea actual se está ejecutando, por favor no la repita"
|
||||
NoSuchResource: "No se encontraron contenidos de respaldo en la base de datos, omitiendo..."
|
||||
CleanLog: "Limpiar registro"
|
||||
CleanLogByName: "Limpiar registro de {{.name}}"
|
||||
WafIpGroupNotFound: "Grupo de IP de WAF no encontrado. Por favor, vaya a [Funciones Avanzadas - WAF - Lista Blanca/Negra - Grupo de IP] para agregar un grupo de IP mediante el método de descarga remota."
|
||||
|
||||
#toolbox
|
||||
LoadBackupFailed: 'Error al obtener la conexión de la cuenta de respaldo, error: {{ .detail }}'
|
||||
InExecuting: 'La tarea actual se está ejecutando no la repita'
|
||||
NoSuchResource: 'No se encontraron contenidos de respaldo en la base de datos, omitiendo...'
|
||||
CleanLog: 'Limpiar registro'
|
||||
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.'
|
||||
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'
|
||||
ErrClamdscanNotFound: 'El comando clamdscan no fue detectado, siga la documentación para instalarlo'
|
||||
TaskSwapSet: "Configurar Swap"
|
||||
SetSwap: "Configurar Swap {{ .path }} - {{ .size }}"
|
||||
CreateSwap: "Crear Archivo Swap"
|
||||
FormatSwap: "Formatear Archivo Swap"
|
||||
EnableSwap: "Habilitar Swap"
|
||||
|
||||
#tamper
|
||||
CleanTamperSetting: "Limpiar configuraciones de protección históricas"
|
||||
SetTamperWithRules: "Iniciar protección de directorio según reglas"
|
||||
ProtectDir: "Proteger directorio {{ .name }}"
|
||||
IgnoreFile: "Proteger archivo {{ .name }}"
|
||||
TamperSetSuccessful: "Configuración de protección completada, comenzando monitoreo de los siguientes directorios:"
|
||||
|
||||
#waf
|
||||
TaskSwapSet: 'Configurar Swap'
|
||||
SetSwap: 'Configurar Swap {{ .path }} - {{ .size }}'
|
||||
CreateSwap: 'Crear Archivo Swap'
|
||||
FormatSwap: 'Formatear Archivo Swap'
|
||||
EnableSwap: 'Habilitar Swap'
|
||||
CleanTamperSetting: 'Limpiar configuraciones de protección históricas'
|
||||
SetTamperWithRules: 'Iniciar protección de directorio según reglas'
|
||||
ProtectDir: 'Proteger directorio {{ .name }}'
|
||||
IgnoreFile: 'Proteger archivo {{ .name }}'
|
||||
TamperSetSuccessful: 'Configuración de protección completada, comenzando monitoreo de los siguientes directorios:'
|
||||
ErrScope: 'No se admite la modificación de esta configuración'
|
||||
ErrStateChange: 'Fallo al cambiar de estado'
|
||||
ErrRuleExist: 'La regla ya existe'
|
||||
@@ -298,7 +265,7 @@ ErrRuleNotExist: 'La regla no existe'
|
||||
ErrParseIP: 'Formato de IP incorrecto'
|
||||
ErrDefaultIP: 'default es un nombre reservado, cámbielo'
|
||||
ErrGroupInUse: 'El grupo IP está en uso por listas negras/blancas y no se puede eliminar'
|
||||
ErrIPGroupAclUse: "El grupo IP está en uso por reglas personalizadas del sitio web {{ .name }}, no puede eliminarse"
|
||||
ErrIPGroupAclUse: 'El grupo IP está en uso por reglas personalizadas del sitio web {{ .name }}, no puede eliminarse'
|
||||
ErrGroupExist: 'El nombre del grupo IP ya existe'
|
||||
ErrIPRange: 'Rango de IP incorrecto'
|
||||
ErrIPExist: 'La IP ya existe'
|
||||
@@ -309,10 +276,10 @@ xss: 'XSS'
|
||||
phpExec: 'Ejecución de scripts PHP'
|
||||
oneWordTrojan: 'Troyano de una sola palabra'
|
||||
appFilter: 'Filtrar directorios peligrosos'
|
||||
webshell: 'Webshell'
|
||||
webShell: 'Webshell'
|
||||
args: 'Reglas de parámetros'
|
||||
protocolFilter: 'Filtrado de protocolos'
|
||||
javaFileter: 'Filtrado de archivos Java peligrosos'
|
||||
javaFilter: 'Filtrado de archivos Java peligrosos'
|
||||
scannerFilter: 'Filtrado de escáneres'
|
||||
escapeFilter: 'Filtro de escape'
|
||||
customRule: 'Regla personalizada'
|
||||
@@ -342,10 +309,9 @@ ErrDBNotExist: 'La base de datos no existe'
|
||||
allow: 'permitir'
|
||||
deny: 'denegar'
|
||||
OpenrestyNotFound: 'Openresty no está instalado'
|
||||
remoteIpIsNull: "La lista de IP está vacía"
|
||||
OpenrestyVersionErr: "La versión de Openresty es demasiado baja, actualice a 1.27.1.2-2-2-focal"
|
||||
|
||||
#task
|
||||
remoteIpIsNull: 'La lista de IP está vacía'
|
||||
OpenrestyVersionErr: 'La versión de Openresty es demasiado baja, actualice a 1.27.1.2-2-2-focal'
|
||||
ErrFileTooLarge: 'El archivo supera 1 MB y no se puede cargar'
|
||||
TaskStart: 'La tarea {{ .name }} inicia [INICIO]'
|
||||
TaskEnd: 'La tarea {{ .name }} completada [COMPLETADA]'
|
||||
TaskFailed: 'La tarea {{ .name }} falló'
|
||||
@@ -357,11 +323,11 @@ SubTaskFailed: '{{ .name }} falló: {{ .err }}'
|
||||
TaskInstall: 'Instalar'
|
||||
TaskUninstall: 'Desinstalar'
|
||||
TaskCreate: 'Crear'
|
||||
TaskProtect: "Proteger"
|
||||
TaskDelete: 'Eliminar'
|
||||
TaskUpgrade: 'Actualizar'
|
||||
TaskUpdate: 'Actualizar'
|
||||
TaskRestart: 'Reiniciar'
|
||||
TaskProtect: 'Proteger'
|
||||
TaskBackup: 'Respaldar'
|
||||
TaskRecover: 'Recuperar'
|
||||
TaskRollback: 'Revertir'
|
||||
@@ -369,9 +335,10 @@ TaskPull: 'Descargar'
|
||||
TaskCommit: 'Commit'
|
||||
TaskBuild: 'Construir'
|
||||
TaskPush: 'Subir'
|
||||
TaskClean: 'Limpieza'
|
||||
TaskHandle: 'Ejecutar'
|
||||
TaskImport: "Importar"
|
||||
TaskExport: "Exportar"
|
||||
TaskImport: 'Importar'
|
||||
TaskExport: 'Exportar'
|
||||
Website: 'Sitio web'
|
||||
App: 'Aplicación'
|
||||
Runtime: 'Entorno de ejecución'
|
||||
@@ -402,20 +369,13 @@ SubTask: 'Subtarea'
|
||||
RuntimeExtension: 'Extensión del entorno de ejecución'
|
||||
TaskIsExecuting: 'Tarea en ejecución'
|
||||
CustomAppstore: 'Almacén de aplicaciones personalizado'
|
||||
TaskClean: "Limpieza"
|
||||
TaskExec: "Ejecutar"
|
||||
TaskBatch: "Operación por Lotes"
|
||||
TaskExec: 'Ejecutar'
|
||||
TaskBatch: 'Operación por Lotes'
|
||||
FileConvert: 'Conversión de Formato de Archivo'
|
||||
|
||||
# task - ai
|
||||
Clamscan: 'Escanear {{ .name }}'
|
||||
TaskScan: 'Escaneo'
|
||||
OllamaModelPull: 'Descargar modelo Ollama {{ .name }}'
|
||||
OllamaModelSize: 'Obtener tamaño del modelo Ollama {{ .name }}'
|
||||
|
||||
# task - clam
|
||||
Clamscan: "Escanear {{ .name }}"
|
||||
TaskScan: "Escaneo"
|
||||
|
||||
# task-snapshot
|
||||
Snapshot: 'Instantánea'
|
||||
SnapDBInfo: 'Escribir información de base de datos de 1Panel'
|
||||
SnapCopy: 'Copiar archivos y directorios {{ .name }}'
|
||||
@@ -440,7 +400,7 @@ SnapCheckCompress: 'Verificar archivo de compresión de instantánea'
|
||||
SnapCompressSize: 'Tamaño del archivo de instantánea {{ .name }}'
|
||||
SnapUpload: 'Subir archivo de instantánea'
|
||||
SnapUploadTo: 'Subir archivo de instantánea a {{ .name }}'
|
||||
|
||||
SnapUploadRes: 'Subir archivo de instantánea a {{ .name }}'
|
||||
SnapshotRecover: 'Restaurar instantánea'
|
||||
RecoverDownload: 'Descargar archivo de instantánea'
|
||||
Download: 'Descargar'
|
||||
@@ -448,10 +408,10 @@ RecoverDownloadAccount: 'Obtener cuenta de respaldo para descargar instantánea
|
||||
RecoverDecompress: 'Descomprimir archivos de instantánea'
|
||||
Decompress: 'Descompresión'
|
||||
BackupBeforeRecover: 'Respaldar datos del sistema antes de restaurar instantánea'
|
||||
Readjson: 'Leer archivo Json de la instantánea'
|
||||
ReadjsonPath: 'Obtener ruta del archivo Json en la instantánea'
|
||||
ReadjsonContent: 'Leer archivo Json'
|
||||
ReadjsonMarshal: 'Procesar escape de Json'
|
||||
ReadJson: 'Leer archivo Json de la instantánea'
|
||||
ReadJsonPath: 'Obtener ruta del archivo Json en la instantánea'
|
||||
ReadJsonContent: 'Leer archivo Json'
|
||||
ReadJsonMarshal: 'Procesar escape de Json'
|
||||
RecoverApp: 'Restaurar aplicaciones instaladas'
|
||||
RecoverWebsite: 'Recuperar directorio del sitio web'
|
||||
RecoverAppImage: 'Restaurar imagen de la instantánea'
|
||||
@@ -465,9 +425,6 @@ RecoverDaemonJson: 'Restaurar archivo daemon.json de configuración de contenedo
|
||||
RecoverDBData: 'Restaurar datos de base de datos'
|
||||
RecoverBackups: 'Restaurar directorio local de respaldo'
|
||||
RecoverPanelData: 'Recuperar directorio de datos'
|
||||
|
||||
# task - container
|
||||
ContainerNewCliet: 'Inicializar cliente Docker'
|
||||
ContainerImagePull: 'Descargar imagen de contenedor {{ .name }}'
|
||||
ContainerRemoveOld: 'Eliminar el contenedor original {{ .name }}'
|
||||
ContainerImageCheck: 'Comprobar si la imagen se descargó correctamente'
|
||||
@@ -476,22 +433,13 @@ ContainerRecreate: 'Actualización del contenedor fallida, restaurando el conten
|
||||
ContainerCreate: 'Crear nuevo contenedor {{ .name }}'
|
||||
ContainerCreateFailed: 'Falló la creación del contenedor, eliminando el contenedor fallido'
|
||||
ContainerStartCheck: 'Verificar si el contenedor ha iniciado'
|
||||
|
||||
# task - image
|
||||
ImageBuild: 'Construcción de imagen'
|
||||
ImageBuildStdoutCheck: 'Analizar salida de la imagen'
|
||||
ImageBuildRes: 'Salida de construcción de imagen: {{ .name }}'
|
||||
ImagePull: 'Descargar imagen'
|
||||
ImageRepoAuthFromDB: 'Obtener información de autenticación del repositorio desde la base de datos'
|
||||
ImagePush: 'Subir imagen'
|
||||
ImageRenameTag: 'Modificar etiqueta de imagen'
|
||||
ImageNewTag: 'Nueva etiqueta de imagen {{ .name }}'
|
||||
ComposeCreate: 'Crear orquestación'
|
||||
ComposeCreateRes: 'Salida de creación de orquestación: {{ .name }}'
|
||||
ImageRepoAuthFromDB: "Obtener información de autenticación del repositorio desde la base de datos"
|
||||
ImaegPullRes: "Salida de descarga de imagen: {{ .name }}"
|
||||
ImaegPushRes: "Salida de subida de imagen: {{ .name }}"
|
||||
|
||||
# task - website
|
||||
BackupNginxConfig: 'Respaldar archivo de configuración OpenResty'
|
||||
CompressFileSuccess: 'Directorio comprimido con éxito, guardado en {{ .name }}'
|
||||
CompressDir: 'Directorio comprimido'
|
||||
@@ -502,40 +450,27 @@ websiteDir: 'Directorio del sitio web'
|
||||
RecoverFailedStartRollBack: 'Restauración fallida, iniciando reversión'
|
||||
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'
|
||||
|
||||
#alert
|
||||
ErrAlert: 'El formato del mensaje de alerta es incorrecto, ¡revise e intente de nuevo!'
|
||||
ErrAlertPush: 'Error al enviar la alerta, ¡revise e intente de nuevo!'
|
||||
ErrAlertSave: 'Error al guardar la alerta, ¡revise e intente de nuevo!'
|
||||
ErrAlertSync: 'Error en la sincronización de la alerta, ¡revise e intente de nuevo!'
|
||||
ErrAlertRemote: 'Error remoto de alerta, ¡revise e intente de nuevo!'
|
||||
|
||||
#task - runtime
|
||||
ErrInstallExtension: "Ya hay una tarea de instalación en curso, espere a que termine"
|
||||
|
||||
# alert mail template
|
||||
PanelAlertTitle: "Notificación de alerta del panel"
|
||||
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."
|
||||
LicenseExpirationAlert: "Su Panel {{ .node }}{{ .ip }}, la licencia expirará en {{ .day }} días. Inicie sesión en el panel para ver los detalles."
|
||||
CronJobFailedAlert: "Su Panel {{ .node }}{{ .ip }}, la ejecución de la tarea programada {{ .name }} falló. Inicie sesión en el panel para ver los detalles."
|
||||
ClamAlert: "Su Panel {{ .node }}{{ .ip }}, la tarea de escaneo antivirus detectó {{ .num }} archivos infectados. Inicie sesión en el panel para ver los detalles."
|
||||
WebSiteAlert: "Su Panel {{ .node }}{{ .ip }}, {{ .num }} sitios web expirarán en {{ .day }} días. Inicie sesión en el panel para ver los detalles."
|
||||
SSLAlert: "Su Panel {{ .node }}{{ .ip }}, {{ .num }} certificados SSL expirarán en {{ .day }} días. Inicie sesión en el panel para ver los detalles."
|
||||
DiskUsedAlert: "Su Panel {{ .node }}{{ .ip }}, el uso del disco {{ .name }} ha alcanzado {{ .used }}. Inicie sesión en el panel para ver los detalles."
|
||||
ResourceAlert: "Su Panel {{ .node }}{{ .ip }}, la tasa de uso promedio de {{ .name }} en {{ .time }} minutos es {{ .used }}. Inicie sesión en el panel para ver los detalles."
|
||||
PanelVersionAlert: "Su Panel {{ .node }}{{ .ip }}, está disponible la última versión del panel para actualizar. Inicie sesión en el panel para ver los detalles."
|
||||
PanelPwdExpirationAlert: "Su Panel {{ .node }}{{ .ip }}, la contraseña del panel expirará en {{ .day }} días. Inicie sesión en el panel para ver los detalles."
|
||||
CommonAlert: "Su Panel {{ .node }}{{ .ip }}, {{ .msg }}. 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."
|
||||
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."
|
||||
|
||||
#disk
|
||||
DeviceNotFound: "Dispositivo {{ .name }} no encontrado"
|
||||
DeviceIsMounted: "El dispositivo {{ .name }} está montado, desmóntelo primero"
|
||||
PartitionDiskErr: "Error al particionar, {{ .err }}"
|
||||
FormatDiskErr: "Error al formatear disco, {{ .err }}"
|
||||
MountDiskErr: "Error al montar disco, {{ .err }}"
|
||||
UnMountDiskErr: "Error al desmontar disco, {{ .err }}"
|
||||
XfsNotFound: "No se detectó el sistema de archivos xfs, por favor instale xfsprogs primero"
|
||||
ErrAlertSync: 'Error en la sincronización de la alerta, revise e intente de nuevo'
|
||||
ErrInstallExtension: 'Ya hay una tarea de instalación en curso, espere a que termine'
|
||||
PanelAlertTitle: 'Notificación de alerta del panel'
|
||||
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.'
|
||||
LicenseExpirationAlert: 'Su Panel {{ .node }}{{ .ip }}, la licencia expirará en {{ .day }} días. Inicie sesión en el panel para ver los detalles.'
|
||||
CronJobFailedAlert: 'Su Panel {{ .node }}{{ .ip }}, la ejecución de la tarea programada {{ .name }} falló. Inicie sesión en el panel para ver los detalles.'
|
||||
ClamAlert: 'Su Panel {{ .node }}{{ .ip }}, la tarea de escaneo antivirus detectó {{ .num }} archivos infectados. Inicie sesión en el panel para ver los detalles.'
|
||||
WebSiteAlert: 'Su Panel {{ .node }}{{ .ip }}, {{ .num }} sitios web expirarán en {{ .day }} días. Inicie sesión en el panel para ver los detalles.'
|
||||
SSLAlert: 'Su Panel {{ .node }}{{ .ip }}, {{ .num }} certificados SSL expirarán en {{ .day }} días. Inicie sesión en el panel para ver los detalles.'
|
||||
DiskUsedAlert: 'Su Panel {{ .node }}{{ .ip }}, el uso del disco {{ .name }} ha alcanzado {{ .used }}. Inicie sesión en el panel para ver los detalles.'
|
||||
ResourceAlert: 'Su Panel {{ .node }}{{ .ip }}, la tasa de uso promedio de {{ .name }} en {{ .time }} minutos es {{ .used }}. Inicie sesión en el panel para ver los detalles.'
|
||||
PanelVersionAlert: 'Su Panel {{ .node }}{{ .ip }}, está disponible la última versión del panel para actualizar. Inicie sesión en el panel para ver los detalles.'
|
||||
PanelPwdExpirationAlert: 'Su Panel {{ .node }}{{ .ip }}, la contraseña del panel expirará en {{ .day }} días. Inicie sesión en el panel para ver los detalles.'
|
||||
CommonAlert: 'Su Panel {{ .node }}{{ .ip }}, {{ .msg }}. 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.'
|
||||
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.'
|
||||
DeviceNotFound: 'Dispositivo {{ .name }} no encontrado'
|
||||
DeviceIsMounted: 'El dispositivo {{ .name }} está montado, desmóntelo primero'
|
||||
PartitionDiskErr: 'Error al particionar, {{ .err }}'
|
||||
FormatDiskErr: 'Error al formatear disco, {{ .err }}'
|
||||
MountDiskErr: 'Error al montar disco, {{ .err }}'
|
||||
XfsNotFound: 'No se detectó el sistema de archivos xfs instale xfsprogs primero'
|
||||
|
||||
+161
-227
@@ -1,30 +1,28 @@
|
||||
ErrInvalidParams: 'リクエストパラメータエラー: {{ .detail }}'
|
||||
ErrTokenParse: 'トークン生成エラー: {{ .detail }}'
|
||||
ErrInitialPassword: '元のパスワードが正しくありません'
|
||||
ErrInternalServer: '内部サーバーエラー: {{ .detail }}'
|
||||
ErrRecordExist: 'レコードがすでに存在します'
|
||||
ErrInvalidParams: '不正なリクエスト: {{ .detail }}'
|
||||
ErrTokenParse: 'トークンエラー: {{ .detail }}'
|
||||
ErrInitialPassword: '元のパスワードが違います'
|
||||
ErrInternalServer: '内部エラー: {{ .detail }}'
|
||||
ErrRecordExist: 'レコードが既に存在します'
|
||||
ErrRecordNotFound: 'レコードが見つかりません'
|
||||
ErrStructTransform: '型変換に失敗しました: {{ .err }}'
|
||||
ErrNotLogin: 'ユーザーがログインしていません: {{ .detail }}'
|
||||
ErrPasswordExpired: '現在のパスワードの有効期限が切れています: {{ .detail }}'
|
||||
ErrNotSupportType: 'システムは現在のタイプ: {{ .name }} をサポートしていません'
|
||||
ErrProxy: 'リクエスト エラーです。ノードのステータスを確認してください: {{ .detail }}'
|
||||
ErrApiConfigStatusInvalid: 'API インターフェースへのアクセスは禁止されています: {{ .detail }}'
|
||||
ErrApiConfigKeyInvalid: 'API インターフェース キー エラー: {{ .detail }}'
|
||||
ErrApiConfigIPInvalid: 'API インターフェースの呼び出しに使用された IP がホワイトリストにありません: {{ .detail }}'
|
||||
ErrApiConfigDisable: 'このインターフェースは、API インターフェース呼び出しの使用を禁止しています: {{ .detail }}'
|
||||
ErrApiConfigKeyTimeInvalid: 'API インターフェースのタイムスタンプ エラー: {{ .detail }}'
|
||||
|
||||
ErrMinQuickJump: "少なくとも1つのクイックジャンプエントリを設定してください!"
|
||||
ErrMaxQuickJump: "最大4つのクイックジャンプエントリを設定できます!"
|
||||
|
||||
#common
|
||||
ErrUsernameIsExist: 'ユーザー名は既に存在します'
|
||||
ErrNameIsExist: '名前は既に存在します'
|
||||
ErrDemoEnvironment: 'デモ サーバー、この操作は禁止されています!'
|
||||
ErrCmdTimeout: 'コマンドの実行がタイムアウトしました!'
|
||||
ErrCmdIllegal: '実行コマンドに不正な文字が含まれています。修正してもう一度お試しください。'
|
||||
ErrPortExist: '{{ .port }} ポートは、{{ .type }} [{{ .name }}] によって既に使用されています'
|
||||
ErrStructTransform: '型変換エラー: {{ .err }}'
|
||||
ErrNotLogin: 'ログインしていません: {{ .detail }}'
|
||||
ErrPasswordExpired: 'パスワード期限切れ: {{ .detail }}'
|
||||
ErrNotSupportType: '未対応のタイプ: {{ .name }}'
|
||||
ErrProxy: 'リクエストに失敗しました: {{ .detail }}'
|
||||
ErrApiConfigStatusInvalid: 'API利用不可: {{ .detail }}'
|
||||
ErrApiConfigKeyInvalid: 'APIキーが無効です: {{ .detail }}'
|
||||
ErrApiConfigIPInvalid: 'IPが許可されていません: {{ .detail }}'
|
||||
ErrApiConfigDisable: 'APIは無効です: {{ .detail }}'
|
||||
ErrApiConfigKeyTimeInvalid: 'タイムスタンプが無効です: {{ .detail }}'
|
||||
ErrShutDown: 'コマンドは手動で停止されました'
|
||||
ErrMinQuickJump: 'クイックアクセスを1件以上追加'
|
||||
ErrMaxQuickJump: '最大4件のクイックアクセス'
|
||||
ErrUsernameIsExist: 'ユーザー名はすでに使われています'
|
||||
ErrNameIsExist: '名称はすでに使われています'
|
||||
ErrDemoEnvironment: 'デモ環境では利用できません'
|
||||
ErrCmdTimeout: 'コマンドがタイムアウトしました'
|
||||
ErrCmdIllegal: 'コマンドに無効な文字が含まれています'
|
||||
ErrPortExist: 'ポート {{ .port }} は {{ .type }} [{{ .name }}] が使用中です'
|
||||
TYPE_APP: 'アプリケーション'
|
||||
TYPE_RUNTIME: 'ランタイム環境'
|
||||
TYPE_DOMAIN: 'ドメイン名'
|
||||
@@ -35,45 +33,40 @@ Failed: '失敗'
|
||||
SystemRestart: 'システムの再起動によりタスクが中断されました'
|
||||
ErrGroupIsDefault: 'デフォルト グループ、削除できません'
|
||||
ErrGroupIsInWebsiteUse: 'グループは別の Web サイトで使用されているため、削除できません。'
|
||||
Decrypt: "復号化"
|
||||
|
||||
#agent
|
||||
ErrAgentAccountBound: 'このアカウントはエージェントに紐付いているため削除できません。確認して再試行してください!'
|
||||
ErrAgentAccountUnavailable: 'アカウント接続情報を利用できません。エラー: {{ .err }}。確認して再試行してください!'
|
||||
ErrAgentProviderNotSupported: 'このエージェント提供元はサポートされていません。確認して再試行してください!'
|
||||
ErrAgentAccountRequired: 'エージェントアカウントを選択して再試行してください。'
|
||||
ErrAgentAccountNotVerified: 'アカウントの検証が完了していません。確認して再試行してください!'
|
||||
ErrAgentProviderMismatch: 'アカウントの提供元が一致しません。確認して再試行してください!'
|
||||
ErrAgentBaseURLRequired: 'Base URL を空にできません。確認して再試行してください!'
|
||||
ErrAgentApiKeyRequired: 'API Key を空にできません。確認して再試行してください!'
|
||||
ErrAgentComposeRequired: 'カスタム compose 内容を空にできません。確認して再試行してください!'
|
||||
ErrAgentIDRequired: 'エージェント ID を空にできません。確認して再試行してください!'
|
||||
ErrAgentAccountIDRequired: 'アカウント ID を空にできません。確認して再試行してください!'
|
||||
|
||||
#backup
|
||||
Decrypt: '復号化'
|
||||
ErrAgentAccountBound: 'アカウントはエージェントに紐づいています'
|
||||
ErrAgentAccountUnavailable: 'アカウント接続不可: {{ .err }}'
|
||||
ErrAgentProviderNotSupported: 'エージェントプロバイダ非対応'
|
||||
ErrAgentAccountRequired: 'まずエージェントアカウントを選択'
|
||||
ErrAgentAccountNotVerified: 'アカウント未検証です'
|
||||
ErrAgentProviderMismatch: 'エージェントプロバイダが一致しません'
|
||||
ErrAgentBaseURLRequired: 'ベースURLが必要です'
|
||||
ErrAgentApiKeyRequired: 'APIキーが必要です'
|
||||
ErrAgentComposeRequired: 'Composeが必要です'
|
||||
ErrAgentIDRequired: 'エージェントIDが必要です'
|
||||
ErrAgentAccountIDRequired: 'アカウントIDが必要です'
|
||||
ErrAgentLimitReached: 'Community Edition では AI エージェントを最大 {{ .max }} 件まで作成できます。Professional Edition にアップグレードすると数の制限はありません'
|
||||
Localhost: 'ローカルマシン'
|
||||
ErrBackupInUsed: 'バックアップ アカウントはスケジュールされたタスクで使用されているため、削除できません。'
|
||||
ErrBackupCheck: 'バックアップ アカウントのテスト接続に失敗しました {{ .err }}'
|
||||
ErrBackupLocalDelete: 'ローカル サーバーのバックアップ アカウントの削除はまだサポートされていません'
|
||||
ErrBackupLocalCreate: 'ローカル サーバーのバックアップ アカウントの作成はまだサポートされていません'
|
||||
|
||||
#app
|
||||
ErrPortInUsed: '{{ .detail }} ポートはすでに使用されています!'
|
||||
ErrBackupInUsed: 'バックアップアカウントがスケジュールで使用中'
|
||||
ErrBackupCheck: '接続テストに失敗しました: {{ .err }}'
|
||||
ErrBackupLocalDelete: 'ローカルバックアップは削除できません'
|
||||
ErrBackupLocalCreate: 'ローカルバックアップは作成できません'
|
||||
ErrPortInUsed: '{{ .detail }} ポートはすでに使用されています'
|
||||
ErrAppLimit: 'インストールされているアプリケーションの数が制限を超えました'
|
||||
ErrNotInstall: 'アプリケーションがインストールされていません'
|
||||
ErrPortInOtherApp: '{{ .port }} ポートは既にアプリケーション {{ .apps }} によって使用されています!'
|
||||
ErrDbUserNotValid: '既存のデータベース、ユーザー名、およびパスワードが一致しません!'
|
||||
ErrUpdateBuWebsite: 'アプリケーションは正常に更新されましたが、Web サイト構成ファイルの変更に失敗しました。設定を確認してください! '
|
||||
ErrPortInOtherApp: '{{ .port }} ポートは既にアプリケーション {{ .apps }} によって使用されています'
|
||||
ErrDbUserNotValid: '既存のデータベース、ユーザー名、およびパスワードが一致しません'
|
||||
ErrUpdateBuWebsite: 'アプリケーションは正常に更新されましたが、Web サイト構成ファイルの変更に失敗しました。設定を確認してください'
|
||||
Err1PanelNetworkFailed: 'デフォルトのコンテナ ネットワークの作成に失敗しました。 {{ .detail }}'
|
||||
ErrFileParse: 'アプリケーションの docker-compose ファイルの解析に失敗しました!'
|
||||
ErrFileParse: 'アプリケーションの docker-compose ファイルの解析に失敗しました'
|
||||
ErrInstallDirNotFound: 'インストール ディレクトリが存在しません。アンインストールする必要がある場合は、強制アンインストールを選択してください。'
|
||||
AppStoreIsUpToDate: 'アプリストアはすでに最新バージョンです'
|
||||
LocalAppVersionNull: '{{ .name }} アプリケーションはバージョンに同期されていません。アプリリストに追加できません'
|
||||
LocalAppVersionErr: '{{ .name }} バージョン {{ .version }} の同期に失敗しました! {{ .err }}'
|
||||
LocalAppVersionErr: '{{ .name }} バージョン {{ .version }} の同期に失敗しました {{ .err }}'
|
||||
ErrFileNotFound: '{{ .name }} ファイルが存在しません'
|
||||
ErrFileParseApp: '{{ .name }} ファイルの解析に失敗しました {{ .err }}'
|
||||
ErrAppDirNull: 'バージョン フォルダーが存在しません'
|
||||
LocalAppErr: 'アプリケーション {{ .name }} の同期に失敗しました! {{ .err }}'
|
||||
LocalAppErr: 'アプリケーション {{ .name }} の同期に失敗しました {{ .err }}'
|
||||
ErrContainerName: 'コンテナ名が既に存在します'
|
||||
ErrCreateHttpClient: 'リクエスト {{ .err }} の作成に失敗しました'
|
||||
ErrHttpReqTimeOut: 'リクエストがタイムアウトしました {{ .err }}'
|
||||
@@ -86,64 +79,58 @@ ErrAppBackup: '{{ .name }} アプリケーションのバックアップに失
|
||||
ErrVersionTooLow: '現在の 1Panel のバージョンが低すぎるため、App Store を更新できません。操作する前にバージョンをアップグレードしてください。'
|
||||
ErrAppNameExist: 'アプリケーション名がすでに存在します'
|
||||
AppStoreIsSyncing: 'App Store が同期中です。しばらくしてからもう一度お試しください'
|
||||
ErrGetCompose: 'docker-compose.yml ファイルの取得に失敗しました! {{ .detail }}'
|
||||
ErrGetCompose: 'docker-compose.yml ファイルの取得に失敗しました {{ .detail }}'
|
||||
ErrAppWarn: '異常な状態です。ログを確認してください'
|
||||
ErrAppParamKey: 'パラメータ {{ .name }} フィールドが異常です'
|
||||
ErrAppUpgrade: 'アプリケーション {{ .name }} のアップグレードに失敗しました {{ .err }}'
|
||||
AppRecover: 'アプリケーション {{ .name }} をロールバックします'
|
||||
PullImageStart: "イメージ [{{ .name }}] のプルを開始します"
|
||||
PullImageStart: 'イメージ [{{ .name }}] のプルを開始します'
|
||||
PullImageSuccess: 'イメージのプルが成功しました'
|
||||
AppStoreIsLastVersion: 'App Store はすでに最新バージョンです'
|
||||
AppStoreSyncSuccess: 'App Store の同期が成功しました'
|
||||
SyncAppDetail: 'アプリケーション構成を同期する'
|
||||
AppVersionNotMatch: '{{ .name }} アプリケーションには、より高い 1Panel バージョンが必要なため、同期をスキップします'
|
||||
MoveSiteDir: "ウェブサイトディレクトリの変更を検出しました。OpenResty ウェブサイトディレクトリを {{ .name }} に移行する必要があります"
|
||||
MoveSiteDir: 'ウェブサイトディレクトリの変更を検出しました。OpenResty ウェブサイトディレクトリを {{ .name }} に移行する必要があります'
|
||||
MoveSiteDirSuccess: 'Web サイト ディレクトリの移行に成功しました'
|
||||
DeleteRuntimePHP: 'PHP ランタイムを削除する'
|
||||
CustomAppStoreFileValid: 'App Store パッケージは .tar.gz 形式である必要があります'
|
||||
CustomAppStoreFileValid: 'App Store パッケージは.tar.gz 形式である必要があります'
|
||||
PullImageTimeout: 'プル イメージのタイムアウトです。イメージのアクセラレーションを増やすか、別のイメージのアクセラレーションに変更してください'
|
||||
ErrAppIsDown: '{{ .name }} アプリケーションの状態が異常です。確認してください'
|
||||
ErrCustomApps: 'インストールされているアプリケーションがあります。まずアンインストールしてください'
|
||||
ErrCustomRuntimes: 'ランタイム環境がインストールされています。まずそれを削除してください'
|
||||
ErrAppVersionDeprecated: "{{ .name }} アプリケーションは現在の 1Panel バージョンと互換性がありません、スキップしました"
|
||||
ErrDockerFailed: "Docker の状態が異常です。サービス状態を確認してください"
|
||||
ErrDockerComposeCmdNotFound: "Docker Compose コマンドは存在しません。ホストマシンにこのコマンドを先にインストールしてください"
|
||||
UseExistImage: 'イメージのプルに失敗しました、既存のイメージを使用します'
|
||||
|
||||
#ssh
|
||||
ExportIP: "ログインIP"
|
||||
ExportArea: "地域"
|
||||
ExportPort: "ポート"
|
||||
ExportAuthMode: "ログイン方式"
|
||||
ExportUser: "ユーザー"
|
||||
ExportStatus: "ログイン状態"
|
||||
ExportDate: "時間"
|
||||
|
||||
#file
|
||||
ErrAppVersionDeprecated: '{{ .name }} アプリケーションは現在の 1Panel バージョンと互換性がありません、スキップしました'
|
||||
ErrDockerFailed: 'Docker の状態が異常です。サービス状態を確認してください'
|
||||
ErrDockerComposeCmdNotFound: 'Docker Compose コマンドは存在しません。ホストマシンにこのコマンドを先にインストールしてください'
|
||||
UseExistImage: 'イメージは既に存在します。既存のイメージを使用します'
|
||||
ErrDatabaseNotFound: 'データベース {{ .name }} は存在しません'
|
||||
ExportIP: 'ログインIP'
|
||||
ExportArea: '地域'
|
||||
ExportPort: 'ポート'
|
||||
ExportAuthMode: 'ログイン方式'
|
||||
ExportUser: 'ユーザー'
|
||||
ExportStatus: 'ログイン状態'
|
||||
ExportDate: '時間'
|
||||
ErrFileCanNotRead: 'このファイルはプレビューをサポートしていません'
|
||||
ErrFileToLarge: 'ファイルは 10M より大きいため開けません'
|
||||
ErrPathNotFound: 'ディレクトリが存在しません'
|
||||
ErrMovePathFailed: 'ターゲット パスに元のパスを含めることはできません!'
|
||||
ErrLinkPathNotFound: 'ターゲット パスが存在しません!'
|
||||
ErrFileIsExist: 'ファイルまたはフォルダーは既に存在します!'
|
||||
ErrMovePathFailed: 'ターゲット パスに元のパスを含めることはできません'
|
||||
ErrLinkPathNotFound: 'ターゲット パスが存在しません'
|
||||
ErrFileIsExist: 'ファイルまたはフォルダーは既に存在します'
|
||||
ErrFileUpload: '{{ .name }} はファイル {{ .detail }} のアップロードに失敗しました'
|
||||
ErrFileDownloadDir: 'ダウンロード フォルダーはサポートされていません'
|
||||
ErrCmdNotFound: '{{ .name}} コマンドが存在しません。まずこのコマンドをホストにインストールしてください'
|
||||
ErrCmdNotFound: '{{ .name }} コマンドが存在しません。まずこのコマンドをホストにインストールしてください'
|
||||
ErrSourcePathNotFound: 'ソース ディレクトリが存在しません'
|
||||
ErrFavoriteExist: 'このパスはすでにお気に入りに登録されています'
|
||||
ErrInvalidChar: '不正な文字は許可されません'
|
||||
ErrPathNotDelete: '選択されたディレクトリは削除できません'
|
||||
ErrLogFileToLarge: "ログファイルが500MBを超えており、開くことができません"
|
||||
FileDropFailed: "ファイル {{ .name }} のクリーンアップに失敗しました: {{ .err }}"
|
||||
FileDropSuccess: "ファイル {{ .name }} のクリーンアップに成功しました、{{ .count }} ファイルを削除、{{ .size }} のディスク領域を解放"
|
||||
FileDropSum: "ファイルのクリーンアップが完了しました、合計 {{ .count }} ファイルを削除、合計 {{ .size }} のディスク領域を解放"
|
||||
ErrBadDecrypt: "圧縮パッケージの解凍パスワードが間違っています。解凍に失敗しました。確認して再試行してください!"
|
||||
|
||||
#website
|
||||
ErrLogFileToLarge: 'ログファイルが500MBを超えており、開くことができません'
|
||||
FileDropFailed: 'ファイル {{ .name }} のクリーンアップに失敗しました: {{ .err }}'
|
||||
FileDropSuccess: 'ファイル {{ .name }} のクリーンアップに成功しました、{{ .count }} ファイルを削除、{{ .size }} のディスク領域を解放'
|
||||
FileDropSum: 'ファイルのクリーンアップが完了しました、合計 {{ .count }} ファイルを削除、合計 {{ .size }} のディスク領域を解放'
|
||||
ErrBadDecrypt: '圧縮パッケージの解凍パスワードが間違っています。解凍に失敗しました。確認後再試行!'
|
||||
ErrAliasIsExist: 'エイリアスがすでに存在します'
|
||||
ErrBackupMatch: 'バックアップ ファイルは、現在の Web サイト データ {{ .detail }} の一部と一致しません'
|
||||
ErrBackupExist: 'バックアップ ファイル内のソース データの対応する部分が存在しません {{ .detail }}'
|
||||
ErrPHPResource: 'ローカルオペレーティング環境は切り替えをサポートしていません! '
|
||||
ErrPHPResource: 'ローカルオペレーティング環境は切り替えをサポートしていません'
|
||||
ErrPathPermission: 'インデックス ディレクトリに 1000:1000 以外の権限を持つフォルダーが検出されました。これにより、Web サイトでアクセス拒否エラーが発生する可能性があります。上記の保存ボタンをクリックしてください。'
|
||||
ErrDomainIsUsed: 'ドメイン名はウェブサイト [{{ .name }}] で既に使用されています'
|
||||
ErrDomainFormat: '{{ .name }} ドメイン名の形式が正しくありません'
|
||||
@@ -151,11 +138,11 @@ ErrDefaultAlias: 'デフォルトは予約済みのコードです。別のコ
|
||||
ErrParentWebsite: 'まずサブサイト {{ .name }} を削除する必要があります'
|
||||
ErrBuildDirNotFound: 'ビルド ディレクトリが存在しません'
|
||||
ErrImageNotExist: 'オペレーティング環境 {{ .name }} イメージが存在しません。オペレーティング環境を再編集してください'
|
||||
ErrProxyIsUsed: "ロードバランシングはリバースプロキシによって使用されているため、削除できません"
|
||||
ErrProxyIsUsed: 'ロードバランシングはリバースプロキシによって使用されているため、削除できません'
|
||||
ErrSSLValid: '証明書ファイルが異常です、証明書の状態を確認してください!'
|
||||
ErrWebsiteDir: "ウェブサイトディレクトリ内のディレクトリを選択してください。"
|
||||
ErrComposerFileNotFound: "composer.json ファイルが存在しません"
|
||||
ErrRuntimeNoPort: "ランタイム環境にポートが設定されていません。先にランタイム環境を編集してください。"
|
||||
ErrWebsiteDir: 'ウェブサイトディレクトリ内のディレクトリを選択してください。'
|
||||
ErrComposerFileNotFound: 'composer.json ファイルが存在しません'
|
||||
ErrRuntimeNoPort: 'ランタイム環境にポートが設定されていません。先にランタイム環境を編集してください。'
|
||||
Status: 'ステータス'
|
||||
start: '開始'
|
||||
stop: '停止'
|
||||
@@ -168,8 +155,6 @@ delete: '削除'
|
||||
ErrDefaultWebsite: 'デフォルト Web サイトが既に設定されています。設定する前にキャンセルしてください!'
|
||||
SSL: '証明書'
|
||||
Set: '設定'
|
||||
|
||||
#ssl
|
||||
ErrSSLCannotDelete: '{{ .name }} 証明書は Web サイトで使用されているため、削除できません'
|
||||
ErrAccountCannotDelete: 'アカウントは証明書に関連付けられているため、削除できません'
|
||||
ErrSSLApply: '証明書の更新は成功しましたが、openresty の再ロードに失敗しました。設定を確認してください。'
|
||||
@@ -180,12 +165,12 @@ ErrSSLKeyFormat: '秘密鍵ファイルの検証に失敗しました'
|
||||
ErrSSLCertificateFormat: '証明書ファイルの形式が正しくありません。pem 形式を使用してください'
|
||||
ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid または EabHmacKey は空白にできません'
|
||||
ErrOpenrestyNotFound: 'Http モードでは、まず Openresty をインストールする必要があります'
|
||||
ApplySSLStart: '証明書の申請を開始します。ドメイン名 [{{ .domain }}] 申請方法 [{{ .type }}] '
|
||||
ApplySSLStart: '証明書の申請を開始します。ドメイン名 [{{ .domain }}] 申請方法 [{{ .type }}]'
|
||||
dnsAccount: 'DNS 自動'
|
||||
dnsManual: 'DNS マニュアル'
|
||||
http: "HTTP"
|
||||
http: 'HTTP'
|
||||
ApplySSLFailed: '[{{ .domain }}] 証明書の申請に失敗しました、{{ .detail }}'
|
||||
ApplySSLSuccess: '[{{ .domain }}] 証明書の申請に成功しました! '
|
||||
ApplySSLSuccess: '[{{ .domain }}] 証明書の申請に成功しました。'
|
||||
DNSAccountName: 'DNS アカウント [{{ .name }}] ベンダー [{{ .type }}]'
|
||||
PushDirLog: '証明書がディレクトリ [{{ .path }}] {{ .status }} にプッシュされました'
|
||||
ErrDeleteCAWithSSL: '現在の組織には発行済みの証明書があり、削除できません。'
|
||||
@@ -200,41 +185,33 @@ ExecShellSuccess: 'スクリプトの実行が成功しました'
|
||||
StartUpdateSystemSSL: 'システム証明書の更新を開始します'
|
||||
UpdateSystemSSLSuccess: 'システム証明書を正常に更新しました'
|
||||
ErrWildcardDomain: 'HTTP モードでワイルドカード ドメイン名証明書を申請できません'
|
||||
ErrApplySSLCanNotDelete: "申請中の証明書 {{.name}} は削除できません。しばらくしてからもう一度お試しください。"
|
||||
StartPushSSLToNode: "証明書をノードにプッシュ開始"
|
||||
PushSSLToNodeFailed: "ノードに証明書をプッシュ失敗: {{ .err }}"
|
||||
PushSSLToNodeSuccess: "ノードに証明書をプッシュ成功"
|
||||
|
||||
#mysql
|
||||
ErrApplySSLCanNotDelete: '申請中の証明書 {{ .name }} は削除できません。しばらくしてからもう一度お試しください。'
|
||||
StartPushSSLToNode: '証明書をノードにプッシュ開始'
|
||||
PushSSLToNodeFailed: 'ノードに証明書をプッシュ失敗: {{ .err }}'
|
||||
PushSSLToNodeSuccess: 'ノードに証明書をプッシュ成功'
|
||||
ErrUserIsExist: '現在のユーザーは既に存在します。再入力してください'
|
||||
ErrDatabaseIsExist: '現在のデータベースは既に存在します。再入力してください'
|
||||
ErrExecTimeOut: 'SQL 実行がタイムアウトしました。データベースを確認してください'
|
||||
ErrRemoteExist: 'この名前のリモート データベースは既に存在します。変更してもう一度お試しください'
|
||||
ErrLocalExist: '名前はローカル データベースに既に存在します。変更してもう一度お試しください'
|
||||
RemoteBackup: "リモートデータベースをバックアップするには、まずイメージ {{ .name }} を使用してローカルコンテナデータベースサービスを起動する必要があります。しばらくお待ちください..."
|
||||
RemoteRecover: "リモートデータベースを復元するには、まずイメージ {{ .name }} を使用してローカルコンテナデータベースサービスを起動する必要があります。しばらくお待ちください..."
|
||||
Arg: "引数"
|
||||
|
||||
#redis
|
||||
RemoteBackup: 'リモートデータベースをバックアップするには、まずイメージ {{ .name }} を使用してローカルコンテナデータベースサービスを起動する必要があります。しばらくお待ちください...'
|
||||
RemoteRecover: 'リモートデータベースを復元するには、まずイメージ {{ .name }} を使用してローカルコンテナデータベースサービスを起動する必要があります。しばらくお待ちください...'
|
||||
Arg: '引数'
|
||||
ErrTypeOfRedis: 'リカバリ ファイルの種類が現在の永続化方法と一致しません。変更して再試行してください'
|
||||
|
||||
#container
|
||||
ErrInUsed: "{{ .detail }} は使用中であり、削除できません!"
|
||||
ErrObjectInUsed: "このオブジェクトは使用中であり、削除できません!"
|
||||
ErrObjectBeDependent: "このイメージは他のイメージに依存されているため、削除できません!"
|
||||
ErrInUsed: '{{ .detail }} は使用中であり、削除できません!'
|
||||
ErrObjectInUsed: 'このオブジェクトは使用中であり、削除できません!'
|
||||
ErrObjectBeDependent: 'このイメージは他のイメージに依存されているため、削除できません!'
|
||||
ErrPortRules: 'ポート番号が一致しません。再入力してください。'
|
||||
ErrPgImagePull: 'イメージのプルがタイムアウトしました。イメージのアクセラレーションを設定するか、{{ .name }} イメージを手動でプルして再試行してください'
|
||||
PruneHelper: "今回のクリーンアップ {{ .name }} でディスク領域 {{ .size }} を解放しました"
|
||||
ImageRemoveHelper: "イメージ{{ .name }}を削除し、{{ .size }}のディスク領域を解放しました"
|
||||
BuildCache: "ビルドキャッシュ"
|
||||
Volume: "ストレージボリューム"
|
||||
Network: "ネットワーク"
|
||||
PruneStart: "クリーンアップ中、しばらくお待ちください..."
|
||||
|
||||
#runtime
|
||||
PruneHelper: '今回のクリーンアップ {{ .name }} でディスク領域 {{ .size }} を解放しました'
|
||||
ImageRemoveHelper: 'イメージ{{ .name }}を削除し、{{ .size }}のディスク領域を解放しました'
|
||||
BuildCache: 'ビルドキャッシュ'
|
||||
Volume: 'ストレージボリューム'
|
||||
Network: 'ネットワーク'
|
||||
PruneStart: 'クリーンアップ中、しばらくお待ちください...'
|
||||
ErrFileNotExist: '{{ .detail }} ファイルが存在しません。ソース ファイルの整合性を確認してください。'
|
||||
ErrImageBuildErr: 'イメージのビルドに失敗しました'
|
||||
ErrImageExist: "イメージはすでに存在します!イメージ名を変更してください。"
|
||||
ErrImageExist: 'イメージはすでに存在します!イメージ名を変更してください。'
|
||||
ErrDelWithWebsite: 'オペレーティング環境は既に Web サイトに関連付けられているため、削除できません'
|
||||
ErrRuntimeStart: '起動に失敗しました'
|
||||
ErrPackageJsonNotFound: 'package.json ファイルが存在しません'
|
||||
@@ -242,55 +219,45 @@ ErrScriptsNotFound: 'スクリプト構成項目が package.json に見つかり
|
||||
ErrContainerNameNotFound: 'コンテナ名を取得できません。.env ファイルを確認してください'
|
||||
ErrNodeModulesNotFound: 'node_modules フォルダが存在しません。ランタイム環境を編集するか、ランタイム環境が正常に起動するまでお待ちください。'
|
||||
ErrContainerNameIsNull: 'コンテナ名が存在しません'
|
||||
ErrPHPPortIsDefault: "ポート9000はデフォルトポートです。修正してから再試行してください"
|
||||
ErrPHPRuntimePortFailed: "ポート {{ .name }} は現在のランタイム環境で使用されています。修正してから再試行してください"
|
||||
|
||||
#tool
|
||||
ErrPHPPortIsDefault: 'ポート9000はデフォルトポートです。修正してから再試行してください'
|
||||
ErrPHPRuntimePortFailed: 'ポート {{ .name }} は現在のランタイム環境で使用されています。修正してから再試行してください'
|
||||
ErrConfigNotFound: '構成ファイルが存在しません'
|
||||
ErrConfigParse: '構成ファイルの形式が正しくありません'
|
||||
ErrConfigIsNull: '構成ファイルは空にできません'
|
||||
ErrConfigDirNotFound: '実行ディレクトリが存在しません'
|
||||
ErrConfigAlreadyExist: '同じ名前の設定ファイルがすでに存在します'
|
||||
ErrUserFindErr: 'ユーザー {{ .name }} の検索に失敗しました {{ .err }}'
|
||||
|
||||
#cronjob
|
||||
CutWebsiteLogSuccess: '{{ .name }} ウェブサイトのログが正常にカットされました。バックアップ パス {{ .path }}'
|
||||
HandleShell: 'スクリプト {{ .name }} を実行します'
|
||||
HandleCurl: "URL {{ .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: "WAF IPグループが見つかりません。[高度な機能 - WAF - ブラックリスト/ホワイトリスト - IPグループ]に移動し、リモートダウンロード方式でIPグループを追加してください。"
|
||||
|
||||
#toolbox
|
||||
Upload: 'アップロード'
|
||||
IgnoreBackupErr: 'バックアップ失敗、エラー: {{ .detail }}、このエラーを無視します...'
|
||||
IgnoreUploadErr: 'アップロード失敗、エラー: {{ .detail }}、このエラーを無視します...'
|
||||
LoadBackupFailed: 'バックアップアカウントの接続取得に失敗、エラー: {{ .detail }}'
|
||||
InExecuting: '現在のタスクは実行中です。重複して実行しないでください!'
|
||||
NoSuchResource: 'データベースにバックアップ内容が見つかりませんでした。スキップします...'
|
||||
CleanLog: 'ログをクリーン'
|
||||
CleanLogByName: '{{ .name }} のログをクリーン'
|
||||
WafIpGroupNotFound: 'WAF IPグループが見つかりません。[高度な機能 - WAF - ブラックリスト/ホワイトリスト - IPグループ]に移動し、リモートダウンロード方式でIPグループを追加してください。'
|
||||
ErrNotExistUser: '現在のユーザーは存在しません。変更してもう一度お試しください。'
|
||||
ErrBanAction: '設定に失敗しました。現在の {{ .name }} サービスは利用できません。確認してもう一度お試しください。'
|
||||
ErrClamdscanNotFound: 'clamdscan コマンドが検出されませんでした。インストールするにはドキュメントを参照してください。'
|
||||
TaskSwapSet: "Swap設定"
|
||||
SetSwap: "Swap設定 {{ .path }} - {{ .size }}"
|
||||
CreateSwap: "Swapファイル作成"
|
||||
FormatSwap: "Swapファイルフォーマット"
|
||||
EnableSwap: "Swapファイル有効化"
|
||||
|
||||
#tamper
|
||||
CleanTamperSetting: "履歴保護設定をクリーンアップ"
|
||||
SetTamperWithRules: "ルールに従ってディレクトリ保護を開始"
|
||||
ProtectDir: "ディレクトリを保護 {{ .name }}"
|
||||
IgnoreFile: "ファイルを保護 {{ .name }}"
|
||||
TamperSetSuccessful: "保護設定が完了し、以下のディレクトリの監視を開始します:"
|
||||
|
||||
#waf
|
||||
TaskSwapSet: 'Swap設定'
|
||||
SetSwap: 'Swap設定 {{ .path }} - {{ .size }}'
|
||||
CreateSwap: 'Swapファイル作成'
|
||||
FormatSwap: 'Swapファイルフォーマット'
|
||||
EnableSwap: 'Swapファイル有効化'
|
||||
CleanTamperSetting: '履歴保護設定をクリーンアップ'
|
||||
SetTamperWithRules: 'ルールに従ってディレクトリ保護を開始'
|
||||
ProtectDir: 'ディレクトリを保護 {{ .name }}'
|
||||
IgnoreFile: 'ファイルを保護 {{ .name }}'
|
||||
TamperSetSuccessful: '保護設定が完了し、以下のディレクトリの監視を開始します:'
|
||||
ErrScope: 'この構成の変更はサポートされていません'
|
||||
ErrStateChange: '状態の変更に失敗しました'
|
||||
ErrRuleExist: 'ルールは既に存在します'
|
||||
@@ -298,7 +265,7 @@ ErrRuleNotExist: 'ルールが存在しません'
|
||||
ErrParseIP: 'IP 形式が間違っています'
|
||||
ErrDefaultIP: 'デフォルトは予約名です。別の名前に変更してください'
|
||||
ErrGroupInUse: 'IP グループはブラックリスト/ホワイトリストで使用されており、削除できません'
|
||||
ErrIPGroupAclUse: "IPグループはウェブサイト {{ .name }} のカスタムルールで使用されているため、削除できません"
|
||||
ErrIPGroupAclUse: 'IPグループはウェブサイト {{ .name }} のカスタムルールで使用されているため、削除できません'
|
||||
ErrGroupExist: 'IP グループ名がすでに存在します'
|
||||
ErrIPRange: 'IP 範囲が間違っています'
|
||||
ErrIPExist: 'IP がすでに存在します'
|
||||
@@ -309,10 +276,10 @@ xss: 'XSS'
|
||||
phpExec: 'PHP スクリプトの実行'
|
||||
oneWordTrojan: 'ワンワードトロイの木馬'
|
||||
appFilter: '危険なディレクトリフィルタリングを適用する'
|
||||
webshell: 'ウェブシェル'
|
||||
webShell: 'ウェブシェル'
|
||||
args: 'パラメータルール'
|
||||
protocolFilter: 'プロトコルフィルタリング'
|
||||
javaFileter: 'Java 危険ファイル フィルター'
|
||||
javaFilter: 'Java 危険ファイル フィルター'
|
||||
scannerFilter: 'スキャナ フィルタ'
|
||||
escapeFilter: 'エスケープフィルター'
|
||||
customRule: 'カスタムルール'
|
||||
@@ -342,10 +309,9 @@ ErrDBNotExist: 'データベースが存在しません'
|
||||
allow: '許可'
|
||||
deny: '拒否'
|
||||
OpenrestyNotFound: 'Openresty がインストールされていません'
|
||||
remoteIpIsNull: "IPリストが空です"
|
||||
OpenrestyVersionErr: "Openrestyのバージョンが低すぎます。Openrestyを1.27.1.2-2-2-focalにアップグレードしてください"
|
||||
|
||||
#task
|
||||
remoteIpIsNull: 'IPリストが空です'
|
||||
OpenrestyVersionErr: 'Openrestyのバージョンが低すぎます。Openrestyを1.27.1.2-2-2-focalにアップグレードしてください'
|
||||
ErrFileTooLarge: 'ファイルが 1MB を超えているためアップロードできません'
|
||||
TaskStart: '{{ .name }} タスクが開始されました [START]'
|
||||
TaskEnd: '{{ .name }} タスクが完了しました [COMPLETED]'
|
||||
TaskFailed: '{{ .name }} タスクが失敗しました'
|
||||
@@ -361,7 +327,7 @@ TaskDelete: '削除'
|
||||
TaskUpgrade: 'アップグレード'
|
||||
TaskUpdate: '更新'
|
||||
TaskRestart: '再起動'
|
||||
TaskProtect: "保護"
|
||||
TaskProtect: '保護'
|
||||
TaskBackup: 'バックアップ'
|
||||
TaskRecover: '回復'
|
||||
TaskRollback: 'ロールバック'
|
||||
@@ -369,10 +335,10 @@ TaskPull: 'プル'
|
||||
TaskCommit: 'コミット'
|
||||
TaskBuild: 'ビルド'
|
||||
TaskPush: 'プッシュ'
|
||||
TaskClean: "クリーンアップ"
|
||||
TaskClean: 'クリーンアップ'
|
||||
TaskHandle: '実行'
|
||||
TaskImport: "インポート"
|
||||
TaskExport: "エクスポート"
|
||||
TaskImport: 'インポート'
|
||||
TaskExport: 'エクスポート'
|
||||
Website: 'ウェブサイト'
|
||||
App: 'アプリケーション'
|
||||
Runtime: 'ランタイム環境'
|
||||
@@ -404,18 +370,12 @@ RuntimeExtension: 'ランタイム環境拡張'
|
||||
TaskIsExecuting: 'タスクは実行中です'
|
||||
CustomAppstore: 'カスタム アプリケーション ウェアハウス'
|
||||
TaskExec: '実行'
|
||||
TaskBatch: "一括操作"
|
||||
TaskBatch: '一括操作'
|
||||
FileConvert: 'ファイル形式の変換'
|
||||
|
||||
# task - clam
|
||||
Clamscan: "{{ .name }} をスキャン"
|
||||
TaskScan: "スキャン"
|
||||
|
||||
#task - ai
|
||||
Clamscan: '{{ .name }} をスキャン'
|
||||
TaskScan: 'スキャン'
|
||||
OllamaModelPull: 'Ollama モデル {{ .name }} をプルします'
|
||||
OllamaModelSize: "Ollama モデル {{ .name }} のサイズを取得します"
|
||||
|
||||
#task - snapshot
|
||||
OllamaModelSize: 'Ollama モデル {{ .name }} のサイズを取得します'
|
||||
Snapshot: 'スナップショット'
|
||||
SnapDBInfo: '1Panel データベース情報を書き込む'
|
||||
SnapCopy: 'ファイルとディレクトリ {{ .name }} をコピーします'
|
||||
@@ -441,7 +401,6 @@ SnapCompressSize: 'スナップショット ファイル サイズ {{ .name }}'
|
||||
SnapUpload: 'スナップショット ファイルをアップロード'
|
||||
SnapUploadTo: 'スナップショット ファイルを {{ .name }} にアップロードします'
|
||||
SnapUploadRes: 'スナップショット ファイルを {{ .name }} にアップロードします'
|
||||
|
||||
SnapshotRecover: 'スナップショットの復元'
|
||||
RecoverDownload: 'スナップショット ファイルをダウンロード'
|
||||
Download: 'ダウンロード'
|
||||
@@ -449,10 +408,10 @@ RecoverDownloadAccount: 'スナップショット ダウンロード バック
|
||||
RecoverDecompress: 'スナップショット圧縮ファイルを解凍する'
|
||||
Decompress: '減圧'
|
||||
BackupBeforeRecover: 'スナップショットの前にシステム関連データをバックアップする'
|
||||
Readjson: 'スナップショット内の Json ファイルを読み取ります'
|
||||
ReadjsonPath: 'スナップショット内の Json ファイル パスを取得します'
|
||||
ReadjsonContent: 'Json ファイルを読み取ります'
|
||||
ReadjsonMarshal: 'Json エスケープ処理'
|
||||
ReadJson: 'スナップショット内の Json ファイルを読み取ります'
|
||||
ReadJsonPath: 'スナップショット内の Json ファイル パスを取得します'
|
||||
ReadJsonContent: 'Json ファイルを読み取ります'
|
||||
ReadJsonMarshal: 'Json エスケープ処理'
|
||||
RecoverApp: 'インストールされたアプリを復元する'
|
||||
RecoverWebsite: 'ウェブサイトディレクトリを回復する'
|
||||
RecoverAppImage: 'スナップショットイメージのバックアップを復元する'
|
||||
@@ -466,9 +425,6 @@ RecoverDaemonJson: 'コンテナ構成 daemon.json ファイルを復元する'
|
||||
RecoverDBData: 'データベース データを回復する'
|
||||
RecoverBackups: 'ローカル バックアップ ディレクトリを復元する'
|
||||
RecoverPanelData: 'リカバリデータディレクトリ'
|
||||
|
||||
#task - container
|
||||
ContainerNewCliet: 'Docker クライアントを初期化する'
|
||||
ContainerImagePull: 'コンテナ イメージ {{ .name }} をプルします'
|
||||
ContainerRemoveOld: '元のコンテナ {{ .name }} を削除します'
|
||||
ContainerImageCheck: 'イメージが正常にプルされているかどうかを確認します'
|
||||
@@ -477,22 +433,13 @@ ContainerRecreate: 'コンテナの更新に失敗しました。元のコンテ
|
||||
ContainerCreate: '新しいコンテナ {{ .name }} を作成します'
|
||||
ContainerCreateFailed: 'コンテナの作成に失敗しました。失敗したコンテナを削除してください'
|
||||
ContainerStartCheck: 'コンテナが起動されているかどうかを確認します'
|
||||
|
||||
#task - image
|
||||
ImageBuild: 'イメージビルド'
|
||||
ImageBuildStdoutCheck: '画像出力コンテンツを解析する'
|
||||
ImageBuildRes: 'イメージビルド出力: {{ .name }}'
|
||||
ImagePull: '画像をプル'
|
||||
ImageRepoAuthFromDB: 'データベースからリポジトリ認証情報を取得する'
|
||||
ImaegPullRes: "画像プル出力: {{ .name }}"
|
||||
ImagePush: '画像をプッシュ'
|
||||
ImageRenameTag: '画像タグを変更する'
|
||||
ImageNewTag: '新しい画像タグ {{ .name }}'
|
||||
ImaegPushRes: '画像プッシュ出力: {{ .name }}'
|
||||
ComposeCreate: 'コンポジションを作成する'
|
||||
ComposeCreateRes: "Compose 作成出力: {{ .name }}"
|
||||
|
||||
#task - website
|
||||
BackupNginxConfig: 'ウェブサイトの OpenResty 構成ファイルをバックアップする'
|
||||
CompressFileSuccess: 'ディレクトリを正常に圧縮しました。{{ .name }} に圧縮されました'
|
||||
CompressDir: '圧縮ディレクトリ'
|
||||
@@ -503,40 +450,27 @@ websiteDir: 'ウェブサイトディレクトリ'
|
||||
RecoverFailedStartRollBack: 'リカバリに失敗しました。ロールバックを開始します'
|
||||
AppBackupFileIncomplete: 'バックアップ ファイルが不完全で、app.json または app.tar.gz ファイルが不足しています'
|
||||
AppAttributesNotMatch: 'アプリケーションの種類または名前が一致しません'
|
||||
|
||||
#alert
|
||||
ErrAlert: '警告メッセージの形式が正しくありません。確認してもう一度お試しください。'
|
||||
ErrAlertPush: 'アラート情報のプッシュ中にエラーが発生しました。確認してもう一度お試しください。'
|
||||
ErrAlertSave: 'アラーム情報の保存中にエラーが発生しました。確認してもう一度お試しください。'
|
||||
ErrAlertSync: 'アラーム情報の同期エラーです。確認してもう一度お試しください。'
|
||||
ErrAlertRemote: 'アラーム メッセージのリモート エラーです。確認してもう一度お試しください。'
|
||||
|
||||
#task - runtime
|
||||
ErrInstallExtension: "インストールタスクが進行中です、タスクが終了するのを待ってください"
|
||||
|
||||
# alert mail template
|
||||
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 }} パネル、過去 {{ .time }} 分間の {{ .name }} 平均使用率は {{ .used }} です。詳細はパネルにログインしてご確認ください。"
|
||||
PanelVersionAlert: "あなたの {{ .node }}{{ .ip }} パネル、最新バージョンがアップグレード可能です。詳細はパネルにログインしてご確認ください。"
|
||||
PanelPwdExpirationAlert: "あなたの {{ .node }}{{ .ip }} パネル、パネルパスワードは {{ .day }} 日後に期限切れになります。詳細はパネルにログインしてご確認ください。"
|
||||
CommonAlert: "あなたの {{ .node }}{{ .ip }} パネル、{{ .msg }}。詳細はパネルにログインしてご確認ください。"
|
||||
NodeExceptionAlert: "あなたの {{ .node }}{{ .ip }} パネル、{{ .num }} 個のノードに異常が発生しています。詳細はパネルにログインしてご確認ください。"
|
||||
LicenseExceptionAlert: "あなたの {{ .node }}{{ .ip }} パネル、{{ .num }} 個のライセンスに異常が発生しています。詳細はパネルにログインしてご確認ください。"
|
||||
SSHAndPanelLoginAlert: "あなたの {{ .node }}{{ .ip }} パネル、{{ .loginIp }} からの {{ .name }} ログインに異常があります。詳細はパネルにログインしてご確認ください。"
|
||||
|
||||
#disk
|
||||
DeviceNotFound: "デバイス {{ .name }} が見つかりません"
|
||||
DeviceIsMounted: "デバイス {{ .name }} はマウントされています、まずアンマウントしてください"
|
||||
PartitionDiskErr: "パーティションに失敗しました、{{ .err }}"
|
||||
FormatDiskErr: "ディスクのフォーマットに失敗しました、{{ .err }}"
|
||||
MountDiskErr: "ディスクのマウントに失敗しました、{{ .err }}"
|
||||
UnMountDiskErr: "ディスクのアンマウントに失敗しました、{{ .err }}"
|
||||
XfsNotFound: "xfs ファイルシステムが検出されませんでした、最初に xfsprogs をインストールしてください"
|
||||
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 }} パネル、過去 {{ .time }} 分間の {{ .name }} 平均使用率は {{ .used }} です。詳細はパネルにログインして'
|
||||
PanelVersionAlert: 'あなたの {{ .node }}{{ .ip }} パネル、最新バージョンがアップグレード可能です。詳細はパネルにログインして'
|
||||
PanelPwdExpirationAlert: 'あなたの {{ .node }}{{ .ip }} パネル、パネルパスワードは {{ .day }} 日後に期限切れになります。詳細はパネルにログインして'
|
||||
CommonAlert: 'あなたの {{ .node }}{{ .ip }} パネル、{{ .msg }}。詳細はパネルにログインして'
|
||||
NodeExceptionAlert: 'あなたの {{ .node }}{{ .ip }} パネル、{{ .num }} 個のノードに異常が発生しています。詳細はパネルにログインして'
|
||||
LicenseExceptionAlert: 'あなたの {{ .node }}{{ .ip }} パネル、{{ .num }} 個のライセンスに異常が発生しています。詳細はパネルにログインして'
|
||||
SSHAndPanelLoginAlert: 'あなたの {{ .node }}{{ .ip }} パネル、{{ .loginIp }} からの {{ .name }} ログインに異常があります。詳細はパネルにログインして'
|
||||
DeviceNotFound: 'デバイス {{ .name }} が見つかりません'
|
||||
DeviceIsMounted: 'デバイス {{ .name }} はマウントされています、まずアンマウントしてください'
|
||||
PartitionDiskErr: 'パーティションに失敗しました、{{ .err }}'
|
||||
FormatDiskErr: 'ディスクのフォーマットに失敗しました、{{ .err }}'
|
||||
MountDiskErr: 'ディスクのマウントに失敗しました、{{ .err }}'
|
||||
XfsNotFound: 'xfs ファイルシステムが検出されませんでした、最初に xfsprogs をインストールしてください'
|
||||
|
||||
+172
-239
@@ -1,31 +1,28 @@
|
||||
ErrInvalidParams: '요청 매개변수 오류: {{ .detail }}'
|
||||
ErrTokenParse: '토큰 생성 오류: {{ .detail }}'
|
||||
ErrInitialPassword: '원래 비밀번호가 올바르지 않습니다'
|
||||
ErrInternalServer: '내부 서버 오류: {{ .detail }}'
|
||||
ErrRecordExist: '레코드가 이미 존재합니다'
|
||||
ErrInvalidParams: '잘못된 요청: {{ .detail }}'
|
||||
ErrTokenParse: '토큰 오류: {{ .detail }}'
|
||||
ErrInitialPassword: '원래 비밀번호가 틀립니다'
|
||||
ErrInternalServer: '서버 오류: {{ .detail }}'
|
||||
ErrRecordExist: '레코드가 이미 있습니다'
|
||||
ErrRecordNotFound: '레코드를 찾을 수 없습니다'
|
||||
ErrStructTransform: '유형 변환에 실패했습니다: {{ .err }}'
|
||||
ErrNotLogin: '사용자가 로그인하지 않았습니다: {{ .detail }}'
|
||||
ErrPasswordExpired: '현재 비밀번호가 만료되었습니다: {{ .detail }}'
|
||||
ErrNotSupportType: '시스템은 현재 유형 {{ .name }}을 지원하지 않습니다.'
|
||||
ErrProxy: '요청 오류, 노드 상태를 확인하세요: {{ .detail }}'
|
||||
ErrApiConfigStatusInvalid: 'API 인터페이스에 대한 액세스가 금지되었습니다: {{ .detail }}'
|
||||
ErrApiConfigKeyInvalid: 'API 인터페이스 키 오류: {{ .detail }}'
|
||||
ErrApiConfigIPInvalid: 'API 인터페이스를 호출하는 데 사용된 IP가 허용 목록에 없습니다: {{ .detail }}'
|
||||
ErrApiConfigDisable: '이 인터페이스는 API 인터페이스 호출 사용을 금지합니다: {{ .detail }}'
|
||||
ErrApiConfigKeyTimeInvalid: 'API 인터페이스 타임스탬프 오류: {{ .detail }}'
|
||||
ErrShutDown: "명령이 수동으로 종료되었습니다!"
|
||||
|
||||
ErrMinQuickJump: "최소 하나의 빠른 점프 항목을 설정해 주세요!"
|
||||
ErrMaxQuickJump: "최대 네 개의 빠른 점프 항목을 설정할 수 있습니다!"
|
||||
|
||||
#흔한
|
||||
ErrUsernameIsExist: '사용자 이름이 이미 존재합니다'
|
||||
ErrStructTransform: '형 변환 실패: {{ .err }}'
|
||||
ErrNotLogin: '로그인하지 않음: {{ .detail }}'
|
||||
ErrPasswordExpired: '비밀번호 만료: {{ .detail }}'
|
||||
ErrNotSupportType: '지원하지 않는 타입: {{ .name }}'
|
||||
ErrProxy: '요청 실패: {{ .detail }}'
|
||||
ErrApiConfigStatusInvalid: 'API 사용 중지: {{ .detail }}'
|
||||
ErrApiConfigKeyInvalid: 'API 키가 잘못됨: {{ .detail }}'
|
||||
ErrApiConfigIPInvalid: 'IP 허용되지 않음: {{ .detail }}'
|
||||
ErrApiConfigDisable: 'API 접근 금지: {{ .detail }}'
|
||||
ErrApiConfigKeyTimeInvalid: '타임스탬프 오류: {{ .detail }}'
|
||||
ErrShutDown: '명령이 수동으로 중단되었습니다'
|
||||
ErrMinQuickJump: '퀵 액세스를 하나 이상 추가하세요'
|
||||
ErrMaxQuickJump: '퀵 액세스는 최대 4개'
|
||||
ErrUsernameIsExist: '아이디가 이미 존재합니다'
|
||||
ErrNameIsExist: '이름이 이미 존재합니다'
|
||||
ErrDemoEnvironment: '데모 서버, 이 작업은 금지되어 있습니다!'
|
||||
ErrCmdTimeout: '명령 실행 시간이 초과되었습니다!'
|
||||
ErrCmdIllegal: '실행 명령에 잘못된 문자가 있습니다. 수정하여 다시 시도하세요!'
|
||||
ErrPortExist: '{{ .port }} 포트는 이미 {{ .type }} [{{ .name }}]에 의해 사용되고 있습니다.'
|
||||
ErrDemoEnvironment: '데모 환경에서는 불가'
|
||||
ErrCmdTimeout: '명령이 시간 초과했습니다'
|
||||
ErrCmdIllegal: '명령어에 허용되지 않은 문자가 포함됨'
|
||||
ErrPortExist: '포트 {{ .port }}는 {{ .type }} [{{ .name }}]에서 사용 중입니다'
|
||||
TYPE_APP: '응용 프로그램'
|
||||
TYPE_RUNTIME: '런타임 환경'
|
||||
TYPE_DOMAIN: '도메인 이름'
|
||||
@@ -36,45 +33,40 @@ Failed: '실패했습니다'
|
||||
SystemRestart: '시스템 재시작으로 인해 작업이 중단되었습니다'
|
||||
ErrGroupIsDefault: '기본 그룹, 삭제할 수 없습니다'
|
||||
ErrGroupIsInWebsiteUse: '그룹이 다른 웹사이트에서 사용 중이므로 삭제할 수 없습니다.'
|
||||
Decrypt: "복호화"
|
||||
|
||||
#agent
|
||||
ErrAgentAccountBound: '이 계정은 에이전트에 바인딩되어 있어 삭제할 수 없습니다. 확인 후 다시 시도하세요!'
|
||||
ErrAgentAccountUnavailable: '계정 연결 정보를 사용할 수 없습니다. 오류: {{ .err }}. 확인 후 다시 시도하세요!'
|
||||
ErrAgentProviderNotSupported: '이 에이전트 제공자는 지원되지 않습니다. 확인 후 다시 시도하세요!'
|
||||
ErrAgentAccountRequired: '에이전트 계정을 선택한 후 다시 시도하세요.'
|
||||
ErrAgentAccountNotVerified: '계정이 검증되지 않았습니다. 확인 후 다시 시도하세요!'
|
||||
ErrAgentProviderMismatch: '계정 제공자가 일치하지 않습니다. 확인 후 다시 시도하세요!'
|
||||
ErrAgentBaseURLRequired: 'Base URL은 비워 둘 수 없습니다. 확인 후 다시 시도하세요!'
|
||||
ErrAgentApiKeyRequired: 'API Key는 비워 둘 수 없습니다. 확인 후 다시 시도하세요!'
|
||||
ErrAgentComposeRequired: '사용자 정의 compose 내용은 비워 둘 수 없습니다. 확인 후 다시 시도하세요!'
|
||||
ErrAgentIDRequired: '에이전트 ID는 비워 둘 수 없습니다. 확인 후 다시 시도하세요!'
|
||||
ErrAgentAccountIDRequired: '계정 ID는 비워 둘 수 없습니다. 확인 후 다시 시도하세요!'
|
||||
|
||||
#지원
|
||||
Decrypt: '복호화'
|
||||
ErrAgentAccountBound: '계정이 에이전트에 묶여 있습니다'
|
||||
ErrAgentAccountUnavailable: '계정 연결 불가: {{ .err }}'
|
||||
ErrAgentProviderNotSupported: '지원되지 않는 에이전트 공급자'
|
||||
ErrAgentAccountRequired: '먼저 에이전트 계정을 선택하세요'
|
||||
ErrAgentAccountNotVerified: '에이전트 계정 미확인'
|
||||
ErrAgentProviderMismatch: '에이전트 공급자 불일치'
|
||||
ErrAgentBaseURLRequired: '기본 URL 필요'
|
||||
ErrAgentApiKeyRequired: 'API 키 필요'
|
||||
ErrAgentComposeRequired: 'Compose 내용 필요'
|
||||
ErrAgentIDRequired: '에이전트 ID 필요'
|
||||
ErrAgentAccountIDRequired: '계정 ID 필요'
|
||||
ErrAgentLimitReached: '커뮤니티 에디션에서는 AI 에이전트를 최대 {{ .max }}개까지 생성할 수 있으며, Professional 에디션으로 업그레이드하면 수량 제한이 없습니다'
|
||||
Localhost: '로컬 머신'
|
||||
ErrBackupInUsed: '백업 계정이 예약된 작업에 사용되었으므로 삭제할 수 없습니다.'
|
||||
ErrBackupCheck: '백업 계정 테스트 연결에 실패했습니다 {{ .err }}'
|
||||
ErrBackupLocalDelete: '로컬 서버 백업 계정 삭제는 아직 지원되지 않습니다.'
|
||||
ErrBackupLocalCreate: '로컬 서버 백업 계정 생성은 아직 지원되지 않습니다.'
|
||||
|
||||
#앱
|
||||
ErrPortInUsed: '{{ .detail }} 포트가 이미 사용 중입니다!'
|
||||
ErrBackupInUsed: '백업 계정이 예약에 사용 중'
|
||||
ErrBackupCheck: '연결 테스트 실패: {{ .err }}'
|
||||
ErrBackupLocalDelete: '로컬 백업은 삭제할 수 없습니다'
|
||||
ErrBackupLocalCreate: '로컬 백업은 만들 수 없습니다'
|
||||
ErrPortInUsed: '{{ .detail }} 포트가 이미 사용 중입니다'
|
||||
ErrAppLimit: '설치된 애플리케이션 수가 한도를 초과했습니다'
|
||||
ErrNotInstall: '응용 프로그램이 설치되지 않았습니다'
|
||||
ErrPortInOtherApp: '{{ .port }} 포트는 이미 {{ .apps }} 애플리케이션에 의해 사용되고 있습니다!'
|
||||
ErrDbUserNotValid: '기존 데이터베이스, 사용자 이름 및 비밀번호가 일치하지 않습니다!'
|
||||
ErrUpdateBuWebsite: '응용 프로그램이 성공적으로 업데이트되었지만, 웹사이트 구성 파일 수정에 실패했습니다. 구성을 확인하세요! '
|
||||
Err1PanelNetworkFailed: '기본 컨테이너 네트워크 생성에 실패했습니다! {{ .세부 사항 }}'
|
||||
ErrFileParse: '응용 프로그램 docker-compose 파일 구문 분석에 실패했습니다!'
|
||||
ErrPortInOtherApp: '{{ .port }} 포트는 이미 {{ .apps }} 애플리케이션에 의해 사용되고 있습니다'
|
||||
ErrDbUserNotValid: '기존 데이터베이스, 사용자 이름 및 비밀번호가 일치하지 않습니다'
|
||||
ErrUpdateBuWebsite: '응용 프로그램이 성공적으로 업데이트되었지만, 웹사이트 구성 파일 수정에 실패했습니다. 구성을 확인하세요'
|
||||
Err1PanelNetworkFailed: '기본 컨테이너 네트워크 생성에 실패했습니다 {{ .세부 사항 }}'
|
||||
ErrFileParse: '응용 프로그램 docker-compose 파일 구문 분석에 실패했습니다'
|
||||
ErrInstallDirNotFound: '설치 디렉토리가 존재하지 않습니다. 제거를 원하실 경우 강제 제거 를 선택해주세요.'
|
||||
AppStoreIsUpToDate: '앱 스토어가 이미 최신 버전입니다'
|
||||
LocalAppVersionNull: '{{ .name }} 애플리케이션이 버전과 동기화되지 않았습니다! 앱 목록에 추가할 수 없습니다.'
|
||||
LocalAppVersionErr: '{{ .name }} 동기화 버전 {{ .version }}이 실패했습니다! {{ .err }}'
|
||||
LocalAppVersionNull: '{{ .name }} 애플리케이션이 버전과 동기화되지 않았습니다 앱 목록에 추가할 수 없습니다.'
|
||||
LocalAppVersionErr: '{{ .name }} 동기화 버전 {{ .version }}이 실패했습니다 {{ .err }}'
|
||||
ErrFileNotFound: '{{ .name }} 파일이 존재하지 않습니다'
|
||||
ErrFileParseApp: '{{ .name }} 파일 구문 분석에 실패했습니다 {{ .err }}'
|
||||
ErrAppDirNull: '버전 폴더가 존재하지 않습니다'
|
||||
LocalAppErr: '애플리케이션 {{ .name }} 동기화에 실패했습니다! {{ .err }}'
|
||||
LocalAppErr: '애플리케이션 {{ .name }} 동기화에 실패했습니다 {{ .err }}'
|
||||
ErrContainerName: '컨테이너 이름이 이미 존재합니다'
|
||||
ErrCreateHttpClient: '요청 {{ .err }}을(를) 생성하지 못했습니다.'
|
||||
ErrHttpReqTimeOut: '요청 시간이 초과되었습니다 {{ .err }}'
|
||||
@@ -87,64 +79,58 @@ ErrAppBackup: '{{ .name }} 애플리케이션 백업에 실패했습니다 {{ .e
|
||||
ErrVersionTooLow: '현재 1Panel 버전이 너무 낮아 App Store를 업데이트할 수 없습니다. 작동하시기 전에 버전을 업그레이드하세요.'
|
||||
ErrAppNameExist: '응용 프로그램 이름이 이미 존재합니다'
|
||||
AppStoreIsSyncing: 'App Store가 동기화 중입니다. 나중에 다시 시도하세요.'
|
||||
ErrGetCompose: 'docker-compose.yml 파일을 가져오지 못했습니다! {{ .detail }}'
|
||||
ErrGetCompose: 'docker-compose.yml 파일을 가져오지 못했습니다 {{ .detail }}'
|
||||
ErrAppWarn: '비정상적인 상태입니다. 로그를 확인해 주세요.'
|
||||
ErrAppParamKey: '매개변수 {{ .name }} 필드가 비정상입니다.'
|
||||
ErrAppUpgrade: '애플리케이션 {{ .name }} 업그레이드에 실패했습니다 {{ .err }}'
|
||||
AppRecover: '롤백 애플리케이션 {{ .name }}'
|
||||
PullImageStart: '이미지 [{{ .name }}] 가져오기 시작'
|
||||
PullImageSuccess: '이미지 가져오기 성공'
|
||||
AppStoreIsLastVersion: '앱스토어가 이미 최신 버전입니다'
|
||||
AppStoreSyncSuccess: '앱스토어 동기화 성공'
|
||||
SyncAppDetail: '애플리케이션 구성 동기화'
|
||||
AppVersionNotMatch: '{{ .name }} 애플리케이션에 더 높은 1Panel 버전이 필요하므로 동기화를 건너뜁니다.'
|
||||
MoveSiteDir: "웹사이트 디렉토리 변경이 감지되었습니다. OpenResty 웹사이트 디렉토리를 {{ .name }} 로 마이그레이션해야 합니다"
|
||||
MoveSiteDir: '웹사이트 디렉토리 변경이 감지되었습니다. OpenResty 웹사이트 디렉토리를 {{ .name }} 로 마이그레이션해야 합니다'
|
||||
MoveSiteDirSuccess: '웹사이트 디렉토리 마이그레이션 성공'
|
||||
DeleteRuntimePHP: 'PHP 런타임 삭제'
|
||||
CustomAppStoreFileValid: '앱 스토어 패키지는 .tar.gz 형식이어야 합니다.'
|
||||
CustomAppStoreFileValid: '앱 스토어 패키지는.tar.gz 형식이어야 합니다.'
|
||||
PullImageTimeout: '이미지 가져오기 시간 초과, 이미지 가속을 높이거나 다른 이미지 가속으로 변경해 보세요.'
|
||||
ErrAppIsDown: '{{ .name }} 애플리케이션 상태가 비정상적입니다. 확인해 주세요'
|
||||
ErrCustomApps: '설치된 애플리케이션이 있습니다. 먼저 제거해 주세요'
|
||||
ErrCustomRuntimes: '설치된 런타임 환경이 있습니다. 먼저 삭제해 주세요'
|
||||
ErrAppVersionDeprecated: "{{ .name }} 응용 프로그램은 현재 1Panel 버전과 호환되지 않아 건너뛰었습니다"
|
||||
ErrDockerFailed: "Docker의 상태가 비정상입니다. 서비스 상태를 확인하세요"
|
||||
ErrDockerComposeCmdNotFound: "Docker Compose 명령이 없습니다. 호스트 머신에 먼저 이 명령을 설치하세요"
|
||||
UseExistImage: '이미지 가져오기 실패, 기존 이미지 사용'
|
||||
|
||||
#ssh
|
||||
ExportIP: "로그인 IP"
|
||||
ExportArea: "위치"
|
||||
ExportPort: "포트"
|
||||
ExportAuthMode: "로그인 방식"
|
||||
ExportUser: "사용자"
|
||||
ExportStatus: "로그인 상태"
|
||||
ExportDate: "시간"
|
||||
|
||||
#파일
|
||||
ErrAppVersionDeprecated: '{{ .name }} 응용 프로그램은 현재 1Panel 버전과 호환되지 않아 건너뛰었습니다'
|
||||
ErrDockerFailed: 'Docker의 상태가 비정상입니다. 서비스 상태를 확인하세요'
|
||||
ErrDockerComposeCmdNotFound: 'Docker Compose 명령이 없습니다. 호스트 머신에 먼저 이 명령을 설치하세요'
|
||||
UseExistImage: '이미지가 이미 존재하여 기존 이미지를 사용합니다'
|
||||
ErrDatabaseNotFound: '데이터베이스 {{ .name }} 이(가) 존재하지 않습니다'
|
||||
ExportIP: '로그인 IP'
|
||||
ExportArea: '위치'
|
||||
ExportPort: '포트'
|
||||
ExportAuthMode: '로그인 방식'
|
||||
ExportUser: '사용자'
|
||||
ExportStatus: '로그인 상태'
|
||||
ExportDate: '시간'
|
||||
ErrFileCanNotRead: '이 파일은 미리보기를 지원하지 않습니다'
|
||||
ErrFileToLarge: '파일이 10M보다 커서 열 수 없습니다'
|
||||
ErrPathNotFound: '디렉토리가 존재하지 않습니다'
|
||||
ErrMovePathFailed: '대상 경로에는 원래 경로가 포함될 수 없습니다!'
|
||||
ErrLinkPathNotFound: '대상 경로가 존재하지 않습니다!'
|
||||
ErrFileIsExist: '파일이나 폴더가 이미 존재합니다!'
|
||||
ErrMovePathFailed: '대상 경로에는 원래 경로가 포함될 수 없습니다'
|
||||
ErrLinkPathNotFound: '대상 경로가 존재하지 않습니다'
|
||||
ErrFileIsExist: '파일이나 폴더가 이미 존재합니다'
|
||||
ErrFileUpload: '{{ .name }}이 파일 {{ .detail }}을 업로드하지 못했습니다.'
|
||||
ErrFileDownloadDir: '다운로드 폴더가 지원되지 않습니다'
|
||||
ErrCmdNotFound: '{{ .name}} 명령이 존재하지 않습니다. 먼저 호스트에 이 명령을 설치하세요'
|
||||
ErrCmdNotFound: '{{ .name }} 명령이 존재하지 않습니다. 먼저 호스트에 이 명령을 설치하세요'
|
||||
ErrSourcePathNotFound: '소스 디렉토리가 존재하지 않습니다'
|
||||
ErrFavoriteExist: '이 경로는 이미 즐겨찾기되었습니다'
|
||||
ErrInvalidChar: '불법 문자는 허용되지 않습니다'
|
||||
ErrPathNotDelete: '선택한 디렉토리를 삭제할 수 없습니다'
|
||||
ErrLogFileToLarge: "로그 파일이 500MB를 초과하여 열 수 없습니다"
|
||||
FileDropFailed: "파일 {{ .name }} 정리 실패: {{ .err }}"
|
||||
FileDropSuccess: "파일 {{ .name }} 정리 성공, {{ .count }}개 파일 삭제, {{ .size }} 디스크 공간 확보"
|
||||
FileDropSum: "파일 정리 완료, 총 {{ .count }}개 파일 삭제, 총 {{ .size }} 디스크 공간 확보"
|
||||
ErrBadDecrypt: "압축 패키지 암호 해제 비밀번호 오류, 압축 해제 실패, 확인 후 다시 시도하세요!"
|
||||
|
||||
#웹사이트
|
||||
ErrLogFileToLarge: '로그 파일이 500MB를 초과하여 열 수 없습니다'
|
||||
FileDropFailed: '파일 {{ .name }} 정리 실패: {{ .err }}'
|
||||
FileDropSuccess: '파일 {{ .name }} 정리 성공, {{ .count }}개 파일 삭제, {{ .size }} 디스크 공간 확보'
|
||||
FileDropSum: '파일 정리 완료, 총 {{ .count }}개 파일 삭제, 총 {{ .size }} 디스크 공간 확보'
|
||||
ErrBadDecrypt: '압축 패키지 암호 해제 비밀번호 오류, 압축 해제 실패, 확인 후 다시 시도하세요'
|
||||
ErrAliasIsExist: '별칭이 이미 존재합니다'
|
||||
ErrBackupMatch: '백업 파일이 현재 웹사이트 데이터 중 일부 {{ .detail }}와 일치하지 않습니다.'
|
||||
ErrBackupExist: '백업 파일에 있는 소스 데이터의 해당 부분이 존재하지 않습니다 {{ .detail }}'
|
||||
ErrPHPResource: '로컬 운영 환경이 전환을 지원하지 않습니다! '
|
||||
ErrPHPResource: '로컬 운영 환경이 전환을 지원하지 않습니다'
|
||||
ErrPathPermission: '인덱스 디렉토리에서 1000:1000이 아닌 권한을 가진 폴더가 감지되었습니다. 이로 인해 웹사이트에서 액세스 거부 오류가 발생할 수 있습니다. 위의 저장 버튼을 클릭해주세요.'
|
||||
ErrDomainIsUsed: '[{{ .name }}] 웹사이트에서 이미 도메인 이름을 사용하고 있습니다.'
|
||||
ErrDomainFormat: '{{ .name }} 도메인 이름 형식이 올바르지 않습니다'
|
||||
@@ -152,11 +138,11 @@ ErrDefaultAlias: '기본값은 예약된 코드입니다. 다른 코드를 사
|
||||
ErrParentWebsite: '먼저 하위 사이트 {{ .name }}을 삭제해야 합니다.'
|
||||
ErrBuildDirNotFound: '빌드 디렉토리가 존재하지 않습니다'
|
||||
ErrImageNotExist: '운영 환경 {{ .name }} 이미지가 존재하지 않습니다. 운영 환경을 다시 편집하세요.'
|
||||
ErrProxyIsUsed: "로드 밸런싱이 역방향 프록시에 의해 사용되었으므로 삭제할 수 없습니다"
|
||||
ErrSSLValid: '인증서 파일에 문제가 있습니다. 인증서 상태를 확인하세요!'
|
||||
ErrWebsiteDir: "웹사이트 디렉토리 내의 디렉토리를 선택하세요."
|
||||
ErrComposerFileNotFound: "composer.json 파일이 존재하지 않습니다"
|
||||
ErrRuntimeNoPort: "런타임 환경에 포트가 설정되지 않았습니다. 먼저 런타임 환경을 편집하세요."
|
||||
ErrProxyIsUsed: '로드 밸런싱이 역방향 프록시에 의해 사용되었으므로 삭제할 수 없습니다'
|
||||
ErrSSLValid: '인증서 파일에 문제가 있습니다. 인증서 상태를 확인하세요'
|
||||
ErrWebsiteDir: '웹사이트 디렉토리 내의 디렉토리를 선택하세요.'
|
||||
ErrComposerFileNotFound: 'composer.json 파일이 존재하지 않습니다'
|
||||
ErrRuntimeNoPort: '런타임 환경에 포트가 설정되지 않았습니다. 먼저 런타임 환경을 편집하세요.'
|
||||
Status: '상태'
|
||||
start: '시작'
|
||||
stop: '중지'
|
||||
@@ -166,14 +152,12 @@ pause: '일시 정지'
|
||||
unpause: '재개'
|
||||
remove: '삭제'
|
||||
delete: '삭제'
|
||||
ErrDefaultWebsite: '기본 웹사이트가 이미 설정되었습니다. 설정하기 전에 취소하세요!'
|
||||
ErrDefaultWebsite: '기본 웹사이트가 이미 설정되었습니다. 설정하기 전에 취소하세요'
|
||||
SSL: '인증서'
|
||||
Set: '설정'
|
||||
|
||||
#SSL인증
|
||||
ErrSSLCannotDelete: '{{ .name }} 인증서는 웹사이트에서 사용 중이므로 삭제할 수 없습니다.'
|
||||
ErrAccountCannotDelete: '계정이 인증서와 연결되어 있어 삭제할 수 없습니다.'
|
||||
ErrSSLApply: '인증서 갱신이 성공했으나, openresty 재로드에 실패했습니다. 구성을 확인해 주세요!'
|
||||
ErrSSLApply: '인증서 갱신이 성공했으나, openresty 재로드에 실패했습니다. 구성을 확인해 주세요'
|
||||
ErrEmailIsExist: '사서함이 이미 존재합니다'
|
||||
ErrSSLKeyNotFound: '개인 키 파일이 존재하지 않습니다'
|
||||
ErrSSLCertificateNotFound: '인증서 파일이 존재하지 않습니다'
|
||||
@@ -181,12 +165,12 @@ ErrSSLKeyFormat: '개인 키 파일 검증에 실패했습니다'
|
||||
ErrSSLCertificateFormat: '인증서 파일 형식이 올바르지 않습니다. pem 형식을 사용하세요.'
|
||||
ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid 또는 EabHmacKey는 비워둘 수 없습니다'
|
||||
ErrOpenrestyNotFound: 'Http 모드를 사용하려면 먼저 Openresty를 설치해야 합니다.'
|
||||
ApplySSLStart: '인증서 신청 시작, 도메인 이름 [{{ .domain }}] 신청 방법 [{{ .type }}] '
|
||||
ApplySSLStart: '인증서 신청 시작, 도메인 이름 [{{ .domain }}] 신청 방법 [{{ .type }}]'
|
||||
dnsAccount: 'DNS 자동'
|
||||
dnsManual: 'DNS 매뉴얼'
|
||||
http: 'HTTP'
|
||||
ApplySSLFailed: '[{{ .domain }}] 인증서 신청이 실패했습니다. {{ .detail }} '
|
||||
ApplySSLSuccess: '[{{ .domain }}] 인증서 신청이 성공적으로 완료되었습니다! ! '
|
||||
ApplySSLFailed: '[{{ .domain }}] 인증서 신청이 실패했습니다. {{ .detail }}'
|
||||
ApplySSLSuccess: '[{{ .domain }}] 인증서 신청이 성공적으로 완료되었습니다'
|
||||
DNSAccountName: 'DNS 계정 [{{ .name }}] 공급업체 [{{ .type }}]'
|
||||
PushDirLog: '인증서가 [{{ .path }}] {{ .status }} 디렉토리로 푸시되었습니다.'
|
||||
ErrDeleteCAWithSSL: '현재 조직에는 발급된 인증서가 있어 삭제할 수 없습니다.'
|
||||
@@ -201,97 +185,79 @@ ExecShellSuccess: '스크립트 실행 성공'
|
||||
StartUpdateSystemSSL: '시스템 인증서 업데이트 시작'
|
||||
UpdateSystemSSLSuccess: '시스템 인증서 업데이트가 성공적으로 완료되었습니다.'
|
||||
ErrWildcardDomain: 'HTTP 모드에서 와일드카드 도메인 이름 인증서를 신청할 수 없습니다'
|
||||
ErrApplySSLCanNotDelete: "신청 중인 인증서 {{.name}}는 삭제할 수 없습니다. 나중에 다시 시도해 주세요."
|
||||
StartPushSSLToNode: "인증서를 노드로 푸시 시작"
|
||||
PushSSLToNodeFailed: "노드로 인증서 푸시 실패: {{ .err }}"
|
||||
PushSSLToNodeSuccess: "노드로 인증서 푸시 성공"
|
||||
|
||||
#마이SQL
|
||||
ErrApplySSLCanNotDelete: '신청 중인 인증서 {{ .name }}는 삭제할 수 없습니다. 나중에 재시도'
|
||||
StartPushSSLToNode: '인증서를 노드로 푸시 시작'
|
||||
PushSSLToNodeFailed: '노드로 인증서 푸시 실패: {{ .err }}'
|
||||
PushSSLToNodeSuccess: '노드로 인증서 푸시 성공'
|
||||
ErrUserIsExist: '현재 사용자가 이미 존재합니다. 다시 입력하세요'
|
||||
ErrDatabaseIsExist: '현재 데이터베이스가 이미 존재합니다. 다시 입력하세요'
|
||||
ErrExecTimeOut: 'SQL 실행 시간이 초과되었습니다. 데이터베이스를 확인하십시오.'
|
||||
ErrRemoteExist: '이 이름을 가진 원격 데이터베이스가 이미 존재합니다. 수정하고 다시 시도하세요'
|
||||
ErrLocalExist: '이름이 로컬 데이터베이스에 이미 존재합니다. 이름을 수정하고 다시 시도하세요'
|
||||
RemoteBackup: "원격 데이터베이스를 백업하려면 먼저 이미지 {{ .name }}을(를) 사용하여 로컬 컨테이너 데이터베이스 서비스를 시작해야 합니다. 잠시만 기다려 주세요..."
|
||||
RemoteRecover: "원격 데이터베이스를 복원하려면 먼저 이미지 {{ .name }}을(를) 사용하여 로컬 컨테이너 데이터베이스 서비스를 시작해야 합니다. 잠시만 기다려 주세요..."
|
||||
Arg: "인수"
|
||||
|
||||
#레디스
|
||||
RemoteBackup: '원격 데이터베이스를 백업하려면 먼저 이미지 {{ .name }}을(를) 사용하여 로컬 컨테이너 데이터베이스 서비스를 시작해야 합니다. 잠시만 기다려 주세요...'
|
||||
RemoteRecover: '원격 데이터베이스를 복원하려면 먼저 이미지 {{ .name }}을(를) 사용하여 로컬 컨테이너 데이터베이스 서비스를 시작해야 합니다. 잠시만 기다려 주세요...'
|
||||
Arg: '인수'
|
||||
ErrTypeOfRedis: '복구 파일 유형이 현재 지속성 방법과 일치하지 않습니다. 수정하고 다시 시도하세요'
|
||||
|
||||
#컨테이너
|
||||
ErrInUsed: "{{ .detail }}(이)가 사용 중이어서 삭제할 수 없습니다!"
|
||||
ErrObjectInUsed: "이 객체는 사용 중이어서 삭제할 수 없습니다!"
|
||||
ErrObjectBeDependent: "이 이미지는 다른 이미지에 의존되어 있어 삭제할 수 없습니다!"
|
||||
ErrPortRules: '포트 번호가 일치하지 않습니다. 다시 입력하세요!'
|
||||
ErrInUsed: '{{ .detail }}(이)가 사용 중이어서 삭제할 수 없습니다'
|
||||
ErrObjectInUsed: '이 객체는 사용 중이어서 삭제할 수 없습니다'
|
||||
ErrObjectBeDependent: '이 이미지는 다른 이미지에 의존되어 있어 삭제할 수 없습니다'
|
||||
ErrPortRules: '포트 번호가 일치하지 않습니다. 다시 입력하세요'
|
||||
ErrPgImagePull: '이미지 풀링 시간이 초과되었습니다. 이미지 가속을 구성하거나 {{ .name }} 이미지를 수동으로 풀링한 다음 다시 시도하세요.'
|
||||
PruneHelper: "이번 정리 {{ .name }}가 디스크 공간 {{ .size }}을(를) 확보했습니다"
|
||||
ImageRemoveHelper: "이미지 {{ .name }} 삭제, {{ .size }} 디스크 공간 확보"
|
||||
BuildCache: "빌드 캐시"
|
||||
Volume: "스토리지 볼륨"
|
||||
Network: "네트워크"
|
||||
PruneStart: "정리 중입니다. 잠시만 기다려주세요..."
|
||||
|
||||
#실행 시간
|
||||
ErrFileNotExist: '{{ .detail }} 파일이 존재하지 않습니다! 소스 파일의 무결성을 확인하세요!'
|
||||
PruneHelper: '이번 정리 {{ .name }}가 디스크 공간 {{ .size }}을(를) 확보했습니다'
|
||||
ImageRemoveHelper: '이미지 {{ .name }} 삭제, {{ .size }} 디스크 공간 확보'
|
||||
BuildCache: '빌드 캐시'
|
||||
Volume: '스토리지 볼륨'
|
||||
Network: '네트워크'
|
||||
PruneStart: '정리 중입니다. 잠시만 기다려주세요...'
|
||||
ErrFileNotExist: '{{ .detail }} 파일이 존재하지 않습니다 소스 파일의 무결성을 확인하세요'
|
||||
ErrImageBuildErr: '이미지 빌드 실패'
|
||||
ErrImageExist: "이미지가 이미 존재합니다! 이미지 이름을 수정하세요."
|
||||
ErrImageExist: '이미지가 이미 존재합니다 이미지 이름을 수정하세요.'
|
||||
ErrDelWithWebsite: '운영 환경이 이미 웹사이트와 연결되어 있어 삭제할 수 없습니다'
|
||||
ErrRuntimeStart: '시작 실패'
|
||||
ErrPackageJsonNotFound: 'package.json 파일이 존재하지 않습니다'
|
||||
ErrScriptsNotFound: 'package.json에서 스크립트 구성 항목을 찾을 수 없습니다.'
|
||||
ErrContainerNameNotFound: '컨테이너 이름을 가져올 수 없습니다. .env 파일을 확인하세요.'
|
||||
ErrNodeModulesNotFound: 'node_modules 폴더가 없습니다! 런타임 환경을 편집하거나 런타임 환경이 성공적으로 시작될 때까지 기다리십시오'
|
||||
ErrContainerNameNotFound: '컨테이너 이름을 가져올 수 없습니다..env 파일을 확인하세요.'
|
||||
ErrNodeModulesNotFound: 'node_modules 폴더가 없습니다 런타임 환경을 편집하거나 런타임 환경이 성공적으로 시작될 때까지 기다리십시오'
|
||||
ErrContainerNameIsNull: '컨테이너 이름이 존재하지 않습니다'
|
||||
ErrPHPPortIsDefault: "9000 포트는 기본 포트입니다. 수정 후 다시 시도하세요"
|
||||
ErrPHPRuntimePortFailed: "포트 {{ .name }} 는 현재 런타임 환경에서 이미 사용 중입니다. 수정 후 다시 시도하세요"
|
||||
|
||||
#도구
|
||||
ErrPHPPortIsDefault: '9000 포트는 기본 포트입니다. 수정 후 다시 시도하세요'
|
||||
ErrPHPRuntimePortFailed: '포트 {{ .name }} 는 현재 런타임 환경에서 이미 사용 중입니다. 수정 후 다시 시도하세요'
|
||||
ErrConfigNotFound: '구성 파일이 존재하지 않습니다'
|
||||
ErrConfigParse: '구성 파일 형식이 올바르지 않습니다'
|
||||
ErrConfigIsNull: '구성 파일은 비어 있을 수 없습니다'
|
||||
ErrConfigDirNotFound: '실행 디렉토리가 존재하지 않습니다'
|
||||
ErrConfigAlreadyExist: '같은 이름의 구성 파일이 이미 존재합니다'
|
||||
ErrUserFindErr: '사용자 {{ .name }} 검색에 실패했습니다 {{ .err }}'
|
||||
|
||||
#크론잡
|
||||
CutWebsiteLogSuccess: '{{ .name }} 웹사이트 로그가 성공적으로 잘렸습니다. 백업 경로 {{ .path }}'
|
||||
HandleShell: '스크립트 {{ .name }} 실행'
|
||||
HandleCurl: "URL {{ .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: "WAF IP 그룹을 찾을 수 없습니다. [고급 기능 - WAF - 블랙/화이트 목록 - IP 그룹]으로 이동하여 원격 다운로드 방식으로 IP 그룹을 추가하십시오."
|
||||
|
||||
#도구상자
|
||||
ErrNotExistUser: '현재 사용자가 존재하지 않습니다. 수정한 후 다시 시도하세요!'
|
||||
ErrBanAction: '설정에 실패했습니다. 현재 {{ .name }} 서비스를 사용할 수 없습니다. 확인하고 다시 시도하세요!'
|
||||
ErrClamdscanNotFound: 'clamdscan 명령이 감지되지 않았습니다. 설명서를 참조하여 설치하세요!'
|
||||
TaskSwapSet: "Swap 설정"
|
||||
SetSwap: "Swap 설정 {{ .path }} - {{ .size }}"
|
||||
CreateSwap: "Swap 파일 생성"
|
||||
FormatSwap: "Swap 파일 포맷"
|
||||
EnableSwap: "Swap 활성화"
|
||||
|
||||
#tamper
|
||||
CleanTamperSetting: "히스토리 보호 설정 정리"
|
||||
SetTamperWithRules: "규칙에 따라 디렉토리 보호 시작"
|
||||
ProtectDir: "디렉토리 보호 {{ .name }}"
|
||||
IgnoreFile: "파일 보호 {{ .name }}"
|
||||
TamperSetSuccessful: "보호 설정 완료, 다음 디렉토리 모니터링 시작:"
|
||||
|
||||
#와프
|
||||
Upload: '업로드'
|
||||
IgnoreBackupErr: '백업 실패, 오류: {{ .detail }}, 이 오류를 무시합니다...'
|
||||
IgnoreUploadErr: '업로드 실패, 오류: {{ .detail }}, 이 오류를 무시합니다...'
|
||||
LoadBackupFailed: '백업 계정 연결 획득 실패, 오류: {{ .detail }}'
|
||||
InExecuting: '현재 작업이 실행 중입니다. 중복 실행하지 마세요'
|
||||
NoSuchResource: '데이터베이스에서 백업 내용을 찾을 수 없어 건너뜁니다...'
|
||||
CleanLog: '로그 정리'
|
||||
CleanLogByName: '{{ .name }} 로그 정리'
|
||||
WafIpGroupNotFound: 'WAF IP 그룹을 찾을 수 없습니다. [고급 기능 - WAF - 블랙/화이트 목록 - IP 그룹]으로 이동하여 원격 다운로드 방식으로 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: '보호 설정 완료, 다음 디렉토리 모니터링 시작:'
|
||||
ErrScope: '이 구성을 수정하는 것은 지원되지 않습니다'
|
||||
ErrStateChange: '상태 변경에 실패했습니다'
|
||||
ErrRuleExist: '규칙이 이미 존재합니다'
|
||||
@@ -299,7 +265,7 @@ ErrRuleNotExist: '규칙이 존재하지 않습니다'
|
||||
ErrParseIP: '잘못된 IP 형식'
|
||||
ErrDefaultIP: '기본값은 예약된 이름입니다. 다른 이름으로 변경해 주세요'
|
||||
ErrGroupInUse: 'IP 그룹이 블랙리스트/화이트리스트에 사용 중이므로 삭제할 수 없습니다.'
|
||||
ErrIPGroupAclUse: "IP 그룹은 웹사이트 {{ .name }} 의 사용자 정의 규칙에 사용되므로 삭제할 수 없습니다"
|
||||
ErrIPGroupAclUse: 'IP 그룹은 웹사이트 {{ .name }} 의 사용자 정의 규칙에 사용되므로 삭제할 수 없습니다'
|
||||
ErrGroupExist: 'IP 그룹 이름이 이미 존재합니다'
|
||||
ErrIPRange: '잘못된 IP 범위'
|
||||
ErrIPExist: 'IP가 이미 존재합니다'
|
||||
@@ -310,10 +276,10 @@ xss: 'XSS'
|
||||
phpExec: 'PHP 스크립트 실행'
|
||||
oneWordTrojan: '한 단어 트로이'
|
||||
appFilter: '위험한 디렉토리 필터링 적용'
|
||||
webshell: '웹쉘'
|
||||
webShell: '웹쉘'
|
||||
args: '매개변수 규칙'
|
||||
protocolFilter: '프로토콜 필터링'
|
||||
javaFileter: 'Java 위험 파일 필터'
|
||||
javaFilter: 'Java 위험 파일 필터'
|
||||
scannerFilter: '스캐너 필터'
|
||||
escapeFilter: '탈출 필터'
|
||||
customRule: '사용자 정의 규칙'
|
||||
@@ -343,10 +309,9 @@ ErrDBNotExist: '데이터베이스가 존재하지 않습니다'
|
||||
allow: '허용하다'
|
||||
deny: '거부하다'
|
||||
OpenrestyNotFound: 'Openresty가 설치되지 않았습니다'
|
||||
remoteIpIsNull: "IP 목록이 비어 있습니다"
|
||||
OpenrestyVersionErr: "Openresty 버전이 너무 낮습니다. Openresty를 1.27.1.2-2-2-focal로 업그레이드하세요"
|
||||
|
||||
#일
|
||||
remoteIpIsNull: 'IP 목록이 비어 있습니다'
|
||||
OpenrestyVersionErr: 'Openresty 버전이 너무 낮습니다. Openresty를 1.27.1.2-2-2-focal로 업그레이드하세요'
|
||||
ErrFileTooLarge: '파일이 1MB를 초과하여 업로드할 수 없습니다'
|
||||
TaskStart: '[START] {{ .name }} 작업이 시작됩니다.'
|
||||
TaskEnd: '{{ .name }} 작업이 완료되었습니다 [완료]'
|
||||
TaskFailed: '{{ .name }} 작업이 실패했습니다'
|
||||
@@ -362,7 +327,7 @@ TaskDelete: '삭제'
|
||||
TaskUpgrade: '업그레이드'
|
||||
TaskUpdate: '업데이트'
|
||||
TaskRestart: '다시 시작'
|
||||
TaskProtect: "보호"
|
||||
TaskProtect: '보호'
|
||||
TaskBackup: '백업'
|
||||
TaskRecover: '복구'
|
||||
TaskRollback: '롤백'
|
||||
@@ -370,10 +335,10 @@ TaskPull: '당기기'
|
||||
TaskCommit: '커밋'
|
||||
TaskBuild: '빌드'
|
||||
TaskPush: '푸시'
|
||||
TaskClean: "정리"
|
||||
TaskClean: '정리'
|
||||
TaskHandle: '실행'
|
||||
TaskImport: "가져오기"
|
||||
TaskExport: "내보내기"
|
||||
TaskImport: '가져오기'
|
||||
TaskExport: '내보내기'
|
||||
Website: '웹사이트'
|
||||
App: '애플리케이션'
|
||||
Runtime: '런타임 환경'
|
||||
@@ -393,7 +358,7 @@ Start: '시작'
|
||||
Run: '시작'
|
||||
Stop: '정지'
|
||||
Image: '거울'
|
||||
Compose : '오케스트레이션'
|
||||
Compose: '오케스트레이션'
|
||||
Container: '컨테이너'
|
||||
AppLink: '연결된 애플리케이션'
|
||||
EnableSSL: 'HTTPS 활성화'
|
||||
@@ -405,18 +370,12 @@ RuntimeExtension: '런타임 환경 확장'
|
||||
TaskIsExecuting: '작업이 실행 중입니다'
|
||||
CustomAppstore: '사용자 정의 애플리케이션 웨어하우스'
|
||||
TaskExec: '실행'
|
||||
TaskBatch: "일괄 작업"
|
||||
TaskBatch: '일괄 작업'
|
||||
FileConvert: '파일 형식 변환'
|
||||
|
||||
# task - clam
|
||||
Clamscan: "{{ .name }} 스캔"
|
||||
TaskScan: "스캔"
|
||||
|
||||
# 작업 - ai
|
||||
Clamscan: '{{ .name }} 스캔'
|
||||
TaskScan: '스캔'
|
||||
OllamaModelPull: 'Ollama 모델 {{ .name }}을(를) 끌어오세요'
|
||||
OllamaModelSize: 'Ollama 모델 {{ .name }}의 크기를 가져옵니다'
|
||||
|
||||
# 작업-스냅샷
|
||||
Snapshot: '스냅샷'
|
||||
SnapDBInfo: '1Panel 데이터베이스 정보 쓰기'
|
||||
SnapCopy: '파일 및 디렉토리 {{ .name }} 복사'
|
||||
@@ -442,7 +401,6 @@ SnapCompressSize: '스냅샷 파일 크기 {{ .name }}'
|
||||
SnapUpload: '스냅샷 파일 업로드'
|
||||
SnapUploadTo: '스냅샷 파일을 {{ .name }}에 업로드'
|
||||
SnapUploadRes: '스냅샷 파일을 {{ .name }}에 업로드'
|
||||
|
||||
SnapshotRecover: '스냅샷 복원'
|
||||
RecoverDownload: '스냅샷 파일 다운로드'
|
||||
Download: '다운로드'
|
||||
@@ -450,10 +408,10 @@ RecoverDownloadAccount: '스냅샷 다운로드 백업 계정 {{ .name }} 가져
|
||||
RecoverDecompress: '스냅샷 압축 파일 압축 해제'
|
||||
Decompress: '감압'
|
||||
BackupBeforeRecover: '스냅샷 전에 시스템 관련 데이터 백업'
|
||||
Readjson: '스냅샷에서 Json 파일을 읽습니다'
|
||||
ReadjsonPath: '스냅샷의 Json 파일 경로 가져오기'
|
||||
ReadjsonContent: 'Json 파일 읽기'
|
||||
ReadjsonMarshal: 'Json 이스케이프 처리'
|
||||
ReadJson: '스냅샷에서 Json 파일을 읽습니다'
|
||||
ReadJsonPath: '스냅샷의 Json 파일 경로 가져오기'
|
||||
ReadJsonContent: 'Json 파일 읽기'
|
||||
ReadJsonMarshal: 'Json 이스케이프 처리'
|
||||
RecoverApp: '설치된 앱 복원'
|
||||
RecoverWebsite: '웹사이트 디렉토리 복구'
|
||||
RecoverAppImage: '스냅샷 이미지 백업 복원'
|
||||
@@ -467,9 +425,6 @@ RecoverDaemonJson: '컨테이너 구성 daemon.json 파일 복원'
|
||||
RecoverDBData: '데이터베이스 데이터 복구'
|
||||
RecoverBackups: '로컬 백업 디렉토리 복원'
|
||||
RecoverPanelData: '복구 데이터 디렉토리'
|
||||
|
||||
# 작업 - 컨테이너
|
||||
ContainerNewCliet: 'Docker 클라이언트 초기화'
|
||||
ContainerImagePull: '컨테이너 이미지 {{ .name }} 가져오기'
|
||||
ContainerRemoveOld: '원래 컨테이너 {{ .name }} 제거'
|
||||
ContainerImageCheck: '이미지가 정상적으로 당겨졌는지 확인'
|
||||
@@ -478,22 +433,13 @@ ContainerRecreate: '컨테이너 업데이트에 실패했습니다. 이제 원
|
||||
ContainerCreate: '새로운 컨테이너 {{ .name }}를 만듭니다'
|
||||
ContainerCreateFailed: '컨테이너 생성에 실패했습니다. 실패한 컨테이너를 삭제하세요'
|
||||
ContainerStartCheck: '컨테이너가 시작되었는지 확인'
|
||||
|
||||
# 작업 - 이미지
|
||||
ImageBuild: '이미지 빌드'
|
||||
ImageBuildStdoutCheck: '이미지 출력 콘텐츠 구문 분석'
|
||||
ImageBuildRes: '이미지 빌드 출력: {{ .name }}'
|
||||
ImagePull: '이미지 가져오기'
|
||||
ImageRepoAuthFromDB: '데이터베이스에서 저장소 인증 정보 가져오기'
|
||||
ImaegPullRes: '이미지 풀 출력: {{ .name }}'
|
||||
ImagePush: '이미지 푸시'
|
||||
ImageRenameTag: '이미지 태그 수정'
|
||||
ImageNewTag: '새로운 이미지 태그 {{ .name }}'
|
||||
ImaegPushRes: '이미지 푸시 출력: {{ .name }}'
|
||||
ComposeCreate: '작곡 만들기'
|
||||
ComposeCreateRes: 'Compose 생성 출력: {{ .name }}'
|
||||
|
||||
# 작업 - 웹사이트
|
||||
BackupNginxConfig: '웹사이트 OpenResty 구성 파일 백업'
|
||||
CompressFileSuccess: '디렉토리 압축이 성공했습니다. {{ .name }}으로 압축되었습니다.'
|
||||
CompressDir: '압축 디렉토리'
|
||||
@@ -504,40 +450,27 @@ websiteDir: '웹사이트 디렉토리'
|
||||
RecoverFailedStartRollBack: '복구 실패, 롤백 시작'
|
||||
AppBackupFileIncomplete: '백업 파일이 불완전하며 app.json 또는 app.tar.gz 파일이 없습니다.'
|
||||
AppAttributesNotMatch: '애플리케이션 유형 또는 이름이 일치하지 않습니다'
|
||||
|
||||
#알리다
|
||||
ErrAlert: '경고 메시지의 형식이 올바르지 않습니다. 확인하고 다시 시도하세요!'
|
||||
ErrAlertPush: '알림 정보를 푸시하는 중 오류가 발생했습니다. 확인하고 다시 시도하세요!'
|
||||
ErrAlertSave: '알람 정보를 저장하는 중 오류가 발생했습니다. 확인하고 다시 시도하세요!'
|
||||
ErrAlertSync: '알람 정보 동기화 오류입니다. 확인하고 다시 시도하세요!'
|
||||
ErrAlertRemote: '알람 메시지 원격 오류, 확인하고 다시 시도하세요!'
|
||||
|
||||
#task - runtime
|
||||
ErrInstallExtension: "이미 설치 작업이 진행 중입니다. 작업이 완료될 때까지 기다려 주세요."
|
||||
|
||||
# alert mail template
|
||||
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 }} 패널, 최근 {{ .time }}분간 {{ .name }} 평균 사용률은 {{ .used }}입니다. 자세한 내용은 패널에 로그인하십시오."
|
||||
PanelVersionAlert: "귀하의 {{ .node }}{{ .ip }} 패널, 최신 버전으로 업그레이드할 수 있습니다. 자세한 내용은 패널에 로그인하십시오."
|
||||
PanelPwdExpirationAlert: "귀하의 {{ .node }}{{ .ip }} 패널, 패널 비밀번호가 {{ .day }}일 후에 만료됩니다. 자세한 내용은 패널에 로그인하십시오."
|
||||
CommonAlert: "귀하의 {{ .node }}{{ .ip }} 패널, {{ .msg }}。자세한 내용은 패널에 로그인하십시오."
|
||||
NodeExceptionAlert: "귀하의 {{ .node }}{{ .ip }} 패널, {{ .num }}개의 노드에 이상이 있습니다. 자세한 내용은 패널에 로그인하십시오."
|
||||
LicenseExceptionAlert: "귀하의 {{ .node }}{{ .ip }} 패널, {{ .num }}개의 라이센스에 이상이 있습니다. 자세한 내용은 패널에 로그인하십시오."
|
||||
SSHAndPanelLoginAlert: "귀하의 {{ .node }}{{ .ip }} 패널, {{ .loginIp }}에서의 {{ .name }} 로그인에 이상이 있습니다. 자세한 내용은 패널에 로그인하십시오."
|
||||
|
||||
#disk
|
||||
DeviceNotFound: "장치 {{ .name }} 을(를) 찾을 수 없습니다"
|
||||
DeviceIsMounted: "장치 {{ .name }} 이(가) 마운트되었습니다, 먼저 마운트 해제하세요"
|
||||
PartitionDiskErr: "파티션 분할에 실패했습니다, {{ .err }}"
|
||||
FormatDiskErr: "디스크 포맷에 실패했습니다, {{ .err }}"
|
||||
MountDiskErr: "디스크 마운트에 실패했습니다, {{ .err }}"
|
||||
UnMountDiskErr: "디스크 마운트 해제에 실패했습니다, {{ .err }}"
|
||||
XfsNotFound: "xfs 파일 시스템이 감지되지 않았습니다, 먼저 xfsprogs 를 설치하세요"
|
||||
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 }} 패널, 최근 {{ .time }}분간 {{ .name }} 평균 사용률은 {{ .used }}입니다. 자세한 내용은 패널에 로그인하십시오.'
|
||||
PanelVersionAlert: '귀하의 {{ .node }}{{ .ip }} 패널, 최신 버전으로 업그레이드할 수 있습니다. 자세한 내용은 패널에 로그인하십시오.'
|
||||
PanelPwdExpirationAlert: '귀하의 {{ .node }}{{ .ip }} 패널, 패널 비밀번호가 {{ .day }}일 후에 만료됩니다. 자세한 내용은 패널에 로그인하십시오.'
|
||||
CommonAlert: '귀하의 {{ .node }}{{ .ip }} 패널, {{ .msg }}。자세한 내용은 패널에 로그인하십시오.'
|
||||
NodeExceptionAlert: '귀하의 {{ .node }}{{ .ip }} 패널, {{ .num }}개의 노드에 이상이 있습니다. 자세한 내용은 패널에 로그인하십시오.'
|
||||
LicenseExceptionAlert: '귀하의 {{ .node }}{{ .ip }} 패널, {{ .num }}개의 라이센스에 이상이 있습니다. 자세한 내용은 패널에 로그인하십시오.'
|
||||
SSHAndPanelLoginAlert: '귀하의 {{ .node }}{{ .ip }} 패널, {{ .loginIp }}에서의 {{ .name }} 로그인에 이상이 있습니다. 자세한 내용은 패널에 로그인하십시오.'
|
||||
DeviceNotFound: '장치 {{ .name }} 을(를) 찾을 수 없습니다'
|
||||
DeviceIsMounted: '장치 {{ .name }} 이(가) 마운트되었습니다, 먼저 마운트 해제하세요'
|
||||
PartitionDiskErr: '파티션 분할에 실패했습니다, {{ .err }}'
|
||||
FormatDiskErr: '디스크 포맷에 실패했습니다, {{ .err }}'
|
||||
MountDiskErr: '디스크 마운트에 실패했습니다, {{ .err }}'
|
||||
XfsNotFound: 'xfs 파일 시스템이 감지되지 않았습니다, 먼저 xfsprogs 를 설치하세요'
|
||||
|
||||
+173
-240
@@ -1,83 +1,72 @@
|
||||
ErrInvalidParams: 'Permintaan ralat parameter: {{ .detail }}'
|
||||
ErrTokenParse: 'Ralat penjanaan token: {{ .detail }}'
|
||||
ErrInitialPassword: 'Kata laluan asal tidak betul'
|
||||
ErrInternalServer: 'Ralat pelayan dalaman: {{ .detail }}'
|
||||
ErrInvalidParams: 'Permintaan tidak sah: {{ .detail }}'
|
||||
ErrTokenParse: 'Token tidak sah: {{ .detail }}'
|
||||
ErrInitialPassword: 'Kata laluan asal salah'
|
||||
ErrInternalServer: 'Ralat pelayan: {{ .detail }}'
|
||||
ErrRecordExist: 'Rekod sudah wujud'
|
||||
ErrRecordNotFound: 'Rekod tidak ditemui'
|
||||
ErrStructTransform: 'Penukaran jenis gagal: {{ .err }}'
|
||||
ErrNotLogin: 'Pengguna tidak log masuk: {{ .detail }}'
|
||||
ErrPasswordExpired: 'Kata laluan semasa telah tamat tempoh: {{ .detail }}'
|
||||
ErrNotSupportType: 'Sistem tidak menyokong jenis semasa: {{ .name }}'
|
||||
ErrProxy: 'Ralat permintaan, sila semak status nod: {{ .detail }}'
|
||||
ErrApiConfigStatusInvalid: 'Akses kepada antara muka API adalah dilarang: {{ .detail }}'
|
||||
ErrApiConfigKeyInvalid: 'Ralat kunci antara muka API: {{ .detail }}'
|
||||
ErrApiConfigIPInvalid: 'IP yang digunakan untuk memanggil antara muka API tiada dalam senarai putih: {{ .detail }}'
|
||||
ErrApiConfigDisable: 'Antara muka ini melarang penggunaan panggilan antara muka API: {{ .detail }}'
|
||||
ErrApiConfigKeyTimeInvalid: 'Ralat cap masa antara muka API: {{ .detail }}'
|
||||
StartPushSSLToNode: "Mula menolak sijil ke nod"
|
||||
PushSSLToNodeFailed: "Gagal menolak sijil ke nod: {{ .err }}"
|
||||
PushSSLToNodeSuccess: "Berjaya menolak sijil ke nod"
|
||||
ErrShutDown: "Arahan dihentikan secara manual!"
|
||||
|
||||
ErrMinQuickJump: "Sila tetapkan sekurang-kurangnya satu entri lompat pantas!"
|
||||
ErrMaxQuickJump: "Anda boleh menetapkan sehingga empat entri lompat pantas!"
|
||||
|
||||
#biasa
|
||||
ErrStructTransform: 'Ralat penukaran: {{ .err }}'
|
||||
ErrNotLogin: 'Belum log masuk: {{ .detail }}'
|
||||
ErrPasswordExpired: 'Kata laluan tamat: {{ .detail }}'
|
||||
ErrNotSupportType: 'Jenis tidak disokong: {{ .name }}'
|
||||
ErrProxy: 'Permintaan gagal: {{ .detail }}'
|
||||
ErrApiConfigStatusInvalid: 'API dilumpuhkan: {{ .detail }}'
|
||||
ErrApiConfigKeyInvalid: 'Kunci API tidak sah: {{ .detail }}'
|
||||
ErrApiConfigIPInvalid: 'IP tidak dibenarkan: {{ .detail }}'
|
||||
ErrApiConfigDisable: 'API tidak dibenarkan: {{ .detail }}'
|
||||
ErrApiConfigKeyTimeInvalid: 'Cap masa tidak sah: {{ .detail }}'
|
||||
ErrShutDown: 'Arahan diberhentikan manual'
|
||||
ErrMinQuickJump: 'Tambah sekurang-kurangnya satu pintasan pantas'
|
||||
ErrMaxQuickJump: 'Maksimum 4 pintasan pantas'
|
||||
ErrUsernameIsExist: 'Nama pengguna sudah wujud'
|
||||
ErrNameIsExist: 'Nama sudah wujud'
|
||||
ErrDemoEnvironment: 'Pelayan demo, operasi ini dilarang!'
|
||||
ErrCmdTimeout: 'Pelaksanaan arahan tamat masa!'
|
||||
ErrCmdIllegal: 'Terdapat aksara yang menyalahi undang-undang dalam perintah pelaksanaan, sila ubah suainya dan cuba lagi!'
|
||||
ErrPortExist: '{{ .port }} port sudah diduduki oleh {{ .type }} [{{ .name }}]'
|
||||
ErrDemoEnvironment: 'Tidak tersedia dalam demo'
|
||||
ErrCmdTimeout: 'Arahan tamat masa'
|
||||
ErrCmdIllegal: 'Arahan ada aksara tidak sah'
|
||||
ErrPortExist: 'Port {{ .port }} sudah digunakan oleh {{ .type }} [{{ .name }}]'
|
||||
TYPE_APP: 'Aplikasi'
|
||||
TYPE_RUNTIME: 'Persekitaran masa jalan'
|
||||
TYPE_DOMAIN: 'Nama Domain'
|
||||
ErrTypePort: Format 'Port {{ .name }} tidak betul'
|
||||
ErrTypePort: 'Format ''Port {{ .name }} tidak betul'''
|
||||
ErrTypePortRange: 'Julat port perlu antara 1-65535'
|
||||
Success: 'Kejayaan'
|
||||
Failed: 'Gagal'
|
||||
SystemRestart: 'Tugas terganggu kerana sistem mula semula'
|
||||
ErrGroupIsDefault: 'Kumpulan lalai, tidak boleh dipadamkan'
|
||||
ErrGroupIsInWebsiteUse: 'Kumpulan sedang digunakan oleh tapak web lain dan tidak boleh dipadamkan.'
|
||||
Decrypt: "Dekripsi"
|
||||
|
||||
#agent
|
||||
ErrAgentAccountBound: 'Akaun ini telah dipautkan kepada ejen dan tidak boleh dipadam. Sila semak dan cuba lagi!'
|
||||
ErrAgentAccountUnavailable: 'Maklumat sambungan akaun tidak tersedia. Ralat: {{ .err }}. Sila semak dan cuba lagi!'
|
||||
ErrAgentProviderNotSupported: 'Penyedia ejen ini tidak disokong. Sila semak dan cuba lagi!'
|
||||
ErrAgentAccountRequired: 'Sila pilih akaun ejen dan cuba lagi.'
|
||||
ErrAgentAccountNotVerified: 'Akaun belum disahkan. Sila semak dan cuba lagi!'
|
||||
ErrAgentProviderMismatch: 'Penyedia akaun tidak sepadan. Sila semak dan cuba lagi!'
|
||||
ErrAgentBaseURLRequired: 'Base URL tidak boleh kosong. Sila semak dan cuba lagi!'
|
||||
ErrAgentApiKeyRequired: 'API Key tidak boleh kosong. Sila semak dan cuba lagi!'
|
||||
ErrAgentComposeRequired: 'Kandungan compose tersuai tidak boleh kosong. Sila semak dan cuba lagi!'
|
||||
ErrAgentIDRequired: 'ID ejen tidak boleh kosong. Sila semak dan cuba lagi!'
|
||||
ErrAgentAccountIDRequired: 'ID akaun tidak boleh kosong. Sila semak dan cuba lagi!'
|
||||
|
||||
#sandaran
|
||||
Decrypt: 'Dekripsi'
|
||||
ErrAgentAccountBound: 'Akaun terikat kepada ejen'
|
||||
ErrAgentAccountUnavailable: 'Sambungan akaun tidak tersedia: {{ .err }}'
|
||||
ErrAgentProviderNotSupported: 'Penyedia ejen tidak disokong'
|
||||
ErrAgentAccountRequired: 'Pilih akaun ejen terlebih dahulu'
|
||||
ErrAgentAccountNotVerified: 'Akaun ejen belum disahkan'
|
||||
ErrAgentProviderMismatch: 'Penyedia ejen tidak sepadan'
|
||||
ErrAgentBaseURLRequired: 'URL asas diperlukan'
|
||||
ErrAgentApiKeyRequired: 'Kunci API diperlukan'
|
||||
ErrAgentComposeRequired: 'Kandungan compose diperlukan'
|
||||
ErrAgentIDRequired: 'ID ejen diperlukan'
|
||||
ErrAgentAccountIDRequired: 'ID akaun diperlukan'
|
||||
ErrAgentLimitReached: 'Edisi Community menyokong sehingga {{ .max }} ejen AI. Naik taraf ke edisi Professional untuk tiada had bilangan'
|
||||
Localhost: 'Mesin Tempatan'
|
||||
ErrBackupInUsed: 'Akaun sandaran telah digunakan dalam tugas yang dijadualkan dan tidak boleh dipadamkan.'
|
||||
ErrBackupCheck: 'Sambungan ujian akaun sandaran gagal {{ .err }}'
|
||||
ErrBackupLocalDelete: 'Memadam akaun sandaran pelayan tempatan belum disokong lagi'
|
||||
ErrBackupLocalCreate: 'Membuat akaun sandaran pelayan tempatan belum disokong lagi'
|
||||
|
||||
#app
|
||||
ErrPortInUsed: 'Port {{ .detail }} sudah diduduki!'
|
||||
ErrBackupInUsed: 'Akaun sandaran sedang digunakan oleh tugas'
|
||||
ErrBackupCheck: 'Ujian sambungan gagal: {{ .err }}'
|
||||
ErrBackupLocalDelete: 'Tidak boleh padam sandaran tempatan'
|
||||
ErrBackupLocalCreate: 'Tidak boleh buat sandaran tempatan'
|
||||
ErrPortInUsed: 'Port {{ .detail }} sudah diduduki'
|
||||
ErrAppLimit: 'Bilangan aplikasi yang dipasang telah melebihi had'
|
||||
ErrNotInstall: 'Aplikasi tidak dipasang'
|
||||
ErrPortInOtherApp: 'Port {{ .port }} sudah diduduki oleh aplikasi {{ .apps }}!'
|
||||
ErrDbUserNotValid: 'Pangkalan data sedia ada, nama pengguna dan kata laluan tidak sepadan!'
|
||||
ErrUpdateBuWebsite: 'Aplikasi telah berjaya dikemas kini, tetapi pengubahsuaian fail konfigurasi tapak web gagal. Sila semak konfigurasi! '
|
||||
Err1PanelNetworkFailed: 'Pembuatan rangkaian kontena lalai gagal! {{ .detail }}'
|
||||
ErrFileParse: 'Penghuraian fail karang docker aplikasi gagal!'
|
||||
ErrPortInOtherApp: 'Port {{ .port }} sudah diduduki oleh aplikasi {{ .apps }}'
|
||||
ErrDbUserNotValid: 'Pangkalan data sedia ada, nama pengguna dan kata laluan tidak sepadan'
|
||||
ErrUpdateBuWebsite: 'Aplikasi telah berjaya dikemas kini, tetapi pengubahsuaian fail konfigurasi tapak web gagal. Sila semak konfigurasi'
|
||||
Err1PanelNetworkFailed: 'Pembuatan rangkaian kontena lalai gagal {{ .detail }}'
|
||||
ErrFileParse: 'Penghuraian fail karang docker aplikasi gagal'
|
||||
ErrInstallDirNotFound: 'Direktori pemasangan tidak wujud. Jika anda perlu menyahpasang, sila pilih Paksa Nyahpasang'
|
||||
AppStoreIsUpToDate: 'Gedung aplikasi sudah pun versi terkini'
|
||||
LocalAppVersionNull: Aplikasi '{{ .name }} tidak disegerakkan ke versi! Tidak dapat menambah pada senarai apl'
|
||||
LocalAppVersionErr: '{{ .name }} versi penyegerakan {{ .version }} gagal! {{ .err }}'
|
||||
LocalAppVersionNull: 'Aplikasi ''{{ .name }} tidak disegerakkan ke versi Tidak dapat menambah pada senarai apl'''
|
||||
LocalAppVersionErr: '{{ .name }} versi penyegerakan {{ .version }} gagal {{ .err }}'
|
||||
ErrFileNotFound: 'Fail {{ .name }} tidak wujud'
|
||||
ErrFileParseApp: '{{ .name }} penghuraian fail gagal {{ .err }}'
|
||||
ErrAppDirNull: 'Folder versi tidak wujud'
|
||||
LocalAppErr: 'Penyegerakan {{ .name }} aplikasi gagal! {{ .err }}'
|
||||
LocalAppErr: 'Penyegerakan {{ .name }} aplikasi gagal {{ .err }}'
|
||||
ErrContainerName: 'Nama kontena sudah wujud'
|
||||
ErrCreateHttpClient: 'Gagal membuat permintaan {{ .err }}'
|
||||
ErrHttpReqTimeOut: 'Permintaan tamat masa {{ .err }}'
|
||||
@@ -85,69 +74,63 @@ 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'
|
||||
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 }}'
|
||||
ErrVersionTooLow: 'Versi 1Panel semasa terlalu rendah untuk mengemas kini App Store. Sila tingkatkan versi sebelum beroperasi.'
|
||||
ErrAppNameExist: 'Nama aplikasi sudah wujud'
|
||||
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'
|
||||
ErrAppParamKey: 'Parameter {{ .name }} medan tidak normal'
|
||||
ErrAppUpgrade: 'Peningkatan {{ .name }} aplikasi gagal {{ .err }}'
|
||||
AppRecover: 'Aplikasi tarik balik {{ .name }}'
|
||||
PullImageStart: 'Mula tarik imej [{{ .name }}]'
|
||||
PullImageSuccess: 'Tarik imej berjaya'
|
||||
AppStoreIsLastVersion: 'App Store sudah pun versi terkini'
|
||||
AppStoreSyncSuccess: 'Penyegerakan App Store berjaya'
|
||||
SyncAppDetail: 'Segerakkan konfigurasi aplikasi'
|
||||
AppVersionNotMatch: 'Aplikasi {{ .name }} memerlukan versi 1Panel yang lebih tinggi, melangkau penyegerakan'
|
||||
MoveSiteDir: "Perubahan direktori laman web didapati. Perlu memindahkan direktori laman web OpenResty ke {{ .name }}"
|
||||
MoveSiteDir: 'Perubahan direktori laman web didapati. Perlu memindahkan direktori laman web OpenResty ke {{ .name }}'
|
||||
MoveSiteDirSuccess: 'Penghijrahan direktori tapak web yang berjaya'
|
||||
DeleteRuntimePHP: 'Padam masa jalan PHP'
|
||||
CustomAppStoreFileValid: 'Pakej gedung apl perlu dalam format .tar.gz'
|
||||
CustomAppStoreFileValid: 'Pakej gedung apl perlu dalam format.tar.gz'
|
||||
PullImageTimeout: 'Tarik tamat masa imej, sila cuba tingkatkan pecutan imej atau tukar kepada pecutan imej lain'
|
||||
ErrAppIsDown: 'Status permohonan {{ .name }} tidak normal, sila semak'
|
||||
ErrCustomApps: 'Ada aplikasi yang dipasang, sila nyahpasangnya dahulu'
|
||||
ErrCustomRuntimes: 'Terdapat persekitaran masa jalan yang dipasang, sila padamkannya dahulu'
|
||||
ErrAppVersionDeprecated: "Aplikasi {{ .name }} tidak sesuai dengan versi 1Panel saat ini, dilewati"
|
||||
ErrDockerFailed: "Keadaan Docker tidak normal, sila periksa status perkhidmatan"
|
||||
ErrDockerComposeCmdNotFound: "Perintah Docker Compose tidak wujud, sila pasang perintah ini di mesin tuan terlebih dahulu"
|
||||
UseExistImage: 'Gagal menarik imej, menggunakan imej sedia ada'
|
||||
|
||||
#ssh
|
||||
ExportIP: "IP Log Masuk"
|
||||
ExportArea: "Lokasi"
|
||||
ExportPort: "Port"
|
||||
ExportAuthMode: "Kaedah Log Masuk"
|
||||
ExportUser: "Pengguna"
|
||||
ExportStatus: "Status Log Masuk"
|
||||
ExportDate: "Masa"
|
||||
|
||||
#fail
|
||||
ErrAppVersionDeprecated: 'Aplikasi {{ .name }} tidak sesuai dengan versi 1Panel saat ini, dilewati'
|
||||
ErrDockerFailed: 'Keadaan Docker tidak normal, sila periksa status perkhidmatan'
|
||||
ErrDockerComposeCmdNotFound: 'Perintah Docker Compose tidak wujud, sila pasang perintah ini di mesin tuan terlebih dahulu'
|
||||
UseExistImage: 'Imej sudah wujud, menggunakan imej sedia ada'
|
||||
ErrDatabaseNotFound: 'Pangkalan data {{ .name }} tidak wujud'
|
||||
ExportIP: 'IP Log Masuk'
|
||||
ExportArea: 'Lokasi'
|
||||
ExportPort: 'Port'
|
||||
ExportAuthMode: 'Kaedah Log Masuk'
|
||||
ExportUser: 'Pengguna'
|
||||
ExportStatus: 'Status Log Masuk'
|
||||
ExportDate: 'Masa'
|
||||
ErrFileCanNotRead: 'Fail ini tidak menyokong pratonton'
|
||||
ErrFileToLarge: 'Fail lebih besar daripada 10M dan tidak boleh dibuka'
|
||||
ErrPathNotFound: 'Direktori tidak wujud'
|
||||
ErrMovePathFailed: 'Laluan sasaran tidak boleh mengandungi laluan asal!'
|
||||
ErrLinkPathNotFound: 'Laluan sasaran tidak wujud!'
|
||||
ErrFileIsExist: 'Fail atau folder sudah wujud!'
|
||||
ErrMovePathFailed: 'Laluan sasaran tidak boleh mengandungi laluan asal'
|
||||
ErrLinkPathNotFound: 'Laluan sasaran tidak wujud'
|
||||
ErrFileIsExist: 'Fail atau folder sudah wujud'
|
||||
ErrFileUpload: '{{ .name }} gagal memuat naik fail {{ .detail }}'
|
||||
ErrFileDownloadDir: 'Folder muat turun tidak disokong'
|
||||
ErrCmdNotFound: 'Arahan {{ .name}} tidak wujud, sila pasang arahan ini pada hos dahulu'
|
||||
ErrCmdNotFound: 'Arahan {{ .name }} tidak wujud, sila pasang arahan ini pada hos dahulu'
|
||||
ErrSourcePathNotFound: 'Direktori sumber tidak wujud'
|
||||
ErrFavoriteExist: 'Laluan ini telah digemari'
|
||||
ErrInvalidChar: 'Aksara haram tidak dibenarkan'
|
||||
ErrPathNotDelete: 'Direktori yang dipilih tidak boleh dipadamkan'
|
||||
ErrLogFileTooLarge: "Fail log melebihi 500MB dan tidak boleh dibuka"
|
||||
FileDropFailed: "Gagal membersihkan fail {{ .name }}: {{ .err }}"
|
||||
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"
|
||||
ErrBadDecrypt: "Kata laluan penyahsulitan pakej termampat salah, penyahmampatan gagal, sila periksa dan cuba lagi!"
|
||||
|
||||
#laman web
|
||||
ErrLogFileToLarge: 'Fail log melebihi 500MB dan tidak boleh dibuka'
|
||||
FileDropFailed: 'Gagal membersihkan fail {{ .name }}: {{ .err }}'
|
||||
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'
|
||||
ErrBadDecrypt: 'Kata laluan penyahsulitan pakej termampat salah, penyahmampatan gagal, sila periksa dan cuba lagi'
|
||||
ErrAliasIsExist: 'Alias sudah wujud'
|
||||
ErrBackupMatch: 'Fail sandaran tidak sepadan dengan beberapa data tapak web semasa {{ .detail }}'
|
||||
ErrBackupExist: 'Bahagian sepadan data sumber dalam fail sandaran tidak wujud {{ .detail }}'
|
||||
ErrPHPResource: 'Persekitaran operasi tempatan tidak menyokong penukaran! '
|
||||
ErrPHPResource: 'Persekitaran operasi tempatan tidak menyokong penukaran'
|
||||
ErrPathPermission: 'Folder dengan keizinan bukan 1000:1000 telah dikesan dalam direktori indeks, yang mungkin menyebabkan ralat dinafikan Akses pada tapak web. Sila klik butang Simpan di atas'
|
||||
ErrDomainIsUsed: 'Nama domain telah digunakan oleh tapak web [{{ .name }}]'
|
||||
ErrDomainFormat: 'Format nama domain {{ .name }} tidak betul'
|
||||
@@ -155,11 +138,11 @@ ErrDefaultAlias: 'lalai ialah kod simpanan, sila gunakan kod lain'
|
||||
ErrParentWebsite: 'Anda perlu memadamkan subtapak {{ .name }} dahulu'
|
||||
ErrBuildDirNotFound: 'Direktori binaan tidak wujud'
|
||||
ErrImageNotExist: 'Imej persekitaran operasi {{ .name }} tidak wujud, sila edit semula persekitaran pengendalian'
|
||||
ErrProxyIsUsed: "Pengimbang beban telah digunakan oleh pengganti terbalik, tidak boleh dipadamkan"
|
||||
ErrSSLValid: 'Fail sijil bermasalah, sila periksa status sijil!'
|
||||
ErrWebsiteDir: "Sila pilih direktori dalam direktori laman web."
|
||||
ErrComposerFileNotFound: "Fail composer.json tidak wujud"
|
||||
ErrRuntimeNoPort: "Persekitaran runtime tidak diset dengan port, sila edit persekitaran runtime terlebih dahulu."
|
||||
ErrProxyIsUsed: 'Pengimbang beban telah digunakan oleh pengganti terbalik, tidak boleh dipadamkan'
|
||||
ErrSSLValid: 'Fail sijil bermasalah, sila periksa status sijil'
|
||||
ErrWebsiteDir: 'Sila pilih direktori dalam direktori laman web.'
|
||||
ErrComposerFileNotFound: 'Fail composer.json tidak wujud'
|
||||
ErrRuntimeNoPort: 'Persekitaran runtime tidak diset dengan port, sila edit persekitaran runtime terlebih dahulu.'
|
||||
Status: 'Status'
|
||||
start: 'Mulakan'
|
||||
stop: 'Berhenti'
|
||||
@@ -169,27 +152,25 @@ pause: 'Jeda'
|
||||
unpause: 'Sambung Semula'
|
||||
remove: 'Padam'
|
||||
delete: 'Padam'
|
||||
ErrDefaultWebsite: 'Laman web lalai telah ditetapkan, sila batalkan sebelum menetapkan!'
|
||||
ErrDefaultWebsite: 'Laman web lalai telah ditetapkan, sila batalkan sebelum menetapkan'
|
||||
SSL: 'Sijil'
|
||||
Set: 'Tetapan'
|
||||
|
||||
#ssl
|
||||
ErrSSLCannotDelete: 'Sijil {{ .name }} sedang digunakan oleh tapak web dan tidak boleh dipadamkan'
|
||||
ErrAccountCannotDelete: 'Akaun dikaitkan dengan sijil dan tidak boleh dipadamkan'
|
||||
ErrSSSLApply: 'Pembaharuan sijil berjaya, muat semula openresty gagal, sila semak konfigurasi!'
|
||||
ErrSSLApply: 'Pembaharuan sijil berjaya, muat semula openresty gagal, sila semak konfigurasi'
|
||||
ErrEmailIsExist: 'Peti mel sudah wujud'
|
||||
ErrSSLKeyNotFound: 'Fail kunci peribadi tidak wujud'
|
||||
ErrSSLCertificateNotFound: 'Fail sijil tidak wujud'
|
||||
ErrSSLKeyFormat: 'Pengesahan fail kunci peribadi gagal'
|
||||
ErrSSLCertificateFormat: 'Format fail sijil tidak betul, sila gunakan format pem'
|
||||
ErrEabKidOrEabHmacKeyCannot Blank: 'EabKid atau EabHmacKey tidak boleh kosong'
|
||||
ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid atau EabHmacKey tidak boleh kosong'
|
||||
ErrOpenrestyNotFound: 'Mod Http memerlukan Openresty dipasang dahulu'
|
||||
ApplySSLStart: 'Mula memohon sijil, nama domain [{{ .domain }}] kaedah permohonan [{{ .type }}] '
|
||||
ApplySSLStart: 'Mula memohon sijil, nama domain [{{ .domain }}] kaedah permohonan [{{ .type }}]'
|
||||
dnsAccount: 'DNS Auto'
|
||||
dnsManual: 'Manual DNS'
|
||||
http: 'HTTP'
|
||||
ApplySSLFailed: 'Permohonan untuk sijil [{{ .domain }}] gagal, {{ .detail }} '
|
||||
ApplySSLSuccess: 'Berjaya memohon sijil [{{ .domain }}]! ! '
|
||||
ApplySSLFailed: 'Permohonan untuk sijil [{{ .domain }}] gagal, {{ .detail }}'
|
||||
ApplySSLSuccess: 'Berjaya memohon sijil [{{ .domain }}]'
|
||||
DNSAccountName: 'Akaun DNS [{{ .name }}] vendor [{{ .type }}]'
|
||||
PushDirLog: 'Sijil ditolak ke direktori [{{ .path }}] {{ .status }}'
|
||||
ErrDeleteCAWithSSL: 'Organisasi semasa mempunyai sijil yang telah dikeluarkan dan tidak boleh dipadamkan.'
|
||||
@@ -204,94 +185,79 @@ ExecShellSuccess: 'Pelaksanaan skrip berjaya'
|
||||
StartUpdateSystemSSL: 'Mula mengemas kini sijil sistem'
|
||||
UpdateSystemSSLSuccess: 'Berjaya kemas kini sijil sistem'
|
||||
ErrWildcardDomain: 'Tidak dapat memohon sijil nama domain kad bebas dalam mod HTTP'
|
||||
ErrApplySSLCanNotDelete: "Sertifikat {{.name}} yang sedang diajukan tidak dapat dihapus, sila cuba lagi kemudian."
|
||||
|
||||
#mysql
|
||||
ErrApplySSLCanNotDelete: 'Sertifikat {{ .name }} yang sedang diajukan tidak dapat dihapus, sila cuba lagi kemudian.'
|
||||
StartPushSSLToNode: 'Mula menolak sijil ke nod'
|
||||
PushSSLToNodeFailed: 'Gagal menolak sijil ke nod: {{ .err }}'
|
||||
PushSSLToNodeSuccess: 'Berjaya menolak sijil ke nod'
|
||||
ErrUserIsExist: 'Pengguna semasa sudah wujud, sila masukkan semula'
|
||||
ErrDatabaseIsExist: 'Pangkalan data semasa sudah wujud, sila masukkan semula'
|
||||
ErrExecTimeOut: 'Pelaksanaan SQL tamat masa, sila semak pangkalan data'
|
||||
ErrRemoteExist: 'Pangkalan data jauh sudah wujud dengan nama ini, sila ubah suainya dan cuba lagi'
|
||||
ErrLocalExist: 'Nama sudah wujud dalam pangkalan data tempatan, sila ubah suai dan cuba lagi'
|
||||
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..."
|
||||
Arg: "Hujah"
|
||||
|
||||
#redis
|
||||
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...'
|
||||
Arg: 'Hujah'
|
||||
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!"
|
||||
ErrObjectInUsed: "Objek ini sedang digunakan dan tidak boleh dipadam!"
|
||||
ErrObjectBeDependent: "Imej ini digantungkan oleh imej lain dan tidak boleh dipadam!"
|
||||
ErrPortRules: 'Nombor port tidak sepadan, sila masukkan semula!'
|
||||
ErrInUsed: '{{ .detail }} 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'
|
||||
ErrPortRules: 'Nombor port tidak sepadan, sila masukkan semula'
|
||||
ErrPgImagePull: 'Tarikh imej tamat masa, sila konfigurasikan pecutan imej atau tarik imej {{ .name }} secara manual dan cuba lagi'
|
||||
PruneHelper: "Pembersihan ini {{ .name }} membebaskan ruang cakera {{ .size }}"
|
||||
ImageRemoveHelper: "Padam imej {{ .name }}, membebaskan {{ .size }} ruang cakera"
|
||||
BuildCache: "Cache binaan"
|
||||
Volume: "Jilid storan"
|
||||
Network: "Rangkaian"
|
||||
PruneStart: "Pembersihan sedang dijalankan, sila tunggu..."
|
||||
|
||||
#masa berjalan
|
||||
ErrFileNotExist: 'Fail {{ .detail }} tidak wujud! Sila semak integriti fail sumber!'
|
||||
PruneHelper: 'Pembersihan ini {{ .name }} membebaskan ruang cakera {{ .size }}'
|
||||
ImageRemoveHelper: 'Padam imej {{ .name }}, membebaskan {{ .size }} ruang cakera'
|
||||
BuildCache: 'Cache binaan'
|
||||
Volume: 'Jilid storan'
|
||||
Network: 'Rangkaian'
|
||||
PruneStart: 'Pembersihan sedang dijalankan, sila tunggu...'
|
||||
ErrFileNotExist: 'Fail {{ .detail }} tidak wujud Sila semak integriti fail sumber'
|
||||
ErrImageBuildErr: 'Pembinaan imej gagal'
|
||||
ErrImageExist: "Imej sudah wujud! Sila ubah nama imej."
|
||||
ErrImageExist: 'Imej sudah wujud Sila ubah nama imej.'
|
||||
ErrDelWithWebsite: 'Persekitaran pengendalian sudah dikaitkan dengan tapak web dan tidak boleh dipadamkan'
|
||||
ErrRuntimeStart: 'Permulaan gagal'
|
||||
ErrPackageJsonNotFound: 'fail package.json tidak wujud'
|
||||
ErrScriptsNotFound: 'Item konfigurasi skrip tidak ditemui dalam package.json'
|
||||
ErrContainerNameNotFound: 'Tidak dapat mendapatkan nama kontena, sila semak fail .env'
|
||||
ErrNodeModulesNotFound: 'Folder node_modules tidak wujud! Sila edit persekitaran masa jalan atau tunggu persekitaran masa jalan berjaya dimulakan'
|
||||
ErrContainerNameNotFound: 'Tidak dapat mendapatkan nama kontena, sila semak fail.env'
|
||||
ErrNodeModulesNotFound: 'Folder node_modules tidak wujud Sila edit persekitaran masa jalan atau tunggu persekitaran masa jalan berjaya dimulakan'
|
||||
ErrContainerNameIsNull: 'Nama kontena tidak wujud'
|
||||
ErrPHPPortIsDefault: "Порт 9000 является портом по умолчанию, пожалуйста, измените и попробуйте снова"
|
||||
ErrPHPRuntimePortFailed: "Порт {{ .name }} уже используется текущей средой выполнения, пожалуйста, измените и попробуйте снова"
|
||||
|
||||
#alat
|
||||
ErrPHPPortIsDefault: 'Порт 9000 является портом по умолчанию, пожалуйста, измените и попробуйте снова'
|
||||
ErrPHPRuntimePortFailed: 'Порт {{ .name }} уже используется текущей средой выполнения, пожалуйста, измените и попробуйте снова'
|
||||
ErrConfigNotFound: 'Fail konfigurasi tidak wujud'
|
||||
ErrConfigParse: 'Format fail konfigurasi tidak betul'
|
||||
ErrConfigIsNull: 'Fail konfigurasi tidak boleh kosong'
|
||||
ErrConfigDirNotFound: 'Direktori berjalan tidak wujud'
|
||||
ErrConfigAlreadyExist: 'Fail konfigurasi dengan nama yang sama sudah wujud'
|
||||
ErrUserFindErr: 'Pengguna {{ .name }} carian gagal {{ .err }}'
|
||||
|
||||
#cronjob
|
||||
CutWebsiteLogSuccess: '{{ .name }} log tapak web berjaya dipotong, laluan sandaran {{ .path }}'
|
||||
HandleShell: 'Laksanakan skrip {{ .name }}'
|
||||
HandleCurl: "Akses URL {{ .name }}"
|
||||
HandleCurl: 'Akses URL {{ .name }}'
|
||||
HandleNtpSync: 'Penyegerakan masa sistem'
|
||||
HandleSystemClean: 'Pembersihan cache sistem'
|
||||
SystemLog: 'Log Sistem'
|
||||
CutWebsiteLog: 'Putar Log Laman Web'
|
||||
FileOrDir: 'Direktori / Fail'
|
||||
UploadFile: 'Muat naik fail sandaran {{ .file }} ke {{ .backup }}'
|
||||
Upload: "Muat Naik"
|
||||
IgnoreBackupErr: "Sandaran gagal, ralat: {{ .detail }}, abaikan ralat ini..."
|
||||
IgnoreUploadErr: "Muat naik gagal, ralat: {{ .detail }}, abaikan ralat ini..."
|
||||
LoadBackupFailed: "Gagal mendapatkan sambungan akaun sandaran, ralat: {{ .detail }}"
|
||||
InExecuting: "Tugas semasa sedang dilaksanakan, jangan ulangi pelaksanaan!"
|
||||
NoSuchResource: "Tiada kandungan sandaran ditemui dalam pangkalan data, dilangkau..."
|
||||
CleanLog: "Bersihkan log"
|
||||
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."
|
||||
|
||||
#kotak alat
|
||||
ErrNotExistUser: 'Pengguna semasa tidak wujud, sila ubah suai 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!'
|
||||
TaskSwapSet: "Tetapkan Swap"
|
||||
SetSwap: "Tetapkan Swap {{ .path }} - {{ .size }}"
|
||||
CreateSwap: "Buat Fail Swap"
|
||||
FormatSwap: "Format Fail Swap"
|
||||
EnableSwap: "Dayakan Swap"
|
||||
|
||||
#tamper
|
||||
CleanTamperSetting: "Bersihkan tetapan perlindungan sejarah"
|
||||
SetTamperWithRules: "Mulakan perlindungan direktori mengikut peraturan"
|
||||
ProtectDir: "Lindungi direktori {{ .name }}"
|
||||
IgnoreFile: "Lindungi fail {{ .name }}"
|
||||
TamperSetSuccessful: "Tetapan perlindungan selesai, mula memantau direktori berikut:"
|
||||
|
||||
#waf
|
||||
Upload: 'Muat Naik'
|
||||
IgnoreBackupErr: 'Sandaran gagal, ralat: {{ .detail }}, abaikan ralat ini...'
|
||||
IgnoreUploadErr: 'Muat naik gagal, ralat: {{ .detail }}, abaikan ralat ini...'
|
||||
LoadBackupFailed: 'Gagal mendapatkan sambungan akaun sandaran, ralat: {{ .detail }}'
|
||||
InExecuting: 'Tugas semasa sedang dilaksanakan, jangan ulangi pelaksanaan'
|
||||
NoSuchResource: 'Tiada kandungan sandaran ditemui dalam pangkalan data, dilangkau...'
|
||||
CleanLog: 'Bersihkan log'
|
||||
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.'
|
||||
ErrNotExistUser: 'Pengguna semasa tidak wujud, sila ubah suai 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'
|
||||
TaskSwapSet: 'Tetapkan Swap'
|
||||
SetSwap: 'Tetapkan Swap {{ .path }} - {{ .size }}'
|
||||
CreateSwap: 'Buat Fail Swap'
|
||||
FormatSwap: 'Format Fail Swap'
|
||||
EnableSwap: 'Dayakan Swap'
|
||||
CleanTamperSetting: 'Bersihkan tetapan perlindungan sejarah'
|
||||
SetTamperWithRules: 'Mulakan perlindungan direktori mengikut peraturan'
|
||||
ProtectDir: 'Lindungi direktori {{ .name }}'
|
||||
IgnoreFile: 'Lindungi fail {{ .name }}'
|
||||
TamperSetSuccessful: 'Tetapan perlindungan selesai, mula memantau direktori berikut:'
|
||||
ErrScope: 'Mengubah suai konfigurasi ini tidak disokong'
|
||||
ErrStateChange: 'Perubahan keadaan gagal'
|
||||
ErrRuleExist: 'Peraturan sudah wujud'
|
||||
@@ -299,7 +265,7 @@ ErrRuleNotExist: 'Peraturan tidak wujud'
|
||||
ErrParseIP: 'Format IP salah'
|
||||
ErrDefaultIP: 'default ialah nama simpanan, sila tukar kepada nama lain'
|
||||
ErrGroupInUse: 'Kumpulan IP digunakan oleh senarai hitam/senarai putih dan tidak boleh dipadamkan'
|
||||
ErrIPGroupAclUse: "Kumpulan IP digunakan oleh peraturan tersuai tapak web {{ .name }}, tidak boleh dipadamkan"
|
||||
ErrIPGroupAclUse: 'Kumpulan IP digunakan oleh peraturan tersuai tapak web {{ .name }}, tidak boleh dipadamkan'
|
||||
ErrGroupExist: 'Nama kumpulan IP sudah wujud'
|
||||
ErrIPRange: 'Julat IP salah'
|
||||
ErrIPExist: 'IP sudah wujud'
|
||||
@@ -310,11 +276,11 @@ xss: 'XSS'
|
||||
phpExec: 'Pelaksanaan skrip PHP'
|
||||
oneWordTrojan: 'One Word Trojan'
|
||||
appFilter: 'Gunakan penapisan direktori berbahaya'
|
||||
webshell: 'Webshell'
|
||||
webShell: 'Webshell'
|
||||
args: 'Peraturan parameter'
|
||||
protocolFilter: 'Penapisan protokol'
|
||||
javaFileter: 'Penapis fail berbahaya Java'
|
||||
Penapis pengimbas: 'Penapis pengimbas'
|
||||
javaFilter: 'Penapis fail berbahaya Java'
|
||||
scannerFilter: 'Penapis pengimbas'
|
||||
escapeFilter: 'penapis melarikan diri'
|
||||
customRule: 'Peraturan tersuai'
|
||||
httpMethod: 'Penapisan kaedah HTTP'
|
||||
@@ -343,10 +309,9 @@ ErrDBNotExist: 'Pangkalan data tidak wujud'
|
||||
allow: 'membenarkan'
|
||||
deny: 'menafikan'
|
||||
OpenrestyNotFound: 'Openresty tidak dipasang'
|
||||
remoteIpIsNull: "Senarai IP kosong"
|
||||
OpenrestyVersionErr: "Versi Openresty terlalu rendah, sila naik taraf Openresty ke 1.27.1.2-2-2-focal"
|
||||
|
||||
#tugas
|
||||
remoteIpIsNull: 'Senarai IP kosong'
|
||||
OpenrestyVersionErr: 'Versi Openresty terlalu rendah, sila naik taraf Openresty ke 1.27.1.2-2-2-focal'
|
||||
ErrFileTooLarge: 'File is larger than 1 MB and cannot be uploaded'
|
||||
TaskStart: '{{ .name }} Task mula [MULA]'
|
||||
TaskEnd: '{{ .name }} Task selesai [SELESAI]'
|
||||
TaskFailed: 'tugas {{ .name }} gagal'
|
||||
@@ -362,7 +327,7 @@ TaskDelete: 'Padam'
|
||||
TaskUpgrade: 'Naik taraf'
|
||||
TaskUpdate: 'Kemas kini'
|
||||
TaskRestart: 'Mulakan semula'
|
||||
TaskProtect: "Lindungi"
|
||||
TaskProtect: 'Lindungi'
|
||||
TaskBackup: 'Sandaran'
|
||||
TaskRecover: 'Pulihkan'
|
||||
TaskRollback: 'Rollback'
|
||||
@@ -370,10 +335,10 @@ TaskPull: 'Tarik'
|
||||
TaskCommit: 'Komit'
|
||||
TaskBuild: 'Bina'
|
||||
TaskPush: 'Tolak'
|
||||
TaskClean: "Pembersihan"
|
||||
TaskClean: 'Pembersihan'
|
||||
TaskHandle: 'Laksanakan'
|
||||
TaskImport: "Import"
|
||||
TaskExport: "Eksport"
|
||||
TaskImport: 'Import'
|
||||
TaskExport: 'Eksport'
|
||||
Website: 'Laman web'
|
||||
App: 'Aplikasi'
|
||||
Runtime: 'Persekitaran masa jalan'
|
||||
@@ -405,18 +370,12 @@ RuntimeExtension: 'Sambungan Persekitaran Runtime'
|
||||
TaskIsExecuting: 'Tugas sedang berjalan'
|
||||
CustomAppstore: 'Gudang aplikasi tersuai'
|
||||
TaskExec: 'Laksanakan'
|
||||
TaskBatch: "Operasi Batch"
|
||||
TaskBatch: 'Operasi Batch'
|
||||
FileConvert: 'Penukaran Format Fail'
|
||||
|
||||
# task - clam
|
||||
Clamscan: "Imbas {{ .name }}"
|
||||
TaskScan: "Imbas"
|
||||
|
||||
# tugasan - ai
|
||||
Clamscan: 'Imbas {{ .name }}'
|
||||
TaskScan: 'Imbas'
|
||||
OllamaModelPull: 'Tarik model Ollama {{ .name }}'
|
||||
OllamaModelSize: 'Dapatkan saiz model Ollama {{ .name }}'
|
||||
|
||||
# gambar tugasan
|
||||
Snapshot: 'Snapshot'
|
||||
SnapDBInfo: 'Tulis maklumat pangkalan data 1Panel'
|
||||
SnapCopy: 'Salin fail & direktori {{ .name }}'
|
||||
@@ -442,7 +401,6 @@ SnapCompressSize: 'Saiz fail syot kilat {{ .name }}'
|
||||
SnapUpload: 'Muat naik fail syot kilat'
|
||||
SnapUploadTo: 'Muat naik fail syot kilat ke {{ .name }}'
|
||||
SnapUploadRes: 'Muat naik fail syot kilat ke {{ .name }}'
|
||||
|
||||
SnapshotRecover: 'Snapshot Restore'
|
||||
RecoverDownload: 'Muat turun fail syot kilat'
|
||||
Download: 'Muat turun'
|
||||
@@ -450,10 +408,10 @@ RecoverDownloadAccount: 'Dapatkan syot kilat muat turun akaun sandaran {{ .name
|
||||
RecoverDecompress: 'Nyahmampatkan fail termampat syot kilat'
|
||||
Decompress: 'Penyahmampatan'
|
||||
BackupBeforeRecover: 'Sandarkan data berkaitan sistem sebelum syot kilat'
|
||||
Readjson: 'Baca fail Json dalam petikan'
|
||||
ReadjsonPath: 'Dapatkan laluan fail Json dalam petikan'
|
||||
ReadjsonContent: 'Baca fail Json'
|
||||
ReadjsonMarshal: 'Pemprosesan melarikan diri Json'
|
||||
ReadJson: 'Baca fail Json dalam petikan'
|
||||
ReadJsonPath: 'Dapatkan laluan fail Json dalam petikan'
|
||||
ReadJsonContent: 'Baca fail Json'
|
||||
ReadJsonMarshal: 'Pemprosesan melarikan diri Json'
|
||||
RecoverApp: 'Pulihkan apl yang dipasang'
|
||||
RecoverWebsite: 'Pulihkan direktori tapak web'
|
||||
RecoverAppImage: 'Pulihkan sandaran imej syot kilat'
|
||||
@@ -467,9 +425,6 @@ RecoverDaemonJson: 'Pulihkan fail daemon.json konfigurasi bekas'
|
||||
RecoverDBData: 'Pulihkan data pangkalan data'
|
||||
RecoverBackups: 'Pulihkan direktori sandaran tempatan'
|
||||
RecoverPanelData: 'Direktori data pemulihan'
|
||||
|
||||
# tugas - bekas
|
||||
ContainerNewCliet: 'Memulakan Klien Docker'
|
||||
ContainerImagePull: 'Tarik imej bekas {{ .name }}'
|
||||
ContainerRemoveOld: 'Alih keluar bekas asal {{ .name }}'
|
||||
ContainerImageCheck: 'Periksa sama ada imej ditarik seperti biasa'
|
||||
@@ -478,22 +433,13 @@ ContainerRecreate: 'Kemas kini kontena gagal, kini mula memulihkan bekas asal'
|
||||
ContainerCreate: 'Buat bekas baharu {{ .name }}'
|
||||
ContainerCreateFailed: 'Penciptaan bekas gagal, padamkan bekas yang gagal'
|
||||
ContainerStartCheck: 'Periksa sama ada bekas telah dimulakan'
|
||||
|
||||
# tugas - imej
|
||||
ImageBuild: 'Membina Imej'
|
||||
ImageBuildStdoutCheck: 'Menghuraikan kandungan output imej'
|
||||
ImageBuildRes: 'Output binaan imej: {{ .name }}'
|
||||
ImagePull: 'Tarik imej'
|
||||
ImageRepoAuthFromDB: 'Dapatkan maklumat pengesahan repositori daripada pangkalan data'
|
||||
ImaegPullRes: 'Output tarik imej: {{ .name }}'
|
||||
ImagePush: 'Tolak imej'
|
||||
ImageRenameTag: 'Ubah suai teg imej'
|
||||
ImageNewTag: 'Teg imej baharu {{ .name }}'
|
||||
ImaegPushRes: 'Output tolak imej: {{ .name }}'
|
||||
ComposeCreate: 'Buat gubahan'
|
||||
ComposeCreateRes: 'Karang cipta output: {{ .name }}'
|
||||
|
||||
# tugas - laman web
|
||||
BackupNginxConfig: 'Fail konfigurasi OpenResty tapak web sandaran'
|
||||
CompressFileSuccess: 'Mampatkan direktori berjaya, dimampatkan ke {{ .name }}'
|
||||
CompressDir: 'Direktori mampatan'
|
||||
@@ -504,40 +450,27 @@ websiteDir: 'Direktori Laman Web'
|
||||
RecoverFailedStartRollBack: 'Pemulihan gagal, mulakan rollback'
|
||||
AppBackupFileIncomplete: 'Fail sandaran tidak lengkap dan tidak mempunyai fail app.json atau app.tar.gz'
|
||||
AppAttributesNotMatch: 'Jenis atau nama aplikasi tidak sepadan'
|
||||
|
||||
#alert
|
||||
ErrAlert: 'Format mesej amaran tidak betul, sila semak dan cuba lagi!'
|
||||
ErrAlertPush: 'Ralat dalam menolak maklumat amaran, sila semak dan cuba lagi!'
|
||||
ErrAlertSave: 'Ralat menyimpan maklumat penggera, sila semak dan cuba lagi!'
|
||||
ErrAlertSync: 'Ralat penyegerakan maklumat penggera, sila semak dan cuba lagi!'
|
||||
ErrAlertRemote: 'Ralat jauh mesej penggera, sila semak dan cuba lagi!'
|
||||
|
||||
#task - runtime
|
||||
ErrInstallExtension: "Tugas pemasangan sudah sedang berjalan, silakan tunggu tugas selesai"
|
||||
|
||||
# alert mail template
|
||||
PanelAlertTitle: "Notifikasi Amaran Panel"
|
||||
TestAlertTitle: "E-mel Ujian - Sahkan Sambungan E-mel"
|
||||
TestAlert: "Ini adalah e-mel ujian untuk mengesahkan konfigurasi penghantaran e-mel anda betul."
|
||||
LicenseExpirationAlert: "Panel {{ .node }}{{ .ip }} Anda, lesen akan tamat tempoh dalam {{ .day }} hari. Sila log masuk ke panel untuk butiran lanjut."
|
||||
CronJobFailedAlert: "Panel {{ .node }}{{ .ip }} Anda, tugas jadual {{ .name }} gagal dilaksanakan. Sila log masuk ke panel untuk butiran lanjut."
|
||||
ClamAlert: "Panel {{ .node }}{{ .ip }} Anda, tugas imbasan virus mengesan {{ .num }} fail yang dijangkiti. Sila log masuk ke panel untuk butiran lanjut."
|
||||
WebSiteAlert: "Panel {{ .node }}{{ .ip }} Anda, {{ .num }} laman web akan tamat tempoh dalam {{ .day }} hari. Sila log masuk ke panel untuk butiran lanjut."
|
||||
SSLAlert: "Panel {{ .node }}{{ .ip }} Anda, {{ .num }} sijil SSL akan tamat tempoh dalam {{ .day }} hari. Sila log masuk ke panel untuk butiran lanjut."
|
||||
DiskUsedAlert: "Panel {{ .node }}{{ .ip }} Anda, penggunaan cakera {{ .name }} telah mencapai {{ .used }}. Sila log masuk ke panel untuk butiran lanjut."
|
||||
ResourceAlert: "Panel {{ .node }}{{ .ip }} Anda, kadar penggunaan purata {{ .name }} dalam tempoh {{ .time }} minit ialah {{ .used }}. Sila log masuk ke panel untuk butiran lanjut."
|
||||
PanelVersionAlert: "Panel {{ .node }}{{ .ip }} Anda, versi panel terkini tersedia untuk dinaik taraf. Sila log masuk ke panel untuk butiran lanjut."
|
||||
PanelPwdExpirationAlert: "Panel {{ .node }}{{ .ip }} Anda, kata laluan panel akan tamat tempoh dalam {{ .day }} hari. Sila log masuk ke panel untuk butiran lanjut."
|
||||
CommonAlert: "Panel {{ .node }}{{ .ip }} Anda, {{ .msg }}. 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."
|
||||
SSHAndPanelLoginAlert: "Panel {{ .node }}{{ .ip }} Anda, log masuk {{ .name }} dari {{ .loginIp }} tidak normal. Sila log masuk ke panel untuk butiran lanjut."
|
||||
|
||||
#disk
|
||||
DeviceNotFound: "Peranti {{ .name }} tidak ditemui"
|
||||
DeviceIsMounted: "Peranti {{ .name }} telah dikaitkan, sila nyahkaitkan terlebih dahulu"
|
||||
PartitionDiskErr: "Gagal membahagikan, {{ .err }}"
|
||||
FormatDiskErr: "Gagal memformat cakera, {{ .err }}"
|
||||
MountDiskErr: "Gagal mengkaitkan cakera, {{ .err }}"
|
||||
UnMountDiskErr: "Gagal nyahkaitkan cakera, {{ .err }}"
|
||||
XfsNotFound: "Sistem fail xfs tidak dikesan, sila pasang xfsprogs terlebih dahulu"
|
||||
ErrAlertSync: 'Ralat penyegerakan maklumat penggera, sila semak dan cuba lagi'
|
||||
ErrInstallExtension: 'Tugas pemasangan sudah sedang berjalan, silakan tunggu tugas selesai'
|
||||
PanelAlertTitle: 'Notifikasi Amaran Panel'
|
||||
TestAlertTitle: 'E-mel Ujian - Sahkan Sambungan E-mel'
|
||||
TestAlert: 'Ini adalah e-mel ujian untuk mengesahkan konfigurasi penghantaran e-mel anda betul.'
|
||||
LicenseExpirationAlert: 'Panel {{ .node }}{{ .ip }} Anda, lesen akan tamat tempoh dalam {{ .day }} hari. Sila log masuk ke panel untuk butiran lanjut.'
|
||||
CronJobFailedAlert: 'Panel {{ .node }}{{ .ip }} Anda, tugas jadual {{ .name }} gagal dilaksanakan. Sila log masuk ke panel untuk butiran lanjut.'
|
||||
ClamAlert: 'Panel {{ .node }}{{ .ip }} Anda, tugas imbasan virus mengesan {{ .num }} fail yang dijangkiti. Sila log masuk ke panel untuk butiran lanjut.'
|
||||
WebSiteAlert: 'Panel {{ .node }}{{ .ip }} Anda, {{ .num }} laman web akan tamat tempoh dalam {{ .day }} hari. Sila log masuk ke panel untuk butiran lanjut.'
|
||||
SSLAlert: 'Panel {{ .node }}{{ .ip }} Anda, {{ .num }} sijil SSL akan tamat tempoh dalam {{ .day }} hari. Sila log masuk ke panel untuk butiran lanjut.'
|
||||
DiskUsedAlert: 'Panel {{ .node }}{{ .ip }} Anda, penggunaan cakera {{ .name }} telah mencapai {{ .used }}. Sila log masuk ke panel untuk butiran lanjut.'
|
||||
ResourceAlert: 'Panel {{ .node }}{{ .ip }} Anda, kadar penggunaan purata {{ .name }} dalam tempoh {{ .time }} minit ialah {{ .used }}. Sila log masuk ke panel untuk butiran lanjut.'
|
||||
PanelVersionAlert: 'Panel {{ .node }}{{ .ip }} Anda, versi panel terkini tersedia untuk dinaik taraf. Sila log masuk ke panel untuk butiran lanjut.'
|
||||
PanelPwdExpirationAlert: 'Panel {{ .node }}{{ .ip }} Anda, kata laluan panel akan tamat tempoh dalam {{ .day }} hari. Sila log masuk ke panel untuk butiran lanjut.'
|
||||
CommonAlert: 'Panel {{ .node }}{{ .ip }} Anda, {{ .msg }}. 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.'
|
||||
SSHAndPanelLoginAlert: 'Panel {{ .node }}{{ .ip }} Anda, log masuk {{ .name }} dari {{ .loginIp }} tidak normal. Sila log masuk ke panel untuk butiran lanjut.'
|
||||
DeviceNotFound: 'Peranti {{ .name }} tidak ditemui'
|
||||
DeviceIsMounted: 'Peranti {{ .name }} telah dikaitkan, sila nyahkaitkan terlebih dahulu'
|
||||
PartitionDiskErr: 'Gagal membahagikan, {{ .err }}'
|
||||
FormatDiskErr: 'Gagal memformat cakera, {{ .err }}'
|
||||
MountDiskErr: 'Gagal mengkaitkan cakera, {{ .err }}'
|
||||
XfsNotFound: 'Sistem fail xfs tidak dikesan, sila pasang xfsprogs terlebih dahulu'
|
||||
|
||||
+178
-245
@@ -1,34 +1,28 @@
|
||||
ErrInvalidParams: 'Erro de parâmetro de solicitação: {{ .detail }}'
|
||||
ErrTokenParse: 'Erro de geração de token: {{ .detail }}'
|
||||
ErrInitialPassword: 'A senha original está incorreta'
|
||||
ErrInternalServer: 'Erro interno do servidor: {{ .detail }}'
|
||||
ErrRecordExist: 'O registro já existe'
|
||||
ErrInvalidParams: 'Requisição inválida: {{ .detail }}'
|
||||
ErrTokenParse: 'Erro de token: {{ .detail }}'
|
||||
ErrInitialPassword: 'Senha original incorreta'
|
||||
ErrInternalServer: 'Erro interno: {{ .detail }}'
|
||||
ErrRecordExist: 'Registro já existe'
|
||||
ErrRecordNotFound: 'Registro não encontrado'
|
||||
ErrStructTransform: 'Falha na conversão de tipo: {{ .err }}'
|
||||
ErrNotLogin: 'Usuário não logado: {{ .detail }}'
|
||||
ErrPasswordExpired: 'A senha atual expirou: {{ .detail }}'
|
||||
ErrNotSupportType: 'O sistema não suporta o tipo atual: {{ .name }}'
|
||||
ErrProxy: 'Erro de solicitação, verifique o status do nó: {{ .detail }}'
|
||||
ErrApiConfigStatusInvalid: 'O acesso à interface da API é proibido: {{ .detail }}'
|
||||
ErrApiConfigKeyInvalid: 'Erro de chave da interface da API: {{ .detail }}'
|
||||
ErrApiConfigIPInvalid: 'O IP usado para chamar a interface da API não está na lista de permissões: {{ .detail }}'
|
||||
ErrApiConfigDisable: 'Esta interface proíbe o uso de chamadas de interface de API: {{ .detail }}'
|
||||
ErrApiConfigKeyTimeInvalid: 'Erro de registro de data e hora da interface da API: {{ .detail }}'
|
||||
StartPushSSLToNode: "Iniciando o envio do certificado para o nó"
|
||||
PushSSLToNodeFailed: "Falha ao enviar o certificado para o nó: {{ .err }}"
|
||||
PushSSLToNodeSuccess: "Certificado enviado com sucesso para o nó"
|
||||
ErrShutDown: "Comando terminado manualmente!"
|
||||
|
||||
ErrMinQuickJump: "Defina pelo menos uma entrada de salto rápido!"
|
||||
ErrMaxQuickJump: "Você pode definir até quatro entradas de salto rápido!"
|
||||
|
||||
#comum
|
||||
ErrUsernameIsExist: 'Nome de usuário já existe'
|
||||
ErrStructTransform: 'Erro de conversão: {{ .err }}'
|
||||
ErrNotLogin: 'Sem sessão: {{ .detail }}'
|
||||
ErrPasswordExpired: 'Senha expirada: {{ .detail }}'
|
||||
ErrNotSupportType: 'Tipo não suportado: {{ .name }}'
|
||||
ErrProxy: 'Requisição falhou: {{ .detail }}'
|
||||
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 }}'
|
||||
ErrShutDown: 'Comando parado manualmente'
|
||||
ErrMinQuickJump: 'Adicione pelo menos um atalho rápido'
|
||||
ErrMaxQuickJump: 'Máximo 4 atalhos rápidos'
|
||||
ErrUsernameIsExist: 'Usuário já existe'
|
||||
ErrNameIsExist: 'Nome já existe'
|
||||
ErrDemoEnvironment: 'Servidor de demonstração, esta operação é proibida!'
|
||||
ErrCmdTimeout: 'Tempo limite de execução do comando expirou!'
|
||||
ErrCmdIllegal: 'Há caracteres ilegais no comando de execução, modifique-o e tente novamente!'
|
||||
ErrPortExist: 'A porta {{ .port }} já está ocupada por {{ .type }} [{{ .name }}]'
|
||||
ErrDemoEnvironment: 'Indisponível em demo'
|
||||
ErrCmdTimeout: 'Comando expirou'
|
||||
ErrCmdIllegal: 'Comando tem caracteres inválidos'
|
||||
ErrPortExist: 'Porta {{ .port }} já ocupada por {{ .type }} [{{ .name }}]'
|
||||
TYPE_APP: 'Aplicativo'
|
||||
TYPE_RUNTIME: 'Ambiente de tempo de execução'
|
||||
TYPE_DOMAIN: 'Nome de domínio'
|
||||
@@ -39,45 +33,40 @@ Failed: 'Falhou'
|
||||
SystemRestart: 'Tarefa interrompida devido à reinicialização do sistema'
|
||||
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.'
|
||||
Decrypt: "Descriptografar"
|
||||
|
||||
#agent
|
||||
ErrAgentAccountBound: 'Esta conta está vinculada a um agente e não pode ser excluída. Verifique e tente novamente!'
|
||||
ErrAgentAccountUnavailable: 'As informações de conexão da conta não estão disponíveis. Erro: {{ .err }}. Verifique e tente novamente!'
|
||||
ErrAgentProviderNotSupported: 'Este provedor de agente não é suportado. Verifique e tente novamente!'
|
||||
ErrAgentAccountRequired: 'Selecione uma conta de agente e tente novamente.'
|
||||
ErrAgentAccountNotVerified: 'A conta não foi verificada. Verifique e tente novamente!'
|
||||
ErrAgentProviderMismatch: 'O provedor da conta não corresponde. Verifique e tente novamente!'
|
||||
ErrAgentBaseURLRequired: 'Base URL não pode estar vazio. Verifique e tente novamente!'
|
||||
ErrAgentApiKeyRequired: 'API Key não pode estar vazio. Verifique e tente novamente!'
|
||||
ErrAgentComposeRequired: 'O conteúdo personalizado do compose não pode estar vazio. Verifique e tente novamente!'
|
||||
ErrAgentIDRequired: 'ID do agente não pode estar vazio. Verifique e tente novamente!'
|
||||
ErrAgentAccountIDRequired: 'ID da conta não pode estar vazio. Verifique e tente novamente!'
|
||||
|
||||
#backup
|
||||
Decrypt: 'Descriptografar'
|
||||
ErrAgentAccountBound: 'Conta vinculada a agente'
|
||||
ErrAgentAccountUnavailable: 'Conexão da conta indisponível: {{ .err }}'
|
||||
ErrAgentProviderNotSupported: 'Provedor de agente não suportado'
|
||||
ErrAgentAccountRequired: 'Selecione uma conta de agente primeiro'
|
||||
ErrAgentAccountNotVerified: 'Conta de agente não verificada'
|
||||
ErrAgentProviderMismatch: 'Provedor de agente diferente'
|
||||
ErrAgentBaseURLRequired: 'URL base obrigatória'
|
||||
ErrAgentApiKeyRequired: 'Chave API obrigatória'
|
||||
ErrAgentComposeRequired: 'Conteúdo de compose obrigatório'
|
||||
ErrAgentIDRequired: 'ID do agente obrigatório'
|
||||
ErrAgentAccountIDRequired: 'ID da conta obrigatório'
|
||||
ErrAgentLimitReached: 'A edição Community suporta até {{ .max }} agentes de IA. Atualize para a edição Professional para remover o limite'
|
||||
Localhost: 'Máquina Local'
|
||||
ErrBackupInUsed: 'A conta de backup foi usada na tarefa agendada e não pode ser excluída.'
|
||||
ErrBackupCheck: 'Falha na conexão de teste da conta de backup {{ .err }}'
|
||||
ErrBackupLocalDelete: 'A exclusão da conta de backup do servidor local ainda não é suportada'
|
||||
ErrBackupLocalCreate: 'A criação de contas de backup do servidor local ainda não é suportada'
|
||||
|
||||
#aplicativo
|
||||
ErrPortInUsed: 'A porta {{ .detail }} já está ocupada!'
|
||||
ErrBackupInUsed: 'Conta de backup em uso por tarefa'
|
||||
ErrBackupCheck: 'Teste de conexão falhou: {{ .err }}'
|
||||
ErrBackupLocalDelete: 'Não é permitido excluir contas locais'
|
||||
ErrBackupLocalCreate: 'Não é permitido criar contas locais'
|
||||
ErrPortInUsed: 'A porta {{ .detail }} já está ocupada'
|
||||
ErrAppLimit: 'O número de aplicativos instalados excedeu o limite'
|
||||
ErrNotInstall: 'Aplicativo não instalado'
|
||||
ErrPortInOtherApp: 'A porta {{ .port }} já está ocupada pelo aplicativo {{ .apps }}!'
|
||||
ErrDbUserNotValid: 'Banco de dados existente, nome de usuário e senha não correspondem!'
|
||||
ErrUpdateBuWebsite: 'O aplicativo foi atualizado com sucesso, mas a modificação do arquivo de configuração do site falhou. Por favor, verifique a configuração! '
|
||||
Err1PanelNetworkFailed: 'Falha na criação da rede de contêiner padrão! {{ .detalhe }}'
|
||||
ErrFileParse: 'Falha na análise do arquivo docker-compose do aplicativo!'
|
||||
ErrPortInOtherApp: 'A porta {{ .port }} já está ocupada pelo aplicativo {{ .apps }}'
|
||||
ErrDbUserNotValid: 'Banco de dados existente, nome de usuário e senha não correspondem'
|
||||
ErrUpdateBuWebsite: 'O aplicativo foi atualizado com sucesso, mas a modificação do arquivo de configuração do site falhou., verifique a configuração'
|
||||
Err1PanelNetworkFailed: 'Falha na criação da rede de contêiner padrão {{ .detalhe }}'
|
||||
ErrFileParse: 'Falha na análise do arquivo docker-compose do aplicativo'
|
||||
ErrInstallDirNotFound: 'O diretório de instalação não existe. Se precisar desinstalar, selecione Forçar desinstalação'
|
||||
AppStoreIsUpToDate: 'A loja de aplicativos já é a versão mais recente'
|
||||
LocalAppVersionNull: 'O aplicativo {{ .name }} não está sincronizado com a versão! Não é possível adicionar à lista de aplicativos'
|
||||
LocalAppVersionErr: '{{ .name }} sincronização da versão {{ .version }} falhou! {{ .err }}'
|
||||
LocalAppVersionNull: 'O aplicativo {{ .name }} não está sincronizado com a versão Não é possível adicionar à lista de aplicativos'
|
||||
LocalAppVersionErr: '{{ .name }} sincronização da versão {{ .version }} falhou {{ .err }}'
|
||||
ErrFileNotFound: 'arquivo {{ .name }} não existe'
|
||||
ErrFileParseApp: 'Falha na análise do arquivo {{ .name }} {{ .err }}'
|
||||
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'
|
||||
ErrCreateHttpClient: 'Falha ao criar solicitação {{ .err }}'
|
||||
ErrHttpReqTimeOut: 'Tempo limite da solicitação esgotado {{ .err }}'
|
||||
@@ -85,69 +74,63 @@ 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'
|
||||
ErrContainerMsg: 'O contêiner {{ .name }} está anormal. Por favor, 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 }}'
|
||||
ErrVersionTooLow: 'A versão atual do 1Panel é muito antiga para atualizar a App Store. Por favor, 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'
|
||||
AppStoreIsSyncing: 'A App Store está sincronizando, tente novamente mais tarde'
|
||||
ErrGetCompose: 'Falha ao obter o arquivo docker-compose.yml! {{ .detail }}'
|
||||
AppStoreIsSyncing: 'A App Store está sincronizando mais tarde'
|
||||
ErrGetCompose: 'Falha ao obter o arquivo docker-compose.yml {{ .detail }}'
|
||||
ErrAppWarn: 'Status anormal, verifique o log'
|
||||
ErrAppParamKey: 'O campo de parâmetro {{ .name }} está anormal'
|
||||
ErrAppUpgrade: 'Falha na atualização do aplicativo {{ .name }} {{ .err }}'
|
||||
AppRecover: 'Reverter aplicativo {{ .name }}'
|
||||
PullImageStart: 'Comece a extrair a imagem [{{ .name }}]'
|
||||
PullImageSuccess: 'Imagem retirada com sucesso'
|
||||
AppStoreIsLastVersion: 'A App Store já é a versão mais recente'
|
||||
AppStoreSyncSuccess: 'Sincronização da App Store bem-sucedida'
|
||||
SyncAppDetail: 'Sincronizar configuração do aplicativo'
|
||||
AppVersionNotMatch: 'o aplicativo {{ .name }} requer uma versão superior do 1Panel, ignorando a sincronização'
|
||||
MoveSiteDir: "Detecção de alteração no diretório do site. É necessário migrar o diretório do site OpenResty para {{ .name }}"
|
||||
MoveSiteDir: 'Detecção de alteração no diretório do site. É necessário migrar o diretório do site OpenResty para {{ .name }}'
|
||||
MoveSiteDirSuccess: 'Migração bem-sucedida do diretório do site'
|
||||
DeleteRuntimePHP: 'Excluir tempo de execução do PHP'
|
||||
CustomAppStoreFileValid: 'Os pacotes da App Store precisam estar no formato .tar.gz'
|
||||
CustomAppStoreFileValid: 'Os pacotes da App Store precisam estar no formato.tar.gz'
|
||||
PullImageTimeout: 'Tempo limite para puxar imagem, tente aumentar a aceleração da imagem ou altere para outra aceleração de imagem'
|
||||
ErrAppIsDown: 'O status do aplicativo {{ .name }} é anormal, verifique'
|
||||
ErrCustomApps: 'Há um aplicativo instalado, desinstale-o primeiro'
|
||||
ErrCustomRuntimes: 'Há um ambiente de execução instalado, exclua-o primeiro'
|
||||
ErrAppVersionDeprecated: "O aplicativo {{ .name }} não é compatível com a versão atual do 1Panel, ignorado"
|
||||
ErrDockerFailed: "O estado do Docker está anormal, verifique o status do serviço"
|
||||
ErrDockerComposeCmdNotFound: "O comando Docker Compose não existe, por favor, instale este comando na máquina host primeiro"
|
||||
UseExistImage: 'Falha ao puxar a imagem, usando imagem existente'
|
||||
|
||||
#ssh
|
||||
ExportIP: "IP de Login"
|
||||
ExportArea: "Localização"
|
||||
ExportPort: "Porta"
|
||||
ExportAuthMode: "Método de Login"
|
||||
ExportUser: "Usuário"
|
||||
ExportStatus: "Status de Login"
|
||||
ExportDate: "Hora"
|
||||
|
||||
#arquivo
|
||||
ErrAppVersionDeprecated: 'O aplicativo {{ .name }} não é compatível com a versão atual do 1Panel, ignorado'
|
||||
ErrDockerFailed: 'O estado do Docker está anormal, verifique o status do serviço'
|
||||
ErrDockerComposeCmdNotFound: 'O comando Docker Compose não existe, instale este comando na máquina host primeiro'
|
||||
UseExistImage: 'A imagem já existe, usando imagem existente'
|
||||
ErrDatabaseNotFound: 'O banco de dados {{ .name }} não existe'
|
||||
ExportIP: 'IP de Login'
|
||||
ExportArea: 'Localização'
|
||||
ExportPort: 'Porta'
|
||||
ExportAuthMode: 'Método de Login'
|
||||
ExportUser: 'Usuário'
|
||||
ExportStatus: 'Status de Login'
|
||||
ExportDate: 'Hora'
|
||||
ErrFileCanNotRead: 'Este arquivo não suporta visualização'
|
||||
ErrFileToLarge: 'O arquivo é maior que 10M e não pode ser aberto'
|
||||
ErrPathNotFound: 'O diretório não existe'
|
||||
ErrMovePathFailed: 'O caminho de destino não pode conter o caminho original!'
|
||||
ErrLinkPathNotFound: 'O caminho de destino não existe!'
|
||||
ErrFileIsExist: 'O arquivo ou pasta já existe!'
|
||||
ErrMovePathFailed: 'O caminho de destino não pode conter o caminho original'
|
||||
ErrLinkPathNotFound: 'O caminho de destino não existe'
|
||||
ErrFileIsExist: 'O arquivo ou pasta já existe'
|
||||
ErrFileUpload: '{{ .name }} falhou ao carregar o arquivo {{ .detail }}'
|
||||
ErrFileDownloadDir: 'A pasta de download não é suportada'
|
||||
ErrCmdNotFound: 'O comando {{ .name}} não existe, instale este comando no host primeiro'
|
||||
ErrCmdNotFound: 'O comando {{ .name }} não existe, instale este comando no host primeiro'
|
||||
ErrSourcePathNotFound: 'O diretório de origem não existe'
|
||||
ErrFavoriteExist: 'Este caminho já foi favorito'
|
||||
ErrInvalidChar: 'Caracteres ilegais não são permitidos'
|
||||
ErrPathNotDelete: 'O diretório selecionado não pode ser excluído'
|
||||
ErrLogFileToLarge: "Fail log melebihi 500MB, tidak boleh dibuka"
|
||||
FileDropFailed: "Falha ao limpar arquivo {{ .name }}: {{ .err }}"
|
||||
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"
|
||||
ErrBadDecrypt: "Erro de senha de descriptografia do pacote compactado, descompactação falhou, verifique e tente novamente!"
|
||||
|
||||
#site
|
||||
ErrLogFileToLarge: 'Fail log melebihi 500MB, tidak boleh dibuka'
|
||||
FileDropFailed: 'Falha ao limpar arquivo {{ .name }}: {{ .err }}'
|
||||
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'
|
||||
ErrBadDecrypt: 'Erro de senha de descriptografia do pacote compactado, descompactação falhou, verifique e'
|
||||
ErrAliasIsExist: 'Alias já existe'
|
||||
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 }}'
|
||||
ErrPHPResource: 'O ambiente operacional local não suporta comutação! '
|
||||
ErrPHPResource: 'O ambiente operacional local não suporta comutação'
|
||||
ErrPathPermission: 'Uma pasta com permissões diferentes de 1000:1000 foi detectada no diretório de índice, o que pode causar um erro de acesso negado no site. Clique no botão Salvar acima'
|
||||
ErrDomainIsUsed: 'O nome de domínio já está sendo usado pelo site [{{ .name }}]'
|
||||
ErrDomainFormat: 'o formato do nome de domínio {{ .name }} está incorreto'
|
||||
@@ -155,11 +138,11 @@ ErrDefaultAlias: 'padrão é um código reservado, use outro código'
|
||||
ErrParentWebsite: 'Você precisa excluir o subsite {{ .name }} primeiro'
|
||||
ErrBuildDirNotFound: 'O diretório de compilação não existe'
|
||||
ErrImageNotExist: 'A imagem do ambiente operacional {{ .name }} não existe, edite novamente o ambiente operacional'
|
||||
ErrProxyIsUsed: "Balanceamento de carga foi usado por proxy reverso, não pode ser excluído"
|
||||
ErrSSLValid: 'O arquivo do certificado está anormal, verifique o status do certificado!'
|
||||
ErrWebsiteDir: "Por favor, selecione um diretório dentro do diretório do site."
|
||||
ErrComposerFileNotFound: "O arquivo composer.json não existe"
|
||||
ErrRuntimeNoPort: "O ambiente de tempo de execução não está configurado com uma porta, edite o ambiente de tempo de execução primeiro."
|
||||
ErrProxyIsUsed: 'Balanceamento de carga foi usado por proxy reverso, não pode ser excluído'
|
||||
ErrSSLValid: 'O arquivo do certificado está anormal, verifique o status do certificado'
|
||||
ErrWebsiteDir: ', selecione um diretório dentro do diretório do site.'
|
||||
ErrComposerFileNotFound: 'O arquivo composer.json não existe'
|
||||
ErrRuntimeNoPort: 'O ambiente de tempo de execução não está configurado com uma porta, edite o ambiente de tempo de execução primeiro.'
|
||||
Status: 'Status'
|
||||
start: 'Iniciar'
|
||||
stop: 'Parar'
|
||||
@@ -169,14 +152,12 @@ pause: 'Pausar'
|
||||
unpause: 'Retomar'
|
||||
remove: 'Excluir'
|
||||
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'
|
||||
Set: 'Configurações'
|
||||
|
||||
#ssl
|
||||
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'
|
||||
ErrSSLApply: 'Renovação do certificado bem-sucedida, falha na recarga do Openresty, verifique a configuração!'
|
||||
ErrSSLApply: 'Renovação do certificado bem-sucedida, falha na recarga do Openresty, verifique a configuração'
|
||||
ErrEmailIsExist: 'A caixa de correio já existe'
|
||||
ErrSSLKeyNotFound: 'O arquivo de chave privada não existe'
|
||||
ErrSSLCertificateNotFound: 'O arquivo de certificado não existe'
|
||||
@@ -188,8 +169,8 @@ ApplySSLStart: 'Comece a solicitar um certificado, nome de domínio [{{ .domain
|
||||
dnsAccount: 'DNS Automático'
|
||||
dnsManual: 'Manual DNS'
|
||||
http: 'HTTP'
|
||||
ApplySSLFailed: 'Falha na solicitação de certificado [{{ .domain }}], {{ .detail }} '
|
||||
ApplySSLSuccess: 'Solicitação de certificado [{{ .domain }}] realizada com sucesso! ! '
|
||||
ApplySSLFailed: 'Falha na solicitação de certificado [{{ .domain }}], {{ .detail }}'
|
||||
ApplySSLSuccess: 'Solicitação de certificado [{{ .domain }}] realizada com sucesso'
|
||||
DNSAccountName: 'Conta DNS [{{ .name }}] fornecedor [{{ .type }}]'
|
||||
PushDirLog: 'Certificado enviado para o diretório [{{ .path }}] {{ .status }}'
|
||||
ErrDeleteCAWithSSL: 'A organização atual tem um certificado que foi emitido e não pode ser excluído.'
|
||||
@@ -204,94 +185,79 @@ ExecShellSuccess: 'Execução do script bem-sucedida'
|
||||
StartUpdateSystemSSL: 'Iniciar atualização do certificado do sistema'
|
||||
UpdateSystemSSLSuccess: 'Atualizar certificado do sistema com sucesso'
|
||||
ErrWildcardDomain: 'Não é possível solicitar certificado de nome de domínio curinga no modo HTTP'
|
||||
ErrApplySSLCanNotDelete: "O certificado {{.name}} que está sendo solicitado não pode ser excluído, tente novamente mais tarde."
|
||||
|
||||
#mysql
|
||||
ErrApplySSLCanNotDelete: 'O certificado {{ .name }} que está sendo solicitado não pode ser excluído mais tarde.'
|
||||
StartPushSSLToNode: 'Iniciando o envio do certificado para o nó'
|
||||
PushSSLToNodeFailed: 'Falha ao enviar o certificado para o nó: {{ .err }}'
|
||||
PushSSLToNodeSuccess: 'Certificado enviado com sucesso para o nó'
|
||||
ErrUserIsExist: 'O usuário 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'
|
||||
ErrRemoteExist: 'O banco de dados remoto já existe com este nome, modifique-o e tente novamente'
|
||||
ErrLocalExist: 'O nome já existe no banco de dados local, modifique-o e tente novamente'
|
||||
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 }}, por favor 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 }}, por favor aguarde..."
|
||||
Arg: "Argumento"
|
||||
|
||||
#redis
|
||||
ErrTypeOfRedis: 'O tipo de arquivo de recuperação não corresponde ao método de persistência atual, modifique-o e tente novamente'
|
||||
|
||||
#recipiente
|
||||
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!"
|
||||
ErrObjectBeDependent: "Esta imagem é dependida por outras imagens e não pode ser excluída!"
|
||||
ErrPortRules: 'O número da porta não corresponde, digite novamente!'
|
||||
ErrPgImagePull: 'Tempo limite para extração de imagem. Configure a aceleração de imagem ou extraia manualmente a imagem {{ .name }} e tente novamente'
|
||||
PruneHelper: "Esta limpeza {{ .name }} liberou espaço em disco {{ .size }}"
|
||||
ImageRemoveHelper: "Excluída a imagem {{ .name }}, liberando {{ .size }} de espaço em disco"
|
||||
BuildCache: "Cache de construção"
|
||||
Volume: "Volume de armazenamento"
|
||||
Network: "Rede"
|
||||
PruneStart: "Limpando em andamento, por favor aguarde..."
|
||||
|
||||
#tempo de execução
|
||||
ErrFileNotExist: 'O arquivo {{ .detail }} não existe! Verifique a integridade do arquivo de origem!'
|
||||
ErrRemoteExist: 'O banco de dados remoto já existe com este nome, modifique-o e'
|
||||
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...'
|
||||
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'
|
||||
ErrTypeOfRedis: 'O tipo de arquivo de recuperação não corresponde ao método de persistência atual, modifique-o e'
|
||||
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'
|
||||
ErrObjectBeDependent: 'Esta imagem é dependida por outras imagens e não pode ser excluída'
|
||||
ErrPortRules: 'O número da porta não corresponde, digite novamente'
|
||||
ErrPgImagePull: 'Tempo limite para extração de imagem. Configure a aceleração de imagem ou extraia manualmente a imagem {{ .name }} e'
|
||||
PruneHelper: 'Esta limpeza {{ .name }} liberou espaço em disco {{ .size }}'
|
||||
ImageRemoveHelper: 'Excluída a imagem {{ .name }}, liberando {{ .size }} de espaço em disco'
|
||||
BuildCache: 'Cache de construção'
|
||||
Volume: 'Volume de armazenamento'
|
||||
Network: 'Rede'
|
||||
PruneStart: 'Limpando em andamento aguarde...'
|
||||
ErrFileNotExist: 'O arquivo {{ .detail }} não existe Verifique a integridade do arquivo de origem'
|
||||
ErrImageBuildErr: 'Falha na criação da imagem'
|
||||
ErrImageExist: "A imagem já existe! Por favor, modifique o nome da imagem."
|
||||
ErrImageExist: 'A imagem já existe, modifique o nome da imagem.'
|
||||
ErrDelWithWebsite: 'O ambiente operacional já está associado a um site e não pode ser excluído'
|
||||
ErrRuntimeStart: 'Falha na inicialização'
|
||||
ErrPackageJsonNotFound: 'o arquivo package.json não existe'
|
||||
ErrScriptsNotFound: 'O item de configuração de scripts não foi encontrado em package.json'
|
||||
ErrContainerNameNotFound: 'Não foi possível obter o nome do contêiner, verifique o arquivo .env'
|
||||
ErrNodeModulesNotFound: 'A pasta node_modules não existe! Edite o ambiente de execução ou aguarde até que o ambiente de execução inicie com sucesso'
|
||||
ErrContainerNameNotFound: 'Não foi possível obter o nome do contêiner, verifique o arquivo.env'
|
||||
ErrNodeModulesNotFound: 'A pasta node_modules não existe Edite o ambiente de execução ou aguarde até que o ambiente de execução inicie com sucesso'
|
||||
ErrContainerNameIsNull: 'O nome do contêiner não existe'
|
||||
ErrPHPPortIsDefault: "Port 9000 adalah port lalai, sila ubah dan cuba lagi"
|
||||
ErrPHPRuntimePortFailed: "Port {{ .name }} telah digunakan oleh persekitaran runtime semasa, sila ubah dan cuba lagi"
|
||||
|
||||
#ferramenta
|
||||
ErrPHPPortIsDefault: 'Port 9000 adalah port lalai, sila ubah dan cuba lagi'
|
||||
ErrPHPRuntimePortFailed: 'Port {{ .name }} telah digunakan oleh persekitaran runtime semasa, sila ubah dan cuba lagi'
|
||||
ErrConfigNotFound: 'O arquivo de configuração não existe'
|
||||
ErrConfigParse: 'O formato do arquivo de configuração está incorreto'
|
||||
ErrConfigIsNull: 'O arquivo de configuração não pode estar vazio'
|
||||
ErrConfigDirNotFound: 'O diretório de execução não existe'
|
||||
ErrConfigAlreadyExist: 'Um arquivo de configuração com o mesmo nome já existe'
|
||||
ErrUserFindErr: 'Falha na pesquisa do usuário {{ .name }} {{ .err }}'
|
||||
|
||||
#cronjob
|
||||
CutWebsiteLogSuccess: '{{ .name }} registro do site cortado com sucesso, caminho de backup {{ .path }}'
|
||||
HandleShell: 'Executar script {{ .name }}'
|
||||
HandleCurl: "Acessar URL {{ .name }}"
|
||||
HandleCurl: 'Acessar URL {{ .name }}'
|
||||
HandleNtpSync: 'Sincronização de hora do sistema'
|
||||
HandleSystemClean: 'Limpeza de cache do sistema'
|
||||
SystemLog: 'Log do Sistema'
|
||||
CutWebsiteLog: 'Rotacionar Log do Website'
|
||||
FileOrDir: 'Diretório / Arquivo'
|
||||
UploadFile: 'Enviando arquivo de backup {{ .file }} para {{ .backup }}'
|
||||
Upload: "Enviar"
|
||||
IgnoreBackupErr: "Backup falhou, erro: {{ .detail }}, ignorando este erro..."
|
||||
IgnoreUploadErr: "Upload falhou, erro: {{ .detail }}, ignorando este erro..."
|
||||
LoadBackupFailed: "Falha ao obter conexão da conta de backup, erro: {{ .detail }}"
|
||||
InExecuting: "A tarefa atual está sendo executada, não repita a execução!"
|
||||
NoSuchResource: "Nenhum conteúdo de backup encontrado no banco de dados, ignorando..."
|
||||
CleanLog: "Limpar log"
|
||||
CleanLogByName: "Limpar log de {{.name}}"
|
||||
WafIpGroupNotFound: "Grupo de IP do WAF não encontrado. Por favor, 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 tente novamente!'
|
||||
ErrBanAction: 'Falha na configuração. O serviço atual {{ .name }} não está disponível. Verifique e tente novamente!'
|
||||
ErrClamdscanNotFound: 'O comando clamdscan não foi detectado, consulte a documentação para instalá-lo!'
|
||||
TaskSwapSet: "Configurar Swap"
|
||||
SetSwap: "Configurar Swap {{ .path }} - {{ .size }}"
|
||||
CreateSwap: "Criar Arquivo Swap"
|
||||
FormatSwap: "Formatar Arquivo Swap"
|
||||
EnableSwap: "Ativar Swap"
|
||||
|
||||
#tamper
|
||||
CleanTamperSetting: "Limpar configurações de proteção históricas"
|
||||
SetTamperWithRules: "Iniciar proteção de diretório de acordo com as regras"
|
||||
ProtectDir: "Proteger diretório {{ .name }}"
|
||||
IgnoreFile: "Proteger arquivo {{ .name }}"
|
||||
TamperSetSuccessful: "Configurações de proteção concluídas, iniciando monitoramento dos seguintes diretórios:"
|
||||
|
||||
#waf
|
||||
Upload: 'Enviar'
|
||||
IgnoreBackupErr: 'Backup falhou, erro: {{ .detail }}, ignorando este erro...'
|
||||
IgnoreUploadErr: 'Upload falhou, erro: {{ .detail }}, ignorando este erro...'
|
||||
LoadBackupFailed: 'Falha ao obter conexão da conta de backup, erro: {{ .detail }}'
|
||||
InExecuting: 'A tarefa atual está sendo executada, não repita a execução'
|
||||
NoSuchResource: 'Nenhum conteúdo de backup encontrado no banco de dados, ignorando...'
|
||||
CleanLog: 'Limpar log'
|
||||
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.'
|
||||
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'
|
||||
ErrClamdscanNotFound: 'O comando clamdscan não foi detectado, consulte a documentação para instalá-lo'
|
||||
TaskSwapSet: 'Configurar Swap'
|
||||
SetSwap: 'Configurar Swap {{ .path }} - {{ .size }}'
|
||||
CreateSwap: 'Criar Arquivo Swap'
|
||||
FormatSwap: 'Formatar Arquivo Swap'
|
||||
EnableSwap: 'Ativar Swap'
|
||||
CleanTamperSetting: 'Limpar configurações de proteção históricas'
|
||||
SetTamperWithRules: 'Iniciar proteção de diretório de acordo com as regras'
|
||||
ProtectDir: 'Proteger diretório {{ .name }}'
|
||||
IgnoreFile: 'Proteger arquivo {{ .name }}'
|
||||
TamperSetSuccessful: 'Configurações de proteção concluídas, iniciando monitoramento dos seguintes diretórios:'
|
||||
ErrScope: 'A modificação desta configuração não é suportada'
|
||||
ErrStateChange: 'Falha na alteração de estado'
|
||||
ErrRuleExist: 'A regra já existe'
|
||||
@@ -299,7 +265,7 @@ ErrRuleNotExist: 'A regra não existe'
|
||||
ErrParseIP: 'Formato de IP errado'
|
||||
ErrDefaultIP: 'padrão é um nome reservado, altere-o para outro nome'
|
||||
ErrGroupInUse: 'O grupo de IP é usado pela lista negra/lista branca e não pode ser excluído'
|
||||
ErrIPGroupAclUse: "O grupo de IP está sendo usado por regras personalizadas do site {{ .name }}, não pode ser excluído"
|
||||
ErrIPGroupAclUse: 'O grupo de IP está sendo usado por regras personalizadas do site {{ .name }}, não pode ser excluído'
|
||||
ErrGroupExist: 'O nome do grupo IP já existe'
|
||||
ErrIPRange: 'Intervalo de IP errado'
|
||||
ErrIPExist: 'IP já existe'
|
||||
@@ -310,10 +276,10 @@ xss: 'XSS'
|
||||
phpExec: 'Execução de script PHP'
|
||||
oneWordTrojan: 'Cavalo de Tróia de Uma Palavra'
|
||||
appFilter: 'Aplicar filtragem de diretório perigosa'
|
||||
webshell: 'Webshell'
|
||||
webShell: 'Webshell'
|
||||
args: 'Regras de parâmetros'
|
||||
protocolFilter: 'Filtragem de protocolo'
|
||||
javaFileter: 'Filtro de arquivo perigoso Java'
|
||||
javaFilter: 'Filtro de arquivo perigoso Java'
|
||||
scannerFilter: 'Filtro do scanner'
|
||||
escapeFilter: 'filtro de escape'
|
||||
customRule: 'Regra personalizada'
|
||||
@@ -343,10 +309,9 @@ ErrDBNotExist: 'O banco de dados não existe'
|
||||
allow: 'permitir'
|
||||
deny: 'negar'
|
||||
OpenrestyNotFound: 'Openresty não está instalado'
|
||||
remoteIpIsNull: "A lista de IP está vazia"
|
||||
OpenrestyVersionErr: "A versão do Openresty é muito baixa, por favor atualize o Openresty para 1.27.1.2-2-2-focal"
|
||||
|
||||
#tarefa
|
||||
remoteIpIsNull: 'A lista de IP está vazia'
|
||||
OpenrestyVersionErr: 'A versão do Openresty é muito baixa atualize o Openresty para 1.27.1.2-2-2-focal'
|
||||
ErrFileTooLarge: 'O arquivo excede 1 MB e não pode ser enviado'
|
||||
TaskStart: '{{ .name }} A tarefa inicia [START]'
|
||||
TaskEnd: '{{ .name }} Tarefa concluída [CONCLUÍDA]'
|
||||
TaskFailed: '{{ .name }} tarefa falhou'
|
||||
@@ -362,18 +327,18 @@ TaskDelete: 'Excluir'
|
||||
TaskUpgrade: 'Atualizar'
|
||||
TaskUpdate: 'Atualizar'
|
||||
TaskRestart: 'Reiniciar'
|
||||
TaskProtect: "Proteger"
|
||||
Backup de Tarefa: 'Backup'
|
||||
TaskProtect: 'Proteger'
|
||||
TaskBackup: 'Backup'
|
||||
TaskRecover: 'Recuperar'
|
||||
TaskRollback: 'Reverter'
|
||||
TaskPull: 'Puxar'
|
||||
TaskCommit: 'Commit'
|
||||
TaskBuild: 'Construir'
|
||||
TaskPush: 'Empurrar'
|
||||
TaskClean: "Limpeza"
|
||||
TaskClean: 'Limpeza'
|
||||
TaskHandle: 'Executar'
|
||||
TaskImport: "Importar"
|
||||
TaskExport: "Exportar"
|
||||
TaskImport: 'Importar'
|
||||
TaskExport: 'Exportar'
|
||||
Website: 'Site'
|
||||
App: 'Aplicativo'
|
||||
Runtime: 'Ambiente de tempo de execução'
|
||||
@@ -405,18 +370,12 @@ RuntimeExtension: 'Extensão do ambiente de tempo de execução'
|
||||
TaskIsExecuting: 'A tarefa está em execução'
|
||||
CustomAppstore: 'Armazém de aplicativos personalizados'
|
||||
TaskExec: 'Executar'
|
||||
TaskBatch: "Operação em Lote"
|
||||
TaskBatch: 'Operação em Lote'
|
||||
FileConvert: 'Conversão de Formato de Arquivo'
|
||||
|
||||
# task - clam
|
||||
Clamscan: "Escanear {{ .name }}"
|
||||
TaskScan: "Escanear"
|
||||
|
||||
# tarefa - ai
|
||||
Clamscan: 'Escanear {{ .name }}'
|
||||
TaskScan: 'Escanear'
|
||||
OllamaModelPull: 'Puxar modelo Ollama {{ .name }}'
|
||||
OllamaModelSize: 'Obtenha o tamanho do modelo Ollama {{ .name }}'
|
||||
|
||||
# tarefa-instantânea
|
||||
Snapshot: 'Instantâneo'
|
||||
SnapDBInfo: 'Escrever informações do banco de dados 1Panel'
|
||||
SnapCopy: 'Copiar arquivos e diretórios {{ .name }}'
|
||||
@@ -442,7 +401,6 @@ SnapCompressSize: 'Tamanho do arquivo de instantâneo {{ .name }}'
|
||||
SnapUpload: 'Carregar arquivo de instantâneo'
|
||||
SnapUploadTo: 'Carregar arquivo de instantâneo para {{ .name }}'
|
||||
SnapUploadRes: 'Carregar arquivo de instantâneo para {{ .name }}'
|
||||
|
||||
SnapshotRecover: 'Restauração de instantâneo'
|
||||
RecoverDownload: 'Baixar arquivo de instantâneo'
|
||||
Download: 'Baixar'
|
||||
@@ -450,10 +408,10 @@ RecoverDownloadAccount: 'Obter conta de backup de download de instantâneo {{ .n
|
||||
RecoverDecompress: 'Descompacte arquivos compactados de instantâneos'
|
||||
Decompress: 'Descompressão'
|
||||
BackupBeforeRecover: 'Fazer backup de dados relacionados ao sistema antes do snapshot'
|
||||
Readjson: 'Ler o arquivo Json no snapshot'
|
||||
ReadjsonPath: 'Obtenha o caminho do arquivo Json no snapshot'
|
||||
ReadjsonContent: 'Ler arquivo Json'
|
||||
ReadjsonMarshal: 'Processamento de escape JSON'
|
||||
ReadJson: 'Ler o arquivo Json no snapshot'
|
||||
ReadJsonPath: 'Obtenha o caminho do arquivo Json no snapshot'
|
||||
ReadJsonContent: 'Ler arquivo Json'
|
||||
ReadJsonMarshal: 'Processamento de escape JSON'
|
||||
RecoverApp: 'Restaurar aplicativos instalados'
|
||||
RecoverWebsite: 'Recuperar diretório de sites'
|
||||
RecoverAppImage: 'Restaurar backup de imagem instantânea'
|
||||
@@ -467,9 +425,6 @@ RecoverDaemonJson: 'Restaurar arquivo daemon.json de configuração do contêine
|
||||
RecoverDBData: 'Recuperar dados do banco de dados'
|
||||
RecoverBackups: 'Restaurar diretório de backup local'
|
||||
RecoverPanelData: 'Diretório de dados de recuperação'
|
||||
|
||||
# tarefa - contêiner
|
||||
ContainerNewCliet: 'Inicializar cliente Docker'
|
||||
ContainerImagePull: 'Puxar imagem do contêiner {{ .name }}'
|
||||
ContainerRemoveOld: 'Remover o contêiner original {{ .name }}'
|
||||
ContainerImageCheck: 'Verifique se a imagem é extraída normalmente'
|
||||
@@ -478,22 +433,13 @@ ContainerRecreate: 'A atualização do contêiner falhou, agora iniciando a rest
|
||||
ContainerCreate: 'Criar um novo contêiner {{ .name }}'
|
||||
ContainerCreateFailed: 'Falha na criação do contêiner, exclua o contêiner com falha'
|
||||
ContainerStartCheck: 'Verifique se o contêiner foi iniciado'
|
||||
|
||||
# tarefa - imagem
|
||||
ImageBuild: 'Construção de imagem'
|
||||
ImageBuildStdoutCheck: 'Analisar conteúdo de saída da imagem'
|
||||
ImageBuildRes: 'Saída da criação da imagem: {{ .name }}'
|
||||
ImagePull: 'Puxar imagem'
|
||||
ImageRepoAuthFromDB: 'Obter informações de autenticação do repositório do banco de dados'
|
||||
ImaegPullRes: 'Saída de extração de imagem: {{ .name }}'
|
||||
ImagePush: 'Enviar imagem'
|
||||
ImageRenameTag: 'Modificar tag de imagem'
|
||||
ImageNewTag: 'Nova tag de imagem {{ .name }}'
|
||||
ImaegPushRes: 'Saída de envio de imagem: {{ .name }}'
|
||||
ComposeCreate: 'Criar uma composição'
|
||||
ComposeCreateRes: 'Compose cria saída: {{ .name }}'
|
||||
|
||||
# tarefa - site
|
||||
BackupNginxConfig: 'Fazer backup do arquivo de configuração do OpenResty do site'
|
||||
CompressFileSuccess: 'Diretório compactado com sucesso, compactado para {{ .name }}'
|
||||
CompressDir: 'Diretório de compressão'
|
||||
@@ -504,40 +450,27 @@ websiteDir: 'Diretório de sites'
|
||||
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'
|
||||
AppAttributesNotMatch: 'O tipo ou nome do aplicativo não corresponde'
|
||||
|
||||
#alerta
|
||||
ErrAlert: 'O formato da mensagem de aviso está incorreto, verifique e tente novamente!'
|
||||
ErrAlertPush: 'Erro ao enviar informações de alerta, verifique e tente novamente!'
|
||||
ErrAlertSave: 'Erro ao salvar as informações do alarme. Verifique e tente novamente!'
|
||||
ErrAlertSync: 'Erro de sincronização de informações de alarme, verifique e tente novamente!'
|
||||
ErrAlertRemote: 'Erro remoto na mensagem de alarme, verifique e tente novamente!'
|
||||
|
||||
#task - runtime
|
||||
ErrInstallExtension: "Já existe uma tarefa de instalação em andamento, aguarde a conclusão da tarefa"
|
||||
|
||||
# alert mail template
|
||||
PanelAlertTitle: "Notificação de Alerta do Painel"
|
||||
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."
|
||||
LicenseExpirationAlert: "Seu Painel {{ .node }}{{ .ip }}, a licença expirará em {{ .day }} dias. Faça login no painel para obter detalhes."
|
||||
CronJobFailedAlert: "Seu Painel {{ .node }}{{ .ip }}, a execução da tarefa agendada {{ .name }} falhou. Faça login no painel para obter detalhes."
|
||||
ClamAlert: "Seu Painel {{ .node }}{{ .ip }}, a tarefa de verificação de vírus detectou {{ .num }} arquivos infectados. Faça login no painel para obter detalhes."
|
||||
WebSiteAlert: "Seu Painel {{ .node }}{{ .ip }}, {{ .num }} sites expirarão em {{ .day }} dias. Faça login no painel para obter detalhes."
|
||||
SSLAlert: "Seu Painel {{ .node }}{{ .ip }}, {{ .num }} certificados SSL expirarão em {{ .day }} dias. Faça login no painel para obter detalhes."
|
||||
DiskUsedAlert: "Seu Painel {{ .node }}{{ .ip }}, o uso do disco {{ .name }} atingiu {{ .used }}. Faça login no painel para obter detalhes."
|
||||
ResourceAlert: "Seu Painel {{ .node }}{{ .ip }}, a taxa de uso médio do {{ .name }} nos últimos {{ .time }} minutos é {{ .used }}. Faça login no painel para obter detalhes."
|
||||
PanelVersionAlert: "Seu Painel {{ .node }}{{ .ip }}, a versão mais recente do painel está disponível para atualização. Faça login no painel para obter detalhes."
|
||||
PanelPwdExpirationAlert: "Seu Painel {{ .node }}{{ .ip }}, a senha do painel expirará em {{ .day }} dias. Faça login no painel para obter detalhes."
|
||||
CommonAlert: "Seu Painel {{ .node }}{{ .ip }}, {{ .msg }}. 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."
|
||||
SSHAndPanelLoginAlert: "Seu Painel {{ .node }}{{ .ip }}, o login {{ .name }} a partir de {{ .loginIp }} é anormal. Faça login no painel para obter detalhes."
|
||||
|
||||
#disk
|
||||
DeviceNotFound: "Dispositivo {{ .name }} não encontrado"
|
||||
DeviceIsMounted: "Dispositivo {{ .name }} está montado, por favor desmonte primeiro"
|
||||
PartitionDiskErr: "Falha ao particionar, {{ .err }}"
|
||||
FormatDiskErr: "Falha ao formatar disco, {{ .err }}"
|
||||
MountDiskErr: "Falha ao montar disco, {{ .err }}"
|
||||
UnMountDiskErr: "Falha ao desmontar disco, {{ .err }}"
|
||||
XfsNotFound: "Sistema de arquivos xfs não detectado, por favor instale xfsprogs primeiro"
|
||||
ErrAlertSync: 'Erro de sincronização de informações de alarme, verifique e'
|
||||
ErrInstallExtension: 'Já existe uma tarefa de instalação em andamento, aguarde a conclusão da tarefa'
|
||||
PanelAlertTitle: 'Notificação de Alerta do Painel'
|
||||
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.'
|
||||
LicenseExpirationAlert: 'Seu Painel {{ .node }}{{ .ip }}, a licença expirará em {{ .day }} dias. Faça login no painel para obter detalhes.'
|
||||
CronJobFailedAlert: 'Seu Painel {{ .node }}{{ .ip }}, a execução da tarefa agendada {{ .name }} falhou. Faça login no painel para obter detalhes.'
|
||||
ClamAlert: 'Seu Painel {{ .node }}{{ .ip }}, a tarefa de verificação de vírus detectou {{ .num }} arquivos infectados. Faça login no painel para obter detalhes.'
|
||||
WebSiteAlert: 'Seu Painel {{ .node }}{{ .ip }}, {{ .num }} sites expirarão em {{ .day }} dias. Faça login no painel para obter detalhes.'
|
||||
SSLAlert: 'Seu Painel {{ .node }}{{ .ip }}, {{ .num }} certificados SSL expirarão em {{ .day }} dias. Faça login no painel para obter detalhes.'
|
||||
DiskUsedAlert: 'Seu Painel {{ .node }}{{ .ip }}, o uso do disco {{ .name }} atingiu {{ .used }}. Faça login no painel para obter detalhes.'
|
||||
ResourceAlert: 'Seu Painel {{ .node }}{{ .ip }}, a taxa de uso médio do {{ .name }} nos últimos {{ .time }} minutos é {{ .used }}. Faça login no painel para obter detalhes.'
|
||||
PanelVersionAlert: 'Seu Painel {{ .node }}{{ .ip }}, a versão mais recente do painel está disponível para atualização. Faça login no painel para obter detalhes.'
|
||||
PanelPwdExpirationAlert: 'Seu Painel {{ .node }}{{ .ip }}, a senha do painel expirará em {{ .day }} dias. Faça login no painel para obter detalhes.'
|
||||
CommonAlert: 'Seu Painel {{ .node }}{{ .ip }}, {{ .msg }}. 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.'
|
||||
SSHAndPanelLoginAlert: 'Seu Painel {{ .node }}{{ .ip }}, o login {{ .name }} a partir de {{ .loginIp }} é anormal. Faça login no painel para obter detalhes.'
|
||||
DeviceNotFound: 'Dispositivo {{ .name }} não encontrado'
|
||||
DeviceIsMounted: 'Dispositivo {{ .name }} está montado desmonte primeiro'
|
||||
PartitionDiskErr: 'Falha ao particionar, {{ .err }}'
|
||||
FormatDiskErr: 'Falha ao formatar disco, {{ .err }}'
|
||||
MountDiskErr: 'Falha ao montar disco, {{ .err }}'
|
||||
XfsNotFound: 'Sistema de arquivos xfs não detectado instale xfsprogs primeiro'
|
||||
|
||||
+169
-236
@@ -1,34 +1,28 @@
|
||||
ErrInvalidParams: 'Ошибка параметра запроса: {{ .detail }}'
|
||||
ErrTokenParse: 'Ошибка генерации токена: {{ .detail }}'
|
||||
ErrInitialPassword: 'Исходный пароль неверный'
|
||||
ErrInternalServer: 'Внутренняя ошибка сервера: {{ .detail }}'
|
||||
ErrInvalidParams: 'Неверный запрос: {{ .detail }}'
|
||||
ErrTokenParse: 'Ошибка токена: {{ .detail }}'
|
||||
ErrInitialPassword: 'Исходный пароль неверен'
|
||||
ErrInternalServer: 'Внутренняя ошибка: {{ .detail }}'
|
||||
ErrRecordExist: 'Запись уже существует'
|
||||
ErrRecordNotFound: 'Запись не найдена'
|
||||
ErrStructTransform: 'Не удалось преобразовать тип: {{ .err }}'
|
||||
ErrNotLogin: 'Пользователь не вошел в систему: {{ .detail }}'
|
||||
ErrPasswordExpired: 'Срок действия текущего пароля истек: {{ .detail }}'
|
||||
ErrNotSupportType: 'Система не поддерживает текущий тип: {{ .name }}'
|
||||
ErrProxy: 'Ошибка запроса, проверьте статус узла: {{ .detail }}'
|
||||
ErrApiConfigStatusInvalid: 'Доступ к интерфейсу API запрещен: {{ .detail }}'
|
||||
ErrApiConfigKeyInvalid: 'Ошибка ключа интерфейса API: {{ .detail }}'
|
||||
ErrApiConfigIPInvalid: 'IP-адрес, используемый для вызова интерфейса API, отсутствует в белом списке: {{ .detail }}'
|
||||
ErrApiConfigDisable: 'Этот интерфейс запрещает использование вызовов интерфейса API: {{ .detail }}'
|
||||
ErrApiConfigKeyTimeInvalid: 'Ошибка временной метки интерфейса API: {{ .detail }}'
|
||||
StartPushSSLToNode: "Начало отправки сертификата на узел"
|
||||
PushSSLToNodeFailed: "Не удалось отправить сертификат на узел: {{ .err }}"
|
||||
PushSSLToNodeSuccess: "Сертификат успешно отправлен на узел"
|
||||
ErrShutDown: "Команда завершена вручную!"
|
||||
|
||||
ErrMinQuickJump: "Пожалуйста, установите хотя бы одну запись быстрого перехода!"
|
||||
ErrMaxQuickJump: "Можно установить до четырех записей быстрого перехода!"
|
||||
|
||||
#общий
|
||||
ErrUsernameIsExist: 'Имя пользователя уже существует'
|
||||
ErrNameIsExist: 'Имя уже существует'
|
||||
ErrDemoEnvironment: 'Демо-сервер, эта операция запрещена!'
|
||||
ErrCmdTimeout: 'Время выполнения команды истекло!'
|
||||
ErrCmdIllegal: 'В команде выполнения есть недопустимые символы. Измените ее и повторите попытку!'
|
||||
ErrPortExist: 'Порт {{ .port }} уже занят {{ .type }} [{{ .name }}]'
|
||||
ErrStructTransform: 'Ошибка преобразования: {{ .err }}'
|
||||
ErrNotLogin: 'Не авторизован: {{ .detail }}'
|
||||
ErrPasswordExpired: 'Пароль истёк: {{ .detail }}'
|
||||
ErrNotSupportType: 'Тип не поддерживается: {{ .name }}'
|
||||
ErrProxy: 'Запрос не удался: {{ .detail }}'
|
||||
ErrApiConfigStatusInvalid: 'API отключено: {{ .detail }}'
|
||||
ErrApiConfigKeyInvalid: 'Неверный API-ключ: {{ .detail }}'
|
||||
ErrApiConfigIPInvalid: 'IP не в списке: {{ .detail }}'
|
||||
ErrApiConfigDisable: 'Доступ по API запрещён: {{ .detail }}'
|
||||
ErrApiConfigKeyTimeInvalid: 'Неверная метка времени: {{ .detail }}'
|
||||
ErrShutDown: 'Команда остановлена вручную'
|
||||
ErrMinQuickJump: 'Добавьте хотя бы одну быструю ссылку'
|
||||
ErrMaxQuickJump: 'Не более 4 быстрых ссылок'
|
||||
ErrUsernameIsExist: 'Имя пользователя занято'
|
||||
ErrNameIsExist: 'Имя уже занято'
|
||||
ErrDemoEnvironment: 'Недоступно в демо'
|
||||
ErrCmdTimeout: 'Команда завершилась по тайм-ауту'
|
||||
ErrCmdIllegal: 'Команда содержит недопустимые символы'
|
||||
ErrPortExist: 'Порт {{ .port }} занят {{ .type }} [{{ .name }}]'
|
||||
TYPE_APP: 'Приложение'
|
||||
TYPE_RUNTIME: 'Среда выполнения'
|
||||
TYPE_DOMAIN: 'Доменное имя'
|
||||
@@ -39,45 +33,40 @@ Failed: 'Не удалось'
|
||||
SystemRestart: 'Задача прервана из-за перезапуска системы'
|
||||
ErrGroupIsDefault: 'Группа по умолчанию, не может быть удалена'
|
||||
ErrGroupIsInWebsiteUse: 'Группа используется другим веб-сайтом и не может быть удалена.'
|
||||
Decrypt: "Расшифровать"
|
||||
|
||||
#agent
|
||||
ErrAgentAccountBound: 'Эта учетная запись привязана к агенту и не может быть удалена. Проверьте и повторите попытку!'
|
||||
ErrAgentAccountUnavailable: 'Информация о подключении учетной записи недоступна. Ошибка: {{ .err }}. Проверьте и повторите попытку!'
|
||||
ErrAgentProviderNotSupported: 'Этот провайдер агента не поддерживается. Проверьте и повторите попытку!'
|
||||
ErrAgentAccountRequired: 'Выберите учетную запись агента и повторите попытку.'
|
||||
ErrAgentAccountNotVerified: 'Учетная запись не прошла проверку. Проверьте и повторите попытку!'
|
||||
ErrAgentProviderMismatch: 'Провайдер учетной записи не совпадает. Проверьте и повторите попытку!'
|
||||
ErrAgentBaseURLRequired: 'Base URL не может быть пустым. Проверьте и повторите попытку!'
|
||||
ErrAgentApiKeyRequired: 'API Key не может быть пустым. Проверьте и повторите попытку!'
|
||||
ErrAgentComposeRequired: 'Пользовательское содержимое compose не может быть пустым. Проверьте и повторите попытку!'
|
||||
ErrAgentIDRequired: 'ID агента не может быть пустым. Проверьте и повторите попытку!'
|
||||
ErrAgentAccountIDRequired: 'ID учетной записи не может быть пустым. Проверьте и повторите попытку!'
|
||||
|
||||
#резервное копирование
|
||||
Decrypt: 'Расшифровать'
|
||||
ErrAgentAccountBound: 'Акаунт привязан к агенту'
|
||||
ErrAgentAccountUnavailable: 'Связь с аккаунтом недоступна: {{ .err }}'
|
||||
ErrAgentProviderNotSupported: 'Провайдер агента не поддерживается'
|
||||
ErrAgentAccountRequired: 'Выберите аккаунт агента'
|
||||
ErrAgentAccountNotVerified: 'Аккаунт не подтверждён'
|
||||
ErrAgentProviderMismatch: 'Провайдер не совпадает'
|
||||
ErrAgentBaseURLRequired: 'Нужен базовый URL'
|
||||
ErrAgentApiKeyRequired: 'Нужен API-ключ'
|
||||
ErrAgentComposeRequired: 'Нужен compose'
|
||||
ErrAgentIDRequired: 'Нужен ID агента'
|
||||
ErrAgentAccountIDRequired: 'Нужен ID аккаунта'
|
||||
ErrAgentLimitReached: 'Community Edition поддерживает до {{ .max }} AI-агентов. Перейдите на Professional Edition, чтобы снять ограничение'
|
||||
Localhost: 'Локальная машина'
|
||||
ErrBackupInUsed: 'Учетная запись резервного копирования использовалась в запланированной задаче и не может быть удалена.'
|
||||
ErrBackupCheck: 'Проверка подключения к резервной копии учетной записи не удалась {{ .err }}'
|
||||
ErrBackupLocalDelete: 'Удаление учетной записи резервного копирования локального сервера пока не поддерживается'
|
||||
ErrBackupLocalCreate: 'Создание учетных записей резервного копирования локального сервера пока не поддерживается'
|
||||
|
||||
#приложение
|
||||
ErrPortInUsed: '{{ .detail }} порт уже занят!'
|
||||
ErrBackupInUsed: 'Аккаунт бэкапа занят задачей'
|
||||
ErrBackupCheck: 'Проверка подключения не удалась: {{ .err }}'
|
||||
ErrBackupLocalDelete: 'Нельзя удалить локальные бэкапы'
|
||||
ErrBackupLocalCreate: 'Нельзя создать локальные бэкапы'
|
||||
ErrPortInUsed: '{{ .detail }} порт уже занят'
|
||||
ErrAppLimit: 'Количество установленных приложений превысило лимит'
|
||||
ErrNotInstall: 'Приложение не установлено'
|
||||
ErrPortInOtherApp: 'Порт {{ .port }} уже занят приложением {{ .apps }}!'
|
||||
ErrDbUserNotValid: 'Существующая база данных, имя пользователя и пароль не совпадают!'
|
||||
ErrUpdateBuWebsite: 'Приложение успешно обновлено, но изменение файла конфигурации веб-сайта не удалось. Пожалуйста, проверьте конфигурацию! '
|
||||
Err1PanelNetworkFailed: 'Создание сети контейнеров по умолчанию не удалось! {{ .detail }}'
|
||||
ErrFileParse: 'Ошибка анализа файла docker-compose приложения!'
|
||||
ErrPortInOtherApp: 'Порт {{ .port }} уже занят приложением {{ .apps }}'
|
||||
ErrDbUserNotValid: 'Существующая база данных, имя пользователя и пароль не совпадают'
|
||||
ErrUpdateBuWebsite: 'Приложение успешно обновлено, но изменение файла конфигурации веб-сайта не удалось. Пожалуйста, проверьте конфигурацию'
|
||||
Err1PanelNetworkFailed: 'Создание сети контейнеров по умолчанию не удалось {{ .detail }}'
|
||||
ErrFileParse: 'Ошибка анализа файла docker-compose приложения'
|
||||
ErrInstallDirNotFound: 'Каталог установки не существует. Если вам необходимо удалить, выберите Принудительное удаление.'
|
||||
AppStoreIsUpToDate: 'В магазине приложений уже установлена последняя версия'
|
||||
LocalAppVersionNull: 'Приложение {{ .name }} не синхронизировано с версией! Невозможно добавить в список приложений.'
|
||||
LocalAppVersionErr: 'Синхронизация версии {{ .version }} {{ .name }} не удалась! {{ .err }}'
|
||||
LocalAppVersionNull: 'Приложение {{ .name }} не синхронизировано с версией Невозможно добавить в список приложений.'
|
||||
LocalAppVersionErr: 'Синхронизация версии {{ .version }} {{ .name }} не удалась {{ .err }}'
|
||||
ErrFileNotFound: 'Файл {{ .name }} не существует'
|
||||
ErrFileParseApp: '{{ .name }} анализ файла не удался {{ .err }}'
|
||||
ErrAppDirNull: 'Папка версии не существует'
|
||||
LocalAppErr: 'Синхронизация приложения {{ .name }} не удалась! {{ .err }}'
|
||||
LocalAppErr: 'Синхронизация приложения {{ .name }} не удалась {{ .err }}'
|
||||
ErrContainerName: 'Имя контейнера уже существует'
|
||||
ErrCreateHttpClient: 'Не удалось создать запрос {{ .err }}'
|
||||
ErrHttpReqTimeOut: 'Истекло время ожидания запроса {{ .err }}'
|
||||
@@ -90,46 +79,42 @@ ErrAppBackup: '{{ .name }} резервное копирование прило
|
||||
ErrVersionTooLow: 'Текущая версия 1Panel слишком низкая для обновления App Store. Пожалуйста, обновите версию перед началом работы.'
|
||||
ErrAppNameExist: 'Имя приложения уже существует'
|
||||
AppStoreIsSyncing: 'App Store синхронизируется, повторите попытку позже'
|
||||
ErrGetCompose: 'Не удалось получить файл docker-compose.yml! {{ .detail }}'
|
||||
ErrGetCompose: 'Не удалось получить файл docker-compose.yml {{ .detail }}'
|
||||
ErrAppWarn: 'Ненормальное состояние, проверьте журнал'
|
||||
ErrAppParamKey: 'Поле параметра {{ .name }} ненормально'
|
||||
ErrAppUpgrade: 'Обновление приложения {{ .name }} не удалось {{ .err }}'
|
||||
AppRecover: 'Откатить приложение {{ .name }}'
|
||||
PullImageStart: 'Начать извлечение изображения [{{ .name }}]'
|
||||
PullImageSuccess: 'Изображение извлечено успешно'
|
||||
AppStoreIsLastVersion: 'В App Store уже установлена последняя версия'
|
||||
AppStoreSyncSuccess: 'Синхронизация с App Store прошла успешно'
|
||||
SyncAppDetail: 'Синхронизировать конфигурацию приложения'
|
||||
AppVersionNotMatch: 'Приложению {{ .name }} требуется более высокая версия 1Panel, синхронизация пропускается'
|
||||
MoveSiteDir: "Обнаружено изменение каталога сайта. Необходимо перенести каталог сайта OpenResty в {{ .name }}"
|
||||
MoveSiteDir: 'Обнаружено изменение каталога сайта. Необходимо перенести каталог сайта OpenResty в {{ .name }}'
|
||||
MoveSiteDirSuccess: 'Успешная миграция каталога веб-сайта'
|
||||
DeleteRuntimePHP: 'Удалить среду выполнения PHP'
|
||||
CustomAppStoreFileValid: 'Пакеты магазина приложений должны быть в формате .tar.gz'
|
||||
CustomAppStoreFileValid: 'Пакеты магазина приложений должны быть в формате.tar.gz'
|
||||
PullImageTimeout: 'Истекло время ожидания извлечения изображения. Попробуйте увеличить ускорение изображения или выбрать другое ускорение изображения'
|
||||
ErrAppIsDown: '{{ .name }} статус приложения ненормальный, проверьте'
|
||||
ErrCustomApps: 'Установлено приложение. Сначала удалите его'
|
||||
ErrCustomRuntimes: 'Установлена среда выполнения. Сначала удалите ее'
|
||||
ErrAppVersionDeprecated: "Приложение {{ .name }} несовместимо с текущей версией 1Panel, пропущено"
|
||||
ErrDockerFailed: "Состояние Docker аномально, проверьте состояние сервиса"
|
||||
ErrDockerComposeCmdNotFound: "Команда Docker Compose отсутствует, пожалуйста, установите эту команду на хост-машине сначала"
|
||||
UseExistImage: 'Не удалось загрузить образ, используется существующий образ'
|
||||
|
||||
#ssh
|
||||
ExportIP: "IP входа"
|
||||
ExportArea: "Местоположение"
|
||||
ExportPort: "Порт"
|
||||
ExportAuthMode: "Способ входа"
|
||||
ExportUser: "Пользователь"
|
||||
ExportStatus: "Статус входа"
|
||||
ExportDate: "Время"
|
||||
|
||||
#файл
|
||||
ErrAppVersionDeprecated: 'Приложение {{ .name }} несовместимо с текущей версией 1Panel, пропущено'
|
||||
ErrDockerFailed: 'Состояние Docker аномально, проверьте состояние сервиса'
|
||||
ErrDockerComposeCmdNotFound: 'Команда Docker Compose отсутствует, пожалуйста, установите эту команду на хост-машине сначала'
|
||||
UseExistImage: 'Образ уже существует, используется существующий образ'
|
||||
ErrDatabaseNotFound: 'База данных {{ .name }} не существует'
|
||||
ExportIP: 'IP входа'
|
||||
ExportArea: 'Местоположение'
|
||||
ExportPort: 'Порт'
|
||||
ExportAuthMode: 'Способ входа'
|
||||
ExportUser: 'Пользователь'
|
||||
ExportStatus: 'Статус входа'
|
||||
ExportDate: 'Время'
|
||||
ErrFileCanNotRead: 'Этот файл не поддерживает предварительный просмотр'
|
||||
ErrFileToLarge: 'Файл больше 10 МБ и не может быть открыт'
|
||||
ErrPathNotFound: 'Каталог не существует'
|
||||
ErrMovePathFailed: 'Целевой путь не может содержать исходный путь!'
|
||||
ErrLinkPathNotFound: 'Целевой путь не существует!'
|
||||
ErrFileIsExist: 'Файл или папка уже существует!'
|
||||
ErrMovePathFailed: 'Целевой путь не может содержать исходный путь'
|
||||
ErrLinkPathNotFound: 'Целевой путь не существует'
|
||||
ErrFileIsExist: 'Файл или папка уже существует'
|
||||
ErrFileUpload: '{{ .name }} не удалось загрузить файл {{ .detail }}'
|
||||
ErrFileDownloadDir: 'Папка загрузки не поддерживается'
|
||||
ErrCmdNotFound: 'Команда {{ .name }} не существует, сначала установите эту команду на хосте'
|
||||
@@ -137,17 +122,15 @@ ErrSourcePathNotFound: 'Исходный каталог не существуе
|
||||
ErrFavoriteExist: 'Этот путь уже добавлен в избранное'
|
||||
ErrInvalidChar: 'Недопустимые символы не допускаются'
|
||||
ErrPathNotDelete: 'Выбранный каталог не может быть удален'
|
||||
ErrLogFileToLarge: "Файл журнала превышает 500MB и не может быть открыт"
|
||||
FileDropFailed: "Не удалось очистить файл {{ .name }}: {{ .err }}"
|
||||
FileDropSuccess: "Файл {{ .name }} успешно очищен, удалено {{ .count }} файлов, освобождено {{ .size }} дискового пространства"
|
||||
FileDropSum: "Очистка файлов завершена успешно, всего удалено {{ .count }} файлов, освобождено {{ .size }} дискового пространства"
|
||||
ErrBadDecrypt: "Ошибка пароля расшифровки сжатого пакета, распаковка не удалась, проверьте и повторите попытку!"
|
||||
|
||||
#веб-сайт
|
||||
ErrLogFileToLarge: 'Файл журнала превышает 500MB и не может быть открыт'
|
||||
FileDropFailed: 'Не удалось очистить файл {{ .name }}: {{ .err }}'
|
||||
FileDropSuccess: 'Файл {{ .name }} успешно очищен, удалено {{ .count }} файлов, освобождено {{ .size }} дискового пространства'
|
||||
FileDropSum: 'Очистка файлов завершена успешно, всего удалено {{ .count }} файлов, освобождено {{ .size }} дискового пространства'
|
||||
ErrBadDecrypt: 'Ошибка пароля расшифровки сжатого пакета, распаковка не удалась, проверьте и повторите попытку'
|
||||
ErrAliasIsExist: 'Псевдоним уже существует'
|
||||
ErrBackupMatch: 'Файл резервной копии не соответствует некоторым текущим данным веб-сайта {{ .detail }}'
|
||||
ErrBackupExist: 'Соответствующая часть исходных данных в файле резервной копии не существует {{ .detail }}'
|
||||
ErrPHPResource: 'Локальная операционная среда не поддерживает переключение!'
|
||||
ErrPHPResource: 'Локальная операционная среда не поддерживает переключение'
|
||||
ErrPathPermission: 'В каталоге index обнаружена папка с разрешениями, отличными от 1000:1000, что может привести к ошибке Отказано в доступе на веб-сайте. Пожалуйста, нажмите кнопку Сохранить выше.'
|
||||
ErrDomainIsUsed: 'Доменное имя уже используется веб-сайтом [{{ .name }}]'
|
||||
ErrDomainFormat: 'Неверный формат доменного имени {{ .name }}'
|
||||
@@ -155,11 +138,11 @@ ErrDefaultAlias: 'по умолчанию зарезервирован код,
|
||||
ErrParentWebsite: 'Сначала вам необходимо удалить дочерний сайт {{ .name }}'
|
||||
ErrBuildDirNotFound: 'Каталог сборки не существует'
|
||||
ErrImageNotExist: 'Образ операционной среды {{ .name }} не существует, пожалуйста, отредактируйте операционную среду заново'
|
||||
ErrProxyIsUsed: "Балансировка нагрузки используется обратным прокси, невозможно удалить"
|
||||
ErrSSLValid: 'Файл сертификата аномален, проверьте статус сертификата!'
|
||||
ErrWebsiteDir: "Пожалуйста, выберите директорию внутри директории сайта."
|
||||
ErrComposerFileNotFound: "Файл composer.json не существует"
|
||||
ErrRuntimeNoPort: "Среда выполнения не настроена с портом, сначала отредактируйте среду выполнения."
|
||||
ErrProxyIsUsed: 'Балансировка нагрузки используется обратным прокси, невозможно удалить'
|
||||
ErrSSLValid: 'Файл сертификата аномален, проверьте статус сертификата'
|
||||
ErrWebsiteDir: 'Пожалуйста, выберите директорию внутри директории сайта.'
|
||||
ErrComposerFileNotFound: 'Файл composer.json не существует'
|
||||
ErrRuntimeNoPort: 'Среда выполнения не настроена с портом, сначала отредактируйте среду выполнения.'
|
||||
Status: 'Статус'
|
||||
start: 'Запустить'
|
||||
stop: 'Остановить'
|
||||
@@ -169,14 +152,12 @@ pause: 'Приостановить'
|
||||
unpause: 'Возобновить'
|
||||
remove: 'Удалить'
|
||||
delete: 'Удалить'
|
||||
ErrDefaultWebsite: 'Веб-сайт по умолчанию уже установлен, отмените его перед настройкой!'
|
||||
ErrDefaultWebsite: 'Веб-сайт по умолчанию уже установлен, отмените его перед настройкой'
|
||||
SSL: 'Сертификат'
|
||||
Set: 'Настройки'
|
||||
|
||||
#ssl
|
||||
ErrSSLCannotDelete: 'Сертификат {{ .name }} используется веб-сайтом и не может быть удален'
|
||||
ErrAccountCannotDelete: 'Учетная запись связана с сертификатом и не может быть удалена'
|
||||
ErrSSLApply: 'Обновление сертификата прошло успешно, перезагрузка OpenResty не удалась, проверьте конфигурацию!'
|
||||
ErrSSLApply: 'Обновление сертификата прошло успешно, перезагрузка OpenResty не удалась, проверьте конфигурацию'
|
||||
ErrEmailIsExist: 'Почтовый ящик уже существует'
|
||||
ErrSSLKeyNotFound: 'Файл закрытого ключа не существует'
|
||||
ErrSSLCertificateNotFound: 'Файл сертификата не существует'
|
||||
@@ -189,7 +170,7 @@ dnsAccount: 'DNS Авто'
|
||||
dnsManual: 'Руководство по DNS'
|
||||
http: 'HTTP'
|
||||
ApplySSLFailed: 'Заявка на сертификат [{{ .domain }}] не выполнена, {{ .detail }}'
|
||||
ApplySSLSuccess: 'Заявка на сертификат [{{ .domain }}] успешно подана! '
|
||||
ApplySSLSuccess: 'Заявка на сертификат [{{ .domain }}] успешно подана'
|
||||
DNSAccountName: 'DNS-аккаунт [{{ .name }}] поставщик [{{ .type }}]'
|
||||
PushDirLog: 'Сертификат перемещен в каталог [{{ .path }}] {{ .status }}'
|
||||
ErrDeleteCAWithSSL: 'Текущая организация имеет сертификат, который был выдан и не может быть удален.'
|
||||
@@ -204,94 +185,79 @@ ExecShellSuccess: 'Скрипт выполнен успешно'
|
||||
StartUpdateSystemSSL: 'Начать обновление системного сертификата'
|
||||
UpdateSystemSSLSuccess: 'Сертификат системы обновлен успешно'
|
||||
ErrWildcardDomain: 'Невозможно подать заявку на получение подстановочного сертификата доменного имени в режиме HTTP'
|
||||
ErrApplySSLCanNotDelete: "Нельзя удалить сертификат {{.name}}, который находится в процессе выпуска. Пожалуйста, попробуйте позже."
|
||||
|
||||
#mysql
|
||||
ErrApplySSLCanNotDelete: 'Нельзя удалить сертификат {{ .name }}, который находится в процессе выпуска. Пожалуйста, попробуйте позже.'
|
||||
StartPushSSLToNode: 'Начало отправки сертификата на узел'
|
||||
PushSSLToNodeFailed: 'Не удалось отправить сертификат на узел: {{ .err }}'
|
||||
PushSSLToNodeSuccess: 'Сертификат успешно отправлен на узел'
|
||||
ErrUserIsExist: 'Текущий пользователь уже существует, пожалуйста, введите еще раз'
|
||||
ErrDatabaseIsExist: 'Текущая база данных уже существует, пожалуйста, введите ее повторно'
|
||||
ErrExecTimeOut: 'Время выполнения SQL истекло, проверьте базу данных'
|
||||
ErrRemoteExist: 'Удаленная база данных с таким именем уже существует. Измените его и повторите попытку'
|
||||
ErrLocalExist: 'Имя уже существует в локальной базе данных, измените его и повторите попытку'
|
||||
RemoteBackup: "Для резервного копирования удаленной базы данных необходимо сначала запустить службу базы данных локального контейнера с помощью образа {{ .name }}, пожалуйста, подождите..."
|
||||
RemoteRecover: "Для восстановления удаленной базы данных необходимо сначала запустить службу базы данных локального контейнера с помощью образа {{ .name }}, пожалуйста, подождите..."
|
||||
Arg: "Аргумент"
|
||||
|
||||
#редис
|
||||
RemoteBackup: 'Для резервного копирования удаленной базы данных необходимо сначала запустить службу базы данных локального контейнера с помощью образа {{ .name }}, пожалуйста, подождите...'
|
||||
RemoteRecover: 'Для восстановления удаленной базы данных необходимо сначала запустить службу базы данных локального контейнера с помощью образа {{ .name }}, пожалуйста, подождите...'
|
||||
Arg: 'Аргумент'
|
||||
ErrTypeOfRedis: 'Тип файла восстановления не соответствует текущему методу сохранения. Измените его и повторите попытку'
|
||||
|
||||
#контейнер
|
||||
ErrInUsed: "{{ .detail }} используется и не может быть удалено!"
|
||||
ErrObjectInUsed: "Этот объект используется и не может быть удален!"
|
||||
ErrObjectBeDependent: "Этот образ зависит от других образов и не может быть удален!"
|
||||
ErrPortRules: 'Номер порта не совпадает, введите заново!'
|
||||
ErrInUsed: '{{ .detail }} используется и не может быть удалено'
|
||||
ErrObjectInUsed: 'Этот объект используется и не может быть удален'
|
||||
ErrObjectBeDependent: 'Этот образ зависит от других образов и не может быть удален'
|
||||
ErrPortRules: 'Номер порта не совпадает, введите заново'
|
||||
ErrPgImagePull: 'Время извлечения изображения истекло. Настройте ускорение изображения или вручную извлеките изображение {{ .name }} и повторите попытку'
|
||||
PruneHelper: "Эта очистка {{ .name }} освободила дисковое пространство {{ .size }}"
|
||||
ImageRemoveHelper: "Удалён образ {{ .name }}, освобождено {{ .size }} дискового пространства"
|
||||
BuildCache: "Кэш сборки"
|
||||
Volume: "Том хранилища"
|
||||
Network: "Сеть"
|
||||
PruneStart: "Очистка выполняется, пожалуйста, подождите..."
|
||||
|
||||
#время выполнения
|
||||
ErrFileNotExist: 'Файл {{ .detail }} не существует! Проверьте целостность исходного файла!'
|
||||
PruneHelper: 'Эта очистка {{ .name }} освободила дисковое пространство {{ .size }}'
|
||||
ImageRemoveHelper: 'Удалён образ {{ .name }}, освобождено {{ .size }} дискового пространства'
|
||||
BuildCache: 'Кэш сборки'
|
||||
Volume: 'Том хранилища'
|
||||
Network: 'Сеть'
|
||||
PruneStart: 'Очистка выполняется, пожалуйста, подождите...'
|
||||
ErrFileNotExist: 'Файл {{ .detail }} не существует Проверьте целостность исходного файла'
|
||||
ErrImageBuildErr: 'Сборка образа не удалась'
|
||||
ErrImageExist: "Изображение уже существует! Пожалуйста, измените имя изображения."
|
||||
ErrImageExist: 'Изображение уже существует Пожалуйста, измените имя изображения.'
|
||||
ErrDelWithWebsite: 'Операционная среда уже связана с веб-сайтом и не может быть удалена'
|
||||
ErrRuntimeStart: 'Запуск не удался'
|
||||
ErrPackageJsonNotFound: 'файл package.json не существует'
|
||||
ErrScriptsNotFound: 'Элемент конфигурации скриптов не найден в package.json'
|
||||
ErrContainerNameNotFound: 'Не удалось получить имя контейнера, проверьте файл .env'
|
||||
ErrNodeModulesNotFound: 'Папка node_modules не существует! Измените среду выполнения или дождитесь ее успешного запуска'
|
||||
ErrContainerNameNotFound: 'Не удалось получить имя контейнера, проверьте файл.env'
|
||||
ErrNodeModulesNotFound: 'Папка node_modules не существует Измените среду выполнения или дождитесь ее успешного запуска'
|
||||
ErrContainerNameIsNull: 'Имя контейнера не существует'
|
||||
ErrPHPPortIsDefault: "A porta 9000 é a porta padrão, por favor, modifique e tente novamente"
|
||||
ErrPHPRuntimePortFailed: "A porta {{ .name }} já está sendo usada pelo ambiente de tempo de execução atual, por favor, modifique e tente novamente"
|
||||
|
||||
#инструмент
|
||||
ErrPHPPortIsDefault: 'A porta 9000 é a porta padrão, por favor, modifique e tente novamente'
|
||||
ErrPHPRuntimePortFailed: 'A porta {{ .name }} já está sendo usada pelo ambiente de tempo de execução atual, por favor, modifique e tente novamente'
|
||||
ErrConfigNotFound: 'Файл конфигурации не существует'
|
||||
ErrConfigParse: 'Неверный формат файла конфигурации'
|
||||
ErrConfigIsNull: 'Файл конфигурации не может быть пустым'
|
||||
ErrConfigDirNotFound: 'Рабочий каталог не существует'
|
||||
ErrConfigAlreadyExist: 'Файл конфигурации с таким именем уже существует'
|
||||
ErrUserFindErr: 'Поиск пользователя {{ .name }} не удался {{ .err }}'
|
||||
|
||||
#cronjob
|
||||
CutWebsiteLogSuccess: 'Журнал веб-сайта {{ .name }} успешно вырезан, путь к резервной копии {{ .path }}'
|
||||
HandleShell: 'Выполнить скрипт {{ .name }}'
|
||||
HandleCurl: "Доступ к URL {{ .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], чтобы добавить группу IP с помощью метода удаленной загрузки."
|
||||
|
||||
#ящик для инструментов
|
||||
ErrNotExistUser: 'Текущий пользователь не существует, измените его и повторите попытку!'
|
||||
ErrBanAction: 'Настройка не удалась. Текущая служба {{ .name }} недоступна. Проверьте и повторите попытку!'
|
||||
ErrClamdscanNotFound: 'Команда clamdscan не обнаружена, обратитесь к документации, чтобы установить ее!'
|
||||
TaskSwapSet: "Настройка Swap"
|
||||
SetSwap: "Настроить Swap {{ .path }} - {{ .size }}"
|
||||
CreateSwap: "Создать Файл Swap"
|
||||
FormatSwap: "Форматировать Файл Swap"
|
||||
EnableSwap: "Включить Swap"
|
||||
|
||||
#tamper
|
||||
CleanTamperSetting: "Очистить исторические настройки защиты"
|
||||
SetTamperWithRules: "Запустить защиту каталога согласно правилам"
|
||||
ProtectDir: "Защитить каталог {{ .name }}"
|
||||
IgnoreFile: "Защитить файл {{ .name }}"
|
||||
TamperSetSuccessful: "Настройки защиты завершены, начинаю мониторинг следующих каталогов:"
|
||||
|
||||
#ваф
|
||||
Upload: 'Загрузить'
|
||||
IgnoreBackupErr: 'Ошибка резервного копирования: {{ .detail }}, игнорируем эту ошибку...'
|
||||
IgnoreUploadErr: 'Ошибка загрузки: {{ .detail }}, игнорируем эту ошибку...'
|
||||
LoadBackupFailed: 'Не удалось получить подключение к учетной записи резервной копии, ошибка: {{ .detail }}'
|
||||
InExecuting: 'Текущая задача выполняется, не повторяйте выполнение'
|
||||
NoSuchResource: 'В базе данных не найдено содержимое резервной копии, пропускаем...'
|
||||
CleanLog: 'Очистить журнал'
|
||||
CleanLogByName: 'Очистить журнал {{ .name }}'
|
||||
WafIpGroupNotFound: 'Группа IP WAF не найдена. Пожалуйста, перейдите в [Расширенные функции - WAF - Черный/Белый список - Группа IP], чтобы добавить группу 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: 'Настройки защиты завершены, начинаю мониторинг следующих каталогов:'
|
||||
ErrScope: 'Изменение этой конфигурации не поддерживается'
|
||||
ErrStateChange: 'He удалось изменить состояние'
|
||||
ErrRuleExist: 'Правило уже существует'
|
||||
@@ -299,7 +265,7 @@ ErrRuleNotExist: 'Правило не существует'
|
||||
ErrParseIP: 'Неправильный формат IP'
|
||||
ErrDefaultIP: 'по умолчанию это зарезервированное имя, пожалуйста, измените его на другое имя'
|
||||
ErrGroupInUse: 'IP-группа используется черным/белым списком и не может быть удалена'
|
||||
ErrIPGroupAclUse: "Группа IP используется пользовательскими правилами сайта {{ .name }}, невозможно удалить"
|
||||
ErrIPGroupAclUse: 'Группа IP используется пользовательскими правилами сайта {{ .name }}, невозможно удалить'
|
||||
ErrGroupExist: 'Имя группы IP уже существует'
|
||||
ErrIPRange: 'Неверный диапазон IP-адресов'
|
||||
ErrIPExist: 'IP-адрес уже существует'
|
||||
@@ -310,10 +276,10 @@ xss: 'XSS'
|
||||
phpExec: 'Выполнение PHP-скрипта'
|
||||
oneWordTrojan: 'Троян из одного слова'
|
||||
appFilter: 'Применить фильтрацию опасных каталогов'
|
||||
webshell: 'Be6-оболочка'
|
||||
webShell: 'Be6-оболочка'
|
||||
args: 'Правила параметров'
|
||||
protocolFilter: 'Фильтрация протоколов'
|
||||
javaFileter: 'Фильтр опасных файлов Java'
|
||||
javaFilter: 'Фильтр опасных файлов Java'
|
||||
scannerFilter: 'Фильтр сканера'
|
||||
escapeFilter: 'фильтр побега'
|
||||
customRule: 'Пользовательское правило'
|
||||
@@ -343,10 +309,9 @@ ErrDBNotExist: 'База данных не существует'
|
||||
allow: 'разрешить'
|
||||
deny: 'отрицать'
|
||||
OpenrestyNotFound: 'Openresty не установлен'
|
||||
remoteIpIsNull: "Список IP пуст"
|
||||
OpenrestyVersionErr: "Версия Openresty слишком низкая, пожалуйста, обновите Openresty до 1.27.1.2-2-2-focal"
|
||||
|
||||
#задача
|
||||
remoteIpIsNull: 'Список IP пуст'
|
||||
OpenrestyVersionErr: 'Версия Openresty слишком низкая, пожалуйста, обновите Openresty до 1.27.1.2-2-2-focal'
|
||||
ErrFileTooLarge: 'File is larger than 1 MB and cannot be uploaded'
|
||||
TaskStart: '{{ .name }} Задача начинается [START]'
|
||||
TaskEnd: '{{ .name }} Задача выполнена [ЗАВЕРШЕНО]'
|
||||
TaskFailed: 'Задача {{ .name }} не выполнена'
|
||||
@@ -362,18 +327,18 @@ TaskDelete: 'Удалить'
|
||||
TaskUpgrade: 'Обновить'
|
||||
TaskUpdate: 'Обновить'
|
||||
TaskRestart: 'Перезапуск'
|
||||
TaskProtect: "Защита"
|
||||
TaskProtect: 'Защита'
|
||||
TaskBackup: 'Резервное копирование'
|
||||
TaskRecover: 'Восстановить'
|
||||
TaskRollback: 'Откат'
|
||||
TaskPull: 'Вытянуть'
|
||||
TaskCommit: 'Kоммит'
|
||||
ЗадачаСборка: 'Сборка'
|
||||
TaskBuild: 'Сборка'
|
||||
TaskPush: 'Push'
|
||||
TaskClean: "Очистка"
|
||||
TaskClean: 'Очистка'
|
||||
TaskHandle: 'Выполнить'
|
||||
TaskImport: "Импорт"
|
||||
TaskExport: "Экспорт"
|
||||
TaskImport: 'Импорт'
|
||||
TaskExport: 'Экспорт'
|
||||
Website: 'Be6-сайт'
|
||||
App: 'Приложение'
|
||||
Runtime: 'Среда выполнения'
|
||||
@@ -405,18 +370,12 @@ RuntimeExtension: 'Расширение среды выполнения'
|
||||
TaskIsExecuting: 'Задача выполняется'
|
||||
CustomAppstore: 'Хранилище пользовательских приложений'
|
||||
TaskExec: 'Выполнить'
|
||||
TaskBatch: "Пакетная операция"
|
||||
TaskBatch: 'Пакетная операция'
|
||||
FileConvert: 'Преобразование формата файла'
|
||||
|
||||
# task - clam
|
||||
Clamscan: "Сканировать {{ .name }}"
|
||||
TaskScan: "Сканировать"
|
||||
|
||||
# задача - ай
|
||||
Clamscan: 'Сканировать {{ .name }}'
|
||||
TaskScan: 'Сканировать'
|
||||
OllamaModelPull: 'Вытянуть модель Ollama {{ .name }}'
|
||||
OllamaModelSize: 'Получить размер модели Ollama {{ .name }}'
|
||||
|
||||
# снимок задачи
|
||||
Snapshot: 'Снимок'
|
||||
SnapDBInfo: 'Запись информации о базе данных 1Panel'
|
||||
SnapCopy: 'Копировать файлы и каталоги {{ .name }}'
|
||||
@@ -442,7 +401,6 @@ SnapCompressSize: 'Размер файла снимка {{ .name }}'
|
||||
SnapUpload: 'Загрузить файл снимка'
|
||||
SnapUploadTo: 'Загрузить файл снимка в {{ .name }}'
|
||||
SnapUploadRes: 'Загрузить файл снимка в {{ .name }}'
|
||||
|
||||
SnapshotRecover: 'Восстановление моментального снимка'
|
||||
RecoverDownload: 'Загрузить файл снимка'
|
||||
Download: 'Скачать'
|
||||
@@ -450,10 +408,10 @@ RecoverDownloadAccount: 'Получить резервную копию учет
|
||||
RecoverDecompress: 'Распаковка сжатых файлов моментальных снимков'
|
||||
Decompress: 'Декомпрессия'
|
||||
BackupBeforeRecover: 'Резервное копирование системных данных перед созданием снимка'
|
||||
Readjson: 'Прочитать файл JSON в снимке'
|
||||
ReadjsonPath: 'Получить путь к файлу JSON в снимке'
|
||||
ReadjsonContent: 'Прочитать файл Json'
|
||||
ReadjsonMarshal: 'Обработка Json escape'
|
||||
ReadJson: 'Прочитать файл JSON в снимке'
|
||||
ReadJsonPath: 'Получить путь к файлу JSON в снимке'
|
||||
ReadJsonContent: 'Прочитать файл Json'
|
||||
ReadJsonMarshal: 'Обработка Json escape'
|
||||
RecoverApp: 'Восстановить установленные приложения'
|
||||
RecoverWebsite: 'Восстановить каталог веб-сайта'
|
||||
RecoverAppImage: 'Восстановить резервную копию образа снимка'
|
||||
@@ -467,9 +425,6 @@ RecoverDaemonJson: 'Восстановить файл конфигурации
|
||||
RecoverDBData: 'Восстановить данные базы данных'
|
||||
RecoverBackups: 'Восстановить локальный каталог резервных копий'
|
||||
RecoverPanelData: 'Каталог данных восстановления'
|
||||
|
||||
# задача - контейнер
|
||||
ContainerNewCliet: 'Инициализировать Docker-клиент'
|
||||
ContainerImagePull: 'Извлечь изображение контейнера {{ .name }}'
|
||||
ContainerRemoveOld: 'Удалить исходный контейнер {{ .name }}'
|
||||
ContainerImageCheck: 'Проверьте, нормально ли извлекается изображение'
|
||||
@@ -478,22 +433,13 @@ ContainerRecreate: 'Обновление контейнера не удалос
|
||||
ContainerCreate: 'Создать новый контейнер {{ .name }}'
|
||||
ContainerCreateFailed: 'Создание контейнера не удалось, удалите неудавшийся контейнер'
|
||||
ContainerStartCheck: 'Проверить, запущен ли контейнер'
|
||||
|
||||
# задача - изображение
|
||||
ImageBuild: 'Создание изображения'
|
||||
ImageBuildStdoutCheck: 'Анализ содержимого выходного изображения'
|
||||
ImageBuildRes: 'Выходные данные сборки образа: {{ .name }}'
|
||||
ImagePull: 'Вытащить изображение'
|
||||
ImageRepoAuthFromDB: 'Получить информацию об аутентификации репозитория из базы данных'
|
||||
ImaegPullRes: 'Выход извлечения изображения: {{ .name }}'
|
||||
ImagePush: 'Отправить изображение'
|
||||
ImageRenameTag: 'Изменить тег изображения'
|
||||
ImageNewTag: 'Новый тег изображения {{ .name }}'
|
||||
ImaegPushRes: 'Вывод push-изображения: {{ .name }}'
|
||||
ComposeCreate: 'Создать композицию'
|
||||
ComposeCreateRes: 'Составить вывод создания: {{ .name }}'
|
||||
|
||||
# задача - веб-сайт
|
||||
BackupNginxConfig: 'Резервное копирование файла конфигурации OpenResty веб-сайта'
|
||||
CompressFileSuccess: 'Каталог успешно сжат, сжат в {{ .name }}'
|
||||
CompressDir: 'Каталог сжатия'
|
||||
@@ -504,40 +450,27 @@ websiteDir: 'Каталог веб-сайтов'
|
||||
RecoverFailedStartRollBack: 'Восстановление не удалось, начать откат'
|
||||
AppBackupFileIncomplete: 'Файл резервной копии неполный и в нем отсутствуют файлы app.json или app.tar.gz'
|
||||
AppAttributesNotMatch: 'Тип или имя приложения не совпадают'
|
||||
|
||||
#тревога
|
||||
ErrAlert: 'Формат предупреждающего сообщения неверен, проверьте и повторите попытку!'
|
||||
ErrAlertPush: 'Ошибка при отправке оповещения. Проверьте и повторите попытку!'
|
||||
ErrAlertSave: 'Ошибка сохранения информации о тревоге, проверьте и повторите попытку!'
|
||||
ErrAlertSync: 'Ошибка синхронизации информации о тревоге, проверьте и повторите попытку!'
|
||||
ErrAlertRemote: 'Ошибка удаленного сообщения об ошибке, проверьте и повторите попытку!'
|
||||
|
||||
#task - runtime
|
||||
ErrInstallExtension: "Уже выполняется задача установки, подождите, пока задача завершится"
|
||||
|
||||
# alert mail template
|
||||
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 }} является аномальным. Войдите в панель для получения деталей."
|
||||
|
||||
#disk
|
||||
DeviceNotFound: "Устройство {{ .name }} не найдено"
|
||||
DeviceIsMounted: "Устройство {{ .name }} подключено, сначала отключите"
|
||||
PartitionDiskErr: "Не удалось разделить, {{ .err }}"
|
||||
FormatDiskErr: "Не удалось отформатировать диск, {{ .err }}"
|
||||
MountDiskErr: "Не удалось подключить диск, {{ .err }}"
|
||||
UnMountDiskErr: "Не удалось отключить диск, {{ .err }}"
|
||||
XfsNotFound: "Файловая система xfs не обнаружена, сначала установите xfsprogs"
|
||||
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'
|
||||
|
||||
+171
-239
@@ -1,34 +1,28 @@
|
||||
ErrInvalidParams: 'İstek parametre hatası: {{ .detail }}'
|
||||
ErrTokenParse: 'Token oluşturma hatası: {{ .detail }}'
|
||||
ErrInvalidParams: 'İstek geçersiz: {{ .detail }}'
|
||||
ErrTokenParse: 'Token hatası: {{ .detail }}'
|
||||
ErrInitialPassword: 'Orijinal şifre yanlış'
|
||||
ErrInternalServer: 'Dahili sunucu hatası: {{ .detail }}'
|
||||
ErrRecordExist: 'Kayıt zaten mevcut'
|
||||
ErrInternalServer: 'Sunucu hatası: {{ .detail }}'
|
||||
ErrRecordExist: 'Kayıt zaten var'
|
||||
ErrRecordNotFound: 'Kayıt bulunamadı'
|
||||
ErrStructTransform: 'Tür dönüştürme başarısız: {{ .err }}'
|
||||
ErrNotLogin: 'Kullanıcı giriş yapmamış: {{ .detail }}'
|
||||
ErrPasswordExpired: 'Mevcut şifrenin süresi dolmuş: {{ .detail }}'
|
||||
ErrNotSupportType: 'Sistem mevcut türü desteklemiyor: {{ .name }}'
|
||||
ErrProxy: 'İstek hatası, lütfen düğüm durumunu kontrol edin: {{ .detail }}'
|
||||
ErrApiConfigStatusInvalid: 'API arayüzüne erişim yasak: {{ .detail }}'
|
||||
ErrApiConfigKeyInvalid: 'API arayüz anahtarı hatası: {{ .detail }}'
|
||||
ErrApiConfigIPInvalid: 'API arayüzünü çağırmak için kullanılan IP beyaz listede değil: {{ .detail }}'
|
||||
ErrApiConfigDisable: 'Bu arayüz API arayüz çağrılarının kullanımını yasaklıyor: {{ .detail }}'
|
||||
ErrApiConfigKeyTimeInvalid: 'API arayüz zaman damgası hatası: {{ .detail }}'
|
||||
StartPushSSLToNode: "Sertifika düğüme gönderilmeye başlandı"
|
||||
PushSSLToNodeFailed: "Sertifika düğüme gönderilemedi: {{ .err }}"
|
||||
PushSSLToNodeSuccess: "Sertifika düğüme başarıyla gönderildi"
|
||||
ErrShutDown: "Komut manuel olarak sonlandırıldı!"
|
||||
|
||||
ErrMinQuickJump: "Lütfen en az bir hızlı atlama girişi ayarlayın!"
|
||||
ErrMaxQuickJump: "En fazla dört hızlı atlama girişi ayarlayabilirsiniz!"
|
||||
|
||||
#common
|
||||
ErrUsernameIsExist: 'Kullanıcı adı zaten mevcut'
|
||||
ErrNameIsExist: 'İsim zaten mevcut'
|
||||
ErrDemoEnvironment: 'Demo sunucu, bu işlem yasak!'
|
||||
ErrCmdTimeout: 'Komut yürütme zaman aşımına uğradı!'
|
||||
ErrCmdIllegal: 'Yürütme komutunda yasak karakterler var, lütfen değiştirin ve tekrar deneyin!'
|
||||
ErrPortExist: '{{ .port }} portu zaten {{ .type }} [{{ .name }}] tarafından kullanılıyor'
|
||||
ErrStructTransform: 'Dönüşüm hatası: {{ .err }}'
|
||||
ErrNotLogin: 'Oturum açılmamış: {{ .detail }}'
|
||||
ErrPasswordExpired: 'Şifre süresi doldu: {{ .detail }}'
|
||||
ErrNotSupportType: 'Bu tür desteklenmiyor: {{ .name }}'
|
||||
ErrProxy: 'İstek başarısız: {{ .detail }}'
|
||||
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 }}'
|
||||
ErrShutDown: 'Komut manuel durduruldu'
|
||||
ErrMinQuickJump: 'En az bir hızlı erişim ekle'
|
||||
ErrMaxQuickJump: '4 hızlı erişim hakkı var'
|
||||
ErrUsernameIsExist: 'Kullanıcı adı mevcut'
|
||||
ErrNameIsExist: 'İsim mevcut'
|
||||
ErrDemoEnvironment: 'Demo modunda yok'
|
||||
ErrCmdTimeout: 'Komut zaman aşımına uğradı'
|
||||
ErrCmdIllegal: 'Komut geçersiz karakter içeriyor'
|
||||
ErrPortExist: '{{ .port }} portu {{ .type }} [{{ .name }}] tarafından kullanılıyor'
|
||||
TYPE_APP: 'Uygulama'
|
||||
TYPE_RUNTIME: 'Çalışma ortamı'
|
||||
TYPE_DOMAIN: 'Alan Adı'
|
||||
@@ -39,45 +33,40 @@ Failed: 'Başarısız'
|
||||
SystemRestart: 'Sistem yeniden başlatması nedeniyle görev kesildi'
|
||||
ErrGroupIsDefault: 'Varsayılan grup, silinemez'
|
||||
ErrGroupIsInWebsiteUse: 'Grup başka bir web sitesi tarafından kullanılıyor ve silinemez.'
|
||||
Decrypt: "Şifre Çöz"
|
||||
|
||||
#agent
|
||||
ErrAgentAccountBound: 'Bu hesap bir ajana bağlı ve silinemez. Kontrol edip tekrar deneyin!'
|
||||
ErrAgentAccountUnavailable: 'Hesap bağlantı bilgileri kullanılamıyor. Hata: {{ .err }}. Kontrol edip tekrar deneyin!'
|
||||
ErrAgentProviderNotSupported: 'Bu ajan sağlayıcısı desteklenmiyor. Kontrol edip tekrar deneyin!'
|
||||
ErrAgentAccountRequired: 'Lütfen bir ajan hesabı seçip tekrar deneyin.'
|
||||
ErrAgentAccountNotVerified: 'Hesap doğrulanmadı. Kontrol edip tekrar deneyin!'
|
||||
ErrAgentProviderMismatch: 'Hesap sağlayıcısı eşleşmiyor. Kontrol edip tekrar deneyin!'
|
||||
ErrAgentBaseURLRequired: 'Base URL boş olamaz. Kontrol edip tekrar deneyin!'
|
||||
ErrAgentApiKeyRequired: 'API Key boş olamaz. Kontrol edip tekrar deneyin!'
|
||||
ErrAgentComposeRequired: 'Özel compose içeriği boş olamaz. Kontrol edip tekrar deneyin!'
|
||||
ErrAgentIDRequired: 'Ajan ID boş olamaz. Kontrol edip tekrar deneyin!'
|
||||
ErrAgentAccountIDRequired: 'Hesap ID boş olamaz. Kontrol edip tekrar deneyin!'
|
||||
|
||||
#backup
|
||||
Decrypt: 'Şifre Çöz'
|
||||
ErrAgentAccountBound: 'Hesap bir ajana bağlı'
|
||||
ErrAgentAccountUnavailable: 'Hesap bağlantısı yok: {{ .err }}'
|
||||
ErrAgentProviderNotSupported: 'Ajans sağlayıcısı desteklenmiyor'
|
||||
ErrAgentAccountRequired: 'Önce bir ajans hesabı seçin'
|
||||
ErrAgentAccountNotVerified: 'Ajans hesabı doğrulanmadı'
|
||||
ErrAgentProviderMismatch: 'Ajans sağlayıcısı eşleşmiyor'
|
||||
ErrAgentBaseURLRequired: 'Temel URL gerekli'
|
||||
ErrAgentApiKeyRequired: 'API anahtarı gerekli'
|
||||
ErrAgentComposeRequired: 'Compose içeriği gerekli'
|
||||
ErrAgentIDRequired: 'Ajans ID gerekli'
|
||||
ErrAgentAccountIDRequired: 'Hesap ID gerekli'
|
||||
ErrAgentLimitReached: 'Community sürümü en fazla {{ .max }} AI ajanını destekler. Sınırı kaldırmak için Professional sürüme yükseltin'
|
||||
Localhost: 'Yerel Makine'
|
||||
ErrBackupInUsed: 'Yedekleme hesabı zamanlanmış görevde kullanıldı ve silinemez.'
|
||||
ErrBackupCheck: 'Yedekleme hesabı test bağlantısı başarısız {{ .err }}'
|
||||
ErrBackupLocalDelete: 'Yerel sunucu yedekleme hesabını silme henüz desteklenmiyor'
|
||||
ErrBackupLocalCreate: 'Yerel sunucu yedekleme hesapları oluşturma henüz desteklenmiyor'
|
||||
|
||||
#app
|
||||
ErrPortInUsed: '{{ .detail }} portu zaten kullanılıyor!'
|
||||
ErrBackupInUsed: 'Yedek hesabı görevde kullanılıyor'
|
||||
ErrBackupCheck: 'Bağlantı testi başarısız: {{ .err }}'
|
||||
ErrBackupLocalDelete: 'Yerel yedek silme yok'
|
||||
ErrBackupLocalCreate: 'Yerel yedek oluşturma yok'
|
||||
ErrPortInUsed: '{{ .detail }} portu zaten kullanılıyor'
|
||||
ErrAppLimit: 'Yüklenen uygulama sayısı sınırı aştı'
|
||||
ErrNotInstall: 'Uygulama yüklenmedi'
|
||||
ErrPortInOtherApp: '{{ .port }} portu zaten {{ .apps }} uygulaması tarafından kullanılıyor!'
|
||||
ErrDbUserNotValid: 'Mevcut veritabanı, kullanıcı adı ve şifre eşleşmiyor!'
|
||||
ErrUpdateBuWebsite: 'Uygulama başarıyla güncellendi, ancak web sitesi yapılandırma dosyası değiştirme başarısız. Lütfen yapılandırmayı kontrol edin! '
|
||||
Err1PanelNetworkFailed: 'Varsayılan konteyner ağ oluşturma başarısız! {{ .detail }}'
|
||||
ErrFileParse: 'Uygulama docker-compose dosya ayrıştırma başarısız!'
|
||||
ErrPortInOtherApp: '{{ .port }} portu zaten {{ .apps }} uygulaması tarafından kullanılıyor'
|
||||
ErrDbUserNotValid: 'Mevcut veritabanı, kullanıcı adı ve şifre eşleşmiyor'
|
||||
ErrUpdateBuWebsite: 'Uygulama başarıyla güncellendi, ancak web sitesi yapılandırma dosyası değiştirme başarısız. Lütfen yapılandırmayı kontrol edin'
|
||||
Err1PanelNetworkFailed: 'Varsayılan konteyner ağ oluşturma başarısız {{ .detail }}'
|
||||
ErrFileParse: 'Uygulama docker-compose dosya ayrıştırma başarısız'
|
||||
ErrInstallDirNotFound: 'Kurulum dizini mevcut değil. Kaldırmanız gerekiyorsa, lütfen Zorla Kaldır seçeneğini seçin'
|
||||
AppStoreIsUpToDate: 'Uygulama mağazası zaten en son sürüm'
|
||||
LocalAppVersionNull: '{{ .name }} uygulaması sürüme senkronize edilmedi! Uygulama listesine eklenemez'
|
||||
LocalAppVersionErr: '{{ .name }} senkronizasyon sürümü {{ .version }} başarısız! {{ .err }}'
|
||||
LocalAppVersionNull: '{{ .name }} uygulaması sürüme senkronize edilmedi Uygulama listesine eklenemez'
|
||||
LocalAppVersionErr: '{{ .name }} senkronizasyon sürümü {{ .version }} başarısız {{ .err }}'
|
||||
ErrFileNotFound: '{{ .name }} dosyası mevcut değil'
|
||||
ErrFileParseApp: '{{ .name }} dosya ayrıştırma başarısız {{ .err }}'
|
||||
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'
|
||||
ErrCreateHttpClient: 'İstek oluşturma başarısız {{ .err }}'
|
||||
ErrHttpReqTimeOut: 'İstek zaman aşımı {{ .err }}'
|
||||
@@ -90,65 +79,58 @@ 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.'
|
||||
ErrAppNameExist: 'Uygulama adı zaten mevcut'
|
||||
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'
|
||||
ErrAppParamKey: 'Parametre {{ .name }} alanı anormal'
|
||||
ErrAppUpgrade: 'Uygulama {{ .name }} yükseltmesi başarısız {{ .err }}'
|
||||
AppRecover: 'Uygulama {{ .name }} geri alma'
|
||||
PullImageStart: 'Image [{{ .name }}] çekmeye başla'
|
||||
PullImageSuccess: 'Image çekme başarılı'
|
||||
AppStoreIsLastVersion: 'Uygulama Mağazası zaten en son sürüm'
|
||||
AppStoreSyncSuccess: 'Uygulama Mağazası senkronizasyonu başarılı'
|
||||
SyncAppDetail: 'Uygulama yapılandırmasını senkronize et'
|
||||
AppVersionNotMatch: '{{ .name }} uygulaması daha yüksek 1Panel sürümü gerektiriyor, senkronizasyon atlanıyor'
|
||||
MoveSiteDir: "Web sitesi dizini değişikliği tespit edildi. OpenResty web sitesi dizinini {{ .name }} adresine taşımak gerekiyor"
|
||||
MoveSiteDir: 'Web sitesi dizini değişikliği tespit edildi. OpenResty web sitesi dizinini {{ .name }} adresine taşımak gerekiyor'
|
||||
MoveSiteDirSuccess: 'Web sitesi dizini taşıma başarılı'
|
||||
DeleteRuntimePHP: 'PHP çalışma zamanını sil'
|
||||
CustomAppStoreFileValid: 'Uygulama mağazası paketlerinin .tar.gz formatında olması gerekiyor'
|
||||
CustomAppStoreFileValid: 'Uygulama mağazası paketlerinin.tar.gz formatında olması gerekiyor'
|
||||
PullImageTimeout: 'Image çekme zaman aşımı, lütfen image hızlandırmayı artırmayı deneyin veya başka bir image hızlandırmaya geçin'
|
||||
ErrAppIsDown: '{{ .name }} uygulama durumu anormal, lütfen kontrol edin'
|
||||
ErrCustomApps: 'Yüklü bir uygulama var, lütfen önce kaldırın'
|
||||
ErrCustomRuntimes: 'Yüklü bir çalışma ortamı var, lütfen önce silin'
|
||||
ErrAppVersionDeprecated: "{{ .name }} uygulaması mevcut 1Panel sürümü ile uyumlu değil, atlandı"
|
||||
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"
|
||||
UseExistImage: 'Görüntü çekme başarısız, mevcut görüntü kullanılıyor'
|
||||
|
||||
#ssh
|
||||
ExportIP: "Giriş IP"
|
||||
ExportArea: "Konum"
|
||||
ExportPort: "Port"
|
||||
ExportAuthMode: "Giriş Yöntemi"
|
||||
ExportUser: "Kullanıcı"
|
||||
ExportStatus: "Giriş Durumu"
|
||||
ExportDate: "Zaman"
|
||||
|
||||
#file
|
||||
ErrAppVersionDeprecated: '{{ .name }} uygulaması mevcut 1Panel sürümü ile uyumlu değil, atlandı'
|
||||
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'
|
||||
UseExistImage: 'Görüntü zaten mevcut, mevcut görüntü kullanılıyor'
|
||||
ErrDatabaseNotFound: '{{ .name }} veritabanı mevcut değil'
|
||||
ExportIP: 'Giriş IP'
|
||||
ExportArea: 'Konum'
|
||||
ExportPort: 'Port'
|
||||
ExportAuthMode: 'Giriş Yöntemi'
|
||||
ExportUser: 'Kullanıcı'
|
||||
ExportStatus: 'Giriş Durumu'
|
||||
ExportDate: 'Zaman'
|
||||
ErrFileCanNotRead: 'Bu dosya önizlemeyi desteklemiyor'
|
||||
ErrFileToLarge: 'Dosya 10M dan büyük ve açılamıyor'
|
||||
ErrPathNotFound: 'Dizin mevcut değil'
|
||||
ErrMovePathFailed: 'Hedef yol orijinal yolu içeremez!'
|
||||
ErrLinkPathNotFound: 'Hedef yol mevcut değil!'
|
||||
ErrFileIsExist: 'Dosya veya klasör zaten mevcut!'
|
||||
ErrMovePathFailed: 'Hedef yol orijinal yolu içeremez'
|
||||
ErrLinkPathNotFound: 'Hedef yol mevcut değil'
|
||||
ErrFileIsExist: 'Dosya veya klasör zaten mevcut'
|
||||
ErrFileUpload: '{{ .name }} dosya yükleme başarısız {{ .detail }}'
|
||||
ErrFileDownloadDir: 'Klasör indirme desteklenmiyor'
|
||||
ErrCmdNotFound: '{{ .name}} komutu mevcut değil, lütfen önce bu komutu host a yükleyin'
|
||||
ErrCmdNotFound: '{{ .name }} komutu mevcut değil, lütfen önce bu komutu host a yükleyin'
|
||||
ErrSourcePathNotFound: 'Kaynak dizin mevcut değil'
|
||||
ErrFavoriteExist: 'Bu yol zaten favorilere eklendi'
|
||||
ErrInvalidChar: 'Yasak karakterlere izin verilmiyor'
|
||||
ErrPathNotDelete: 'Seçilen dizin silinemez'
|
||||
ErrLogFileToLarge: "Günlük dosyası 500MB'ı aşıyor ve açılamıyor"
|
||||
FileDropFailed: "{{ .name }} dosyası temizlenemedi: {{ .err }}"
|
||||
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ı"
|
||||
ErrBadDecrypt: "Sıkıştırılmış paket şifre çözme parolası hatalı, açma başarısız, lütfen kontrol edip tekrar deneyin!"
|
||||
|
||||
|
||||
#website
|
||||
ErrLogFileToLarge: 'Günlük dosyası 500MB''ı aşıyor ve açılamıyor'
|
||||
FileDropFailed: '{{ .name }} dosyası temizlenemedi: {{ .err }}'
|
||||
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ı'
|
||||
ErrBadDecrypt: 'Sıkıştırılmış paket şifre çözme parolası hatalı, açma başarısız, lütfen kontrol edip tekrar deneyin'
|
||||
ErrAliasIsExist: 'Takma ad zaten mevcut'
|
||||
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 }}'
|
||||
ErrPHPResource: 'Yerel işletim ortamı değiştirmeyi desteklemiyor! '
|
||||
ErrPHPResource: 'Yerel işletim ortamı değiştirmeyi desteklemiyor'
|
||||
ErrPathPermission: 'Dizin dizininde 1000:1000 olmayan izinlere sahip bir klasör tespit edildi, bu web sitesinde Erişim reddedildi hatasına neden olabilir. Lütfen yukarıdaki Kaydet düğmesine tıklayın'
|
||||
ErrDomainIsUsed: 'Alan adı zaten [{{ .name }}] web sitesi tarafından kullanılıyor'
|
||||
ErrDomainFormat: '{{ .name }} alan adı formatı yanlış'
|
||||
@@ -156,11 +138,11 @@ ErrDefaultAlias: 'default ayrılmış bir kod, lütfen başka bir kod kullanın'
|
||||
ErrParentWebsite: 'Önce {{ .name }} alt sitesini silmeniz gerekiyor'
|
||||
ErrBuildDirNotFound: 'Yapı dizini mevcut değil'
|
||||
ErrImageNotExist: 'İşletim ortamı {{ .name }} image mevcut değil, lütfen işletim ortamını yeniden düzenleyin'
|
||||
ErrProxyIsUsed: "Yük dengeleme ters proxy tarafından kullanıldı, silinemez"
|
||||
ErrSSLValid: 'Sertifika dosyası anormal, lütfen sertifika durumunu kontrol edin!'
|
||||
ErrWebsiteDir: "Lütfen web sitesi dizini içindeki bir dizin seçin."
|
||||
ErrComposerFileNotFound: "composer.json dosyası mevcut değil"
|
||||
ErrRuntimeNoPort: "Çalışma zamanı ortamı bir porta sahip değil, lütfen önce çalışma zamanı ortamını düzenleyin."
|
||||
ErrProxyIsUsed: 'Yük dengeleme ters proxy tarafından kullanıldı, silinemez'
|
||||
ErrSSLValid: 'Sertifika dosyası anormal, lütfen sertifika durumunu kontrol edin'
|
||||
ErrWebsiteDir: 'Lütfen web sitesi dizini içindeki bir dizin seçin.'
|
||||
ErrComposerFileNotFound: 'composer.json dosyası mevcut değil'
|
||||
ErrRuntimeNoPort: 'Çalışma zamanı ortamı bir porta sahip değil, lütfen önce çalışma zamanı ortamını düzenleyin.'
|
||||
Status: 'Durum'
|
||||
start: 'Başlat'
|
||||
stop: 'Durdur'
|
||||
@@ -170,14 +152,12 @@ pause: 'Duraklat'
|
||||
unpause: 'Devam Et'
|
||||
remove: 'Sil'
|
||||
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'
|
||||
Set: 'Ayarlar'
|
||||
|
||||
#ssl
|
||||
ErrSSLCannotDelete: '{{ .name }} sertifikası bir web sitesi tarafından kullanılıyor 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'
|
||||
ErrEmailIsExist: 'Posta kutusu zaten mevcut'
|
||||
ErrSSLKeyNotFound: 'Özel anahtar dosyası mevcut değil'
|
||||
ErrSSLCertificateNotFound: 'Sertifika dosyası mevcut değil'
|
||||
@@ -185,12 +165,12 @@ ErrSSLKeyFormat: 'Özel anahtar dosyası doğrulama başarısız'
|
||||
ErrSSLCertificateFormat: 'Sertifika dosyası formatı yanlış, lütfen pem formatını kullanın'
|
||||
ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid veya EabHmacKey boş olamaz'
|
||||
ErrOpenrestyNotFound: 'Http modu önce Openresty yüklenmesini gerektiriyor'
|
||||
ApplySSLStart: 'Sertifika başvurusu başlatılıyor, alan adı [{{ .domain }}] başvuru yöntemi [{{ .type }}] '
|
||||
ApplySSLStart: 'Sertifika başvurusu başlatılıyor, alan adı [{{ .domain }}] başvuru yöntemi [{{ .type }}]'
|
||||
dnsAccount: 'DNS Otomatik'
|
||||
dnsManual: 'DNS Manuel'
|
||||
http: 'HTTP'
|
||||
ApplySSLFailed: '[{{ .domain }}] sertifika başvurusu başarısız, {{ .detail }} '
|
||||
ApplySSLSuccess: '[{{ .domain }}] sertifika başvurusu başarılı! !'
|
||||
ApplySSLFailed: '[{{ .domain }}] sertifika başvurusu başarısız, {{ .detail }}'
|
||||
ApplySSLSuccess: '[{{ .domain }}] sertifika başvurusu başarılı'
|
||||
DNSAccountName: 'DNS hesabı [{{ .name }}] sağlayıcı [{{ .type }}]'
|
||||
PushDirLog: 'Sertifika [{{ .path }}] dizinine gönderildi {{ .status }}'
|
||||
ErrDeleteCAWithSSL: 'Mevcut kuruluşun verilmiş bir sertifikası var ve silinemez.'
|
||||
@@ -205,94 +185,79 @@ ExecShellSuccess: 'Betik yürütme başarılı'
|
||||
StartUpdateSystemSSL: 'Sistem sertifikası güncellemeyi başlat'
|
||||
UpdateSystemSSLSuccess: 'Sistem sertifikası güncelleme başarılı'
|
||||
ErrWildcardDomain: 'HTTP modunda joker alan adı sertifikası başvurusu yapılamıyor'
|
||||
ErrApplySSLCanNotDelete: "İşlemde olan sertifika {{.name}} silinemez, lütfen daha sonra tekrar deneyin."
|
||||
|
||||
#mysql
|
||||
ErrApplySSLCanNotDelete: 'İşlemde olan sertifika {{ .name }} silinemez, lütfen daha sonra tekrar deneyin.'
|
||||
StartPushSSLToNode: 'Sertifika düğüme gönderilmeye başlandı'
|
||||
PushSSLToNodeFailed: 'Sertifika düğüme gönderilemedi: {{ .err }}'
|
||||
PushSSLToNodeSuccess: 'Sertifika düğüme başarıyla gönderildi'
|
||||
ErrUserIsExist: 'Mevcut kullanıcı 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'
|
||||
ErrRemoteExist: 'Uzak veritabanında bu adla zaten mevcut, lütfen değiştirin ve tekrar deneyin'
|
||||
ErrLocalExist: 'Yerel veritabanında bu ad zaten mevcut, lütfen değiştirin ve tekrar deneyin'
|
||||
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..."
|
||||
Arg: "Argüman"
|
||||
|
||||
#redis
|
||||
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...'
|
||||
Arg: 'Argüman'
|
||||
ErrTypeOfRedis: 'Kurtarma dosyası türü mevcut kalıcılık yöntemiyle eşleşmiyor, lütfen değiştirin ve tekrar deneyin'
|
||||
|
||||
#container
|
||||
ErrInUsed: "{{ .detail }} 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!"
|
||||
ErrPortRules: 'Port numarası eşleşmiyor, lütfen yeniden girin!'
|
||||
ErrInUsed: '{{ .detail }} 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'
|
||||
ErrPortRules: 'Port numarası eşleşmiyor, lütfen yeniden girin'
|
||||
ErrPgImagePull: 'Image çekme zaman aşımı, lütfen image hızlandırma yapılandırın veya manuel olarak {{ .name }} imageını çekin ve tekrar deneyin'
|
||||
PruneHelper: "Bu temizlik {{ .name }} disk alanı {{ .size }} boşalttı"
|
||||
ImageRemoveHelper: "{{ .name }} imajı silindi, {{ .size }} disk alanı boşalttı"
|
||||
BuildCache: "Derleme önbelleği"
|
||||
Volume: "Depolama hacmi"
|
||||
Network: "Ağ"
|
||||
PruneStart: "Temizlik devam ediyor, lütfen bekleyin..."
|
||||
|
||||
#runtime
|
||||
ErrFileNotExist: '{{ .detail }} dosyası mevcut değil! Lütfen kaynak dosyanın bütünlüğünü kontrol edin!'
|
||||
PruneHelper: 'Bu temizlik {{ .name }} disk alanı {{ .size }} boşalttı'
|
||||
ImageRemoveHelper: '{{ .name }} imajı silindi, {{ .size }} disk alanı boşalttı'
|
||||
BuildCache: 'Derleme önbelleği'
|
||||
Volume: 'Depolama hacmi'
|
||||
Network: 'Ağ'
|
||||
PruneStart: 'Temizlik devam ediyor, lütfen bekleyin...'
|
||||
ErrFileNotExist: '{{ .detail }} dosyası mevcut değil Lütfen kaynak dosyanın bütünlüğünü kontrol edin'
|
||||
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.'
|
||||
ErrDelWithWebsite: 'İşletim ortamı zaten bir web sitesiyle ilişkili ve silinemez'
|
||||
ErrRuntimeStart: 'Başlatma başarısız'
|
||||
ErrPackageJsonNotFound: 'package.json dosyası mevcut değil'
|
||||
ErrScriptsNotFound: 'package.json içinde scripts yapılandırma öğesi bulunamadı'
|
||||
ErrContainerNameNotFound: 'Konteyner adı alınamıyor, lütfen .env dosyasını kontrol edin'
|
||||
ErrNodeModulesNotFound: 'node_modules klasörü mevcut değil! Lütfen çalışma ortamını düzenleyin veya çalışma ortamının başarıyla başlatılmasını bekleyin'
|
||||
ErrContainerNameNotFound: 'Konteyner adı alınamıyor, lütfen.env dosyasını kontrol edin'
|
||||
ErrNodeModulesNotFound: 'node_modules klasörü mevcut değil Lütfen çalışma ortamını düzenleyin veya çalışma ortamının başarıyla başlatılmasını bekleyin'
|
||||
ErrContainerNameIsNull: 'Konteyner adı mevcut değil'
|
||||
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"
|
||||
|
||||
#tool
|
||||
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'
|
||||
ErrConfigNotFound: 'Yapılandırma dosyası mevcut değil'
|
||||
ErrConfigParse: 'Yapılandırma dosyası formatı yanlış'
|
||||
ErrConfigIsNull: 'Yapılandırma dosyası boş olamaz'
|
||||
ErrConfigDirNotFound: 'Çalışma dizini mevcut değil'
|
||||
ErrConfigAlreadyExist: 'Aynı ada sahip bir yapılandırma dosyası zaten mevcut'
|
||||
ErrUserFindErr: 'Kullanıcı {{ .name }} arama başarısız {{ .err }}'
|
||||
|
||||
#cronjob
|
||||
CutWebsiteLogSuccess: '{{ .name }} web sitesi günlüğü başarıyla kesildi, yedekleme yolu {{ .path }}'
|
||||
HandleShell: 'Betik {{ .name }} yürüt'
|
||||
HandleCurl: "URL'ye Eriş {{ .name }}"
|
||||
HandleCurl: 'URL''ye Eriş {{ .name }}'
|
||||
HandleNtpSync: 'Sistem zaman senkronizasyonu'
|
||||
HandleSystemClean: 'Sistem önbellek temizliği'
|
||||
SystemLog: 'Sistem Günlüğü'
|
||||
CutWebsiteLog: 'Web Sitesi Günlüğünü Döndür'
|
||||
FileOrDir: 'Dizin / Dosya'
|
||||
UploadFile: 'Yedekleme dosyası {{ .file }} {{ .backup }} konumuna yükleniyor'
|
||||
Upload: "Yükle"
|
||||
IgnoreBackupErr: "Yedekleme başarısız, hata: {{ .detail }}, bu hata yoksayılıyor..."
|
||||
IgnoreUploadErr: "Yükleme başarısız, hata: {{ .detail }}, bu hata yoksayılıyor..."
|
||||
LoadBackupFailed: "Yedek hesap bağlantısı alınamadı, hata: {{ .detail }}"
|
||||
InExecuting: "Mevcut görev yürütülüyor, lütfen tekrar yürütmeyin!"
|
||||
NoSuchResource: "Veritabanında yedek içeriği bulunamadı, atlanıyor..."
|
||||
CleanLog: "Günlüğü 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."
|
||||
|
||||
#toolbox
|
||||
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!'
|
||||
ErrClamdscanNotFound: 'clamdscan komutu tespit edilmedi, lütfen yüklemek için belgeleri inceleyin!'
|
||||
TaskSwapSet: "Swap Ayarla"
|
||||
SetSwap: "Swap Ayarla {{ .path }} - {{ .size }}"
|
||||
CreateSwap: "Swap Dosyası Oluştur"
|
||||
FormatSwap: "Swap Dosyasını Biçimlendir"
|
||||
EnableSwap: "Swap Etkinleştir"
|
||||
|
||||
#tamper
|
||||
CleanTamperSetting: "Geçmiş koruma ayarlarını temizle"
|
||||
SetTamperWithRules: "Kurallara göre dizin korumasını başlat"
|
||||
ProtectDir: "Dizini koru {{ .name }}"
|
||||
IgnoreFile: "Dosyayı koru {{ .name }}"
|
||||
TamperSetSuccessful: "Koruma ayarları tamamlandı, aşağıdaki dizinler izlenmeye başlanıyor:"
|
||||
|
||||
#waf
|
||||
Upload: 'Yükle'
|
||||
IgnoreBackupErr: 'Yedekleme başarısız, hata: {{ .detail }}, bu hata yoksayılıyor...'
|
||||
IgnoreUploadErr: 'Yükleme başarısız, hata: {{ .detail }}, bu hata yoksayılıyor...'
|
||||
LoadBackupFailed: 'Yedek hesap bağlantısı alınamadı, hata: {{ .detail }}'
|
||||
InExecuting: 'Mevcut görev yürütülüyor, lütfen tekrar yürütmeyin'
|
||||
NoSuchResource: 'Veritabanında yedek içeriği bulunamadı, atlanıyor...'
|
||||
CleanLog: 'Günlüğü 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.'
|
||||
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'
|
||||
ErrClamdscanNotFound: 'clamdscan komutu tespit edilmedi, lütfen yüklemek için belgeleri inceleyin'
|
||||
TaskSwapSet: 'Swap Ayarla'
|
||||
SetSwap: 'Swap Ayarla {{ .path }} - {{ .size }}'
|
||||
CreateSwap: 'Swap Dosyası Oluştur'
|
||||
FormatSwap: 'Swap Dosyasını Biçimlendir'
|
||||
EnableSwap: 'Swap Etkinleştir'
|
||||
CleanTamperSetting: 'Geçmiş koruma ayarlarını temizle'
|
||||
SetTamperWithRules: 'Kurallara göre dizin korumasını başlat'
|
||||
ProtectDir: 'Dizini koru {{ .name }}'
|
||||
IgnoreFile: 'Dosyayı koru {{ .name }}'
|
||||
TamperSetSuccessful: 'Koruma ayarları tamamlandı, aşağıdaki dizinler izlenmeye başlanıyor:'
|
||||
ErrScope: 'Bu yapılandırmayı değiştirme desteklenmiyor'
|
||||
ErrStateChange: 'Durum değiştirme başarısız'
|
||||
ErrRuleExist: 'Kural zaten mevcut'
|
||||
@@ -300,7 +265,7 @@ ErrRuleNotExist: 'Kural mevcut değil'
|
||||
ErrParseIP: 'Yanlış IP formatı'
|
||||
ErrDefaultIP: 'default ayrılmış bir isim, lütfen başka bir isme değiştirin'
|
||||
ErrGroupInUse: 'IP grubu kara liste/beyaz liste tarafından kullanılıyor ve silinemez'
|
||||
ErrIPGroupAclUse: "IP grubu {{ .name }} web sitesinin özel kuralları tarafından kullanılıyor, silinemez"
|
||||
ErrIPGroupAclUse: 'IP grubu {{ .name }} web sitesinin özel kuralları tarafından kullanılıyor, silinemez'
|
||||
ErrGroupExist: 'IP grup adı zaten mevcut'
|
||||
ErrIPRange: 'Yanlış IP aralığı'
|
||||
ErrIPExist: 'IP zaten mevcut'
|
||||
@@ -311,10 +276,10 @@ xss: 'XSS'
|
||||
phpExec: 'PHP betik yürütme'
|
||||
oneWordTrojan: 'Tek Kelime Truva Atı'
|
||||
appFilter: 'Tehlikeli dizin filtreleme uygula'
|
||||
webshell: 'Webshell'
|
||||
webShell: 'Webshell'
|
||||
args: 'Parametre kuralları'
|
||||
protocolFilter: 'Protokol filtreleme'
|
||||
javaFileter: 'Java tehlikeli dosya filtresi'
|
||||
javaFilter: 'Java tehlikeli dosya filtresi'
|
||||
scannerFilter: 'Tarayıcı filtresi'
|
||||
escapeFilter: 'kaçış filtresi'
|
||||
customRule: 'Özel kural'
|
||||
@@ -344,10 +309,9 @@ ErrDBNotExist: 'Veritabanı mevcut değil'
|
||||
allow: 'izin ver'
|
||||
deny: 'reddet'
|
||||
OpenrestyNotFound: 'Openresty yüklü değil'
|
||||
remoteIpIsNull: "IP listesi boş"
|
||||
OpenrestyVersionErr: "Openresty sürümü çok düşük, lütfen Openresty'i 1.27.1.2-2-2-focal olarak güncelleyin"
|
||||
|
||||
#task
|
||||
remoteIpIsNull: 'IP listesi boş'
|
||||
OpenrestyVersionErr: 'Openresty sürümü çok düşük, lütfen Openresty''i 1.27.1.2-2-2-focal olarak güncelleyin'
|
||||
ErrFileTooLarge: 'File is larger than 1 MB and cannot be uploaded'
|
||||
TaskStart: '{{ .name }} görevi başlıyor [BAŞLAT]'
|
||||
TaskEnd: '{{ .name }} Görev tamamlandı [TAMAMLANDI]'
|
||||
TaskFailed: '{{ .name }} görev başarısız'
|
||||
@@ -363,7 +327,7 @@ TaskDelete: 'Sil'
|
||||
TaskUpgrade: 'Yükselt'
|
||||
TaskUpdate: 'Güncelle'
|
||||
TaskRestart: 'Yeniden Başlat'
|
||||
TaskProtect: "Koru"
|
||||
TaskProtect: 'Koru'
|
||||
TaskBackup: 'Yedekle'
|
||||
TaskRecover: 'Kurtar'
|
||||
TaskRollback: 'Geri Al'
|
||||
@@ -371,10 +335,10 @@ TaskPull: 'Çek'
|
||||
TaskCommit: 'işleme'
|
||||
TaskBuild: 'Yapı'
|
||||
TaskPush: 'Gönder'
|
||||
TaskClean: "Temizleme"
|
||||
TaskClean: 'Temizleme'
|
||||
TaskHandle: 'Yürüt'
|
||||
TaskImport: "İçe Aktar"
|
||||
TaskExport: "Dışa Aktar"
|
||||
TaskImport: 'İçe Aktar'
|
||||
TaskExport: 'Dışa Aktar'
|
||||
Website: 'Web Sitesi'
|
||||
App: 'Uygulama'
|
||||
Runtime: 'Çalışma ortamı'
|
||||
@@ -406,18 +370,12 @@ RuntimeExtension: 'Çalışma Ortamı Uzantısı'
|
||||
TaskIsExecuting: 'Görev çalışıyor'
|
||||
CustomAppstore: 'Özel uygulama deposu'
|
||||
TaskExec: 'Çalıştır'
|
||||
TaskBatch: "Toplu İşlem"
|
||||
TaskBatch: 'Toplu İşlem'
|
||||
FileConvert: 'Dosya Formatı Dönüştürme'
|
||||
|
||||
# task - clam
|
||||
Clamscan: "{{ .name }} Tara"
|
||||
TaskScan: "Tara"
|
||||
|
||||
# task - ai
|
||||
Clamscan: '{{ .name }} Tara'
|
||||
TaskScan: 'Tara'
|
||||
OllamaModelPull: 'Ollama modeli {{ .name }} çek'
|
||||
OllamaModelSize: 'Ollama modeli {{ .name }} boyutunu al'
|
||||
|
||||
# task-snapshot
|
||||
Snapshot: 'Anlık Görüntü'
|
||||
SnapDBInfo: '1Panel veritabanı bilgilerini yaz'
|
||||
SnapCopy: 'Dosya ve dizinleri {{ .name }} kopyala'
|
||||
@@ -443,7 +401,6 @@ SnapCompressSize: 'Anlık görüntü dosya boyutu {{ .name }}'
|
||||
SnapUpload: 'Anlık görüntü dosyasını yükle'
|
||||
SnapUploadTo: 'Anlık görüntü dosyasını {{ .name }} konumuna yükle'
|
||||
SnapUploadRes: 'Anlık görüntü dosyasını {{ .name }} konumuna yükle'
|
||||
|
||||
SnapshotRecover: 'Anlık Görüntü Geri Yükleme'
|
||||
RecoverDownload: 'Anlık görüntü dosyasını indir'
|
||||
Download: 'İndir'
|
||||
@@ -451,10 +408,10 @@ RecoverDownloadAccount: 'Anlık görüntü indirme yedek hesabı al {{ .name }}'
|
||||
RecoverDecompress: 'Anlık görüntü sıkıştırılmış dosyalarını açma'
|
||||
Decompress: 'Açma'
|
||||
BackupBeforeRecover: 'Anlık görüntü öncesi sistem ilgili verileri yedekleme'
|
||||
Readjson: 'Anlık görüntüdeki Json dosyasını oku'
|
||||
ReadjsonPath: 'Anlık görüntüdeki Json dosya yolunu al'
|
||||
ReadjsonContent: 'Json dosyasını oku'
|
||||
ReadjsonMarshal: 'Json kaçış işlemesi'
|
||||
ReadJson: 'Anlık görüntüdeki Json dosyasını oku'
|
||||
ReadJsonPath: 'Anlık görüntüdeki Json dosya yolunu al'
|
||||
ReadJsonContent: 'Json dosyasını oku'
|
||||
ReadJsonMarshal: 'Json kaçış işlemesi'
|
||||
RecoverApp: 'Yüklü uygulamaları geri yükle'
|
||||
RecoverWebsite: 'Web sitesi dizinini kurtar'
|
||||
RecoverAppImage: 'Anlık görüntü imaj yedeklemesini geri yükle'
|
||||
@@ -468,9 +425,6 @@ RecoverDaemonJson: 'Konteyner yapılandırma daemon.json dosyasını geri yükle
|
||||
RecoverDBData: 'Veritabanı verilerini kurtar'
|
||||
RecoverBackups: 'Yerel yedekleme dizinini geri yükle'
|
||||
RecoverPanelData: 'Veri dizinini kurtar'
|
||||
|
||||
# task - container
|
||||
ContainerNewCliet: 'Docker İstemcisini Başlat'
|
||||
ContainerImagePull: 'Konteyner imajını çek {{ .name }}'
|
||||
ContainerRemoveOld: 'Orijinal konteyneri kaldır {{ .name }}'
|
||||
ContainerImageCheck: 'İmajın normal çekilip çekilmediğini kontrol et'
|
||||
@@ -479,22 +433,13 @@ ContainerRecreate: 'Konteyner güncellemesi başarısız, şimdi orijinal kontey
|
||||
ContainerCreate: 'Yeni konteyner oluştur {{ .name }}'
|
||||
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'
|
||||
|
||||
# task - image
|
||||
ImageBuild: 'İmaj Oluşturma'
|
||||
ImageBuildStdoutCheck: 'İmaj çıktı içeriğini ayrıştır'
|
||||
ImageBuildRes: 'İmaj oluşturma çıktısı: {{ .name }}'
|
||||
ImagePull: 'İmaj çek'
|
||||
ImageRepoAuthFromDB: 'Veritabanından depo kimlik doğrulama bilgilerini al'
|
||||
ImaegPullRes: 'İmaj çekme çıktısı: {{ .name }}'
|
||||
ImagePush: 'İmaj gönder'
|
||||
ImageRenameTag: 'İmaj etiketini değiştir'
|
||||
ImageNewTag: 'Yeni imaj etiketi {{ .name }}'
|
||||
ImaegPushRes: 'İmaj gönderme çıktısı: {{ .name }}'
|
||||
ComposeCreate: 'Kompozisyon oluştur'
|
||||
ComposeCreateRes: 'Compose oluşturma çıktısı: {{ .name }}'
|
||||
|
||||
# task - website
|
||||
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 }}'
|
||||
CompressDir: 'Sıkıştırma dizini'
|
||||
@@ -505,40 +450,27 @@ websiteDir: 'Web Sitesi Dizini'
|
||||
RecoverFailedStartRollBack: 'Kurtarma başarısız, geri almayı başlat'
|
||||
AppBackupFileIncomplete: 'Yedekleme dosyası eksik ve app.json veya app.tar.gz dosyalarından yoksun'
|
||||
AppAttributesNotMatch: 'Uygulama türü veya adı eşleşmiyor'
|
||||
|
||||
#alert
|
||||
ErrAlert: 'Uyarı mesajının formatı yanlış, lütfen kontrol edin ve tekrar deneyin!'
|
||||
ErrAlertPush: 'Uyarı bilgisi gönderiminde hata, lütfen kontrol edin ve tekrar deneyin!'
|
||||
ErrAlertSave: 'Alarm bilgisini kaydetmede hata, lütfen kontrol edin ve tekrar deneyin!'
|
||||
ErrAlertSync: 'Alarm bilgisi senkronizasyon hatası, lütfen kontrol edin ve tekrar deneyin!'
|
||||
ErrAlertRemote: 'Alarm mesajı uzak hata, lütfen kontrol edin ve tekrar deneyin!'
|
||||
|
||||
#task - runtime
|
||||
ErrInstallExtension: "Zaten devam eden bir kurulum görevi var, görevin bitmesini bekleyin"
|
||||
|
||||
# alert mail template
|
||||
PanelAlertTitle: "Panel Uyarı Bildirimi"
|
||||
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."
|
||||
LicenseExpirationAlert: "Paneliniz {{ .node }}{{ .ip }}, lisans {{ .day }} gün içinde süresi dolacak. Detaylar için paneline giriş yapın."
|
||||
CronJobFailedAlert: "Paneliniz {{ .node }}{{ .ip }}, zamanlanmış görev {{ .name }} çalıştırma başarısız oldu. Detaylar için paneline giriş yapın."
|
||||
ClamAlert: "Paneliniz {{ .node }}{{ .ip }}, virüs tarama görevi {{ .num }} enfekte dosya tespit etti. Detaylar için paneline giriş yapın."
|
||||
WebSiteAlert: "Paneliniz {{ .node }}{{ .ip }}, {{ .num }} web sitesi {{ .day }} gün içinde süresi dolacak. Detaylar için paneline giriş yapın."
|
||||
SSLAlert: "Paneliniz {{ .node }}{{ .ip }}, {{ .num }} SSL sertifikası {{ .day }} gün içinde süresi dolacak. Detaylar için paneline giriş yapın."
|
||||
DiskUsedAlert: "Paneliniz {{ .node }}{{ .ip }}, {{ .name }} diski kullanımı {{ .used }}'a ulaştı. Detaylar için paneline giriş yapın."
|
||||
ResourceAlert: "Paneliniz {{ .node }}{{ .ip }}, son {{ .time }} dakika içindeki ortalama {{ .name }} kullanım oranı {{ .used }}'dır. Detaylar için paneline giriş yapın."
|
||||
PanelVersionAlert: "Paneliniz {{ .node }}{{ .ip }}, en son panel sürümü yükseltme için mevcut. Detaylar için paneline giriş yapın."
|
||||
PanelPwdExpirationAlert: "Paneliniz {{ .node }}{{ .ip }}, panel şifresi {{ .day }} gün içinde süresi dolacak. Detaylar için paneline giriş yapın."
|
||||
CommonAlert: "Paneliniz {{ .node }}{{ .ip }}, {{ .msg }}. 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."
|
||||
SSHAndPanelLoginAlert: "Paneliniz {{ .node }}{{ .ip }}, {{ .loginIp }} adresinden {{ .name }} girişi anormal. Detaylar için paneline giriş yapın."
|
||||
|
||||
#disk
|
||||
DeviceNotFound: "Cihaz {{ .name }} bulunamadı"
|
||||
DeviceIsMounted: "Cihaz {{ .name }} bağlandı, önce çıkarın"
|
||||
PartitionDiskErr: "Bölümleme başarısız, {{ .err }}"
|
||||
FormatDiskErr: "Disk biçimlendirme başarısız, {{ .err }}"
|
||||
MountDiskErr: "Disk bağlama başarısız, {{ .err }}"
|
||||
UnMountDiskErr: "Disk bağının kaldırılması başarısız, {{ .err }}"
|
||||
XfsNotFound: "XFS dosya sistemi algılanmadı, lütfen önce xfsprogs'i yükleyin"
|
||||
ErrAlertSync: 'Alarm bilgisi senkronizasyon hatası, lütfen kontrol edin ve tekrar deneyin'
|
||||
ErrInstallExtension: 'Zaten devam eden bir kurulum görevi var, görevin bitmesini bekleyin'
|
||||
PanelAlertTitle: 'Panel Uyarı Bildirimi'
|
||||
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.'
|
||||
LicenseExpirationAlert: 'Paneliniz {{ .node }}{{ .ip }}, lisans {{ .day }} gün içinde süresi dolacak. Detaylar için paneline giriş yapın.'
|
||||
CronJobFailedAlert: 'Paneliniz {{ .node }}{{ .ip }}, zamanlanmış görev {{ .name }} çalıştırma başarısız oldu. Detaylar için paneline giriş yapın.'
|
||||
ClamAlert: 'Paneliniz {{ .node }}{{ .ip }}, virüs tarama görevi {{ .num }} enfekte dosya tespit etti. Detaylar için paneline giriş yapın.'
|
||||
WebSiteAlert: 'Paneliniz {{ .node }}{{ .ip }}, {{ .num }} web sitesi {{ .day }} gün içinde süresi dolacak. Detaylar için paneline giriş yapın.'
|
||||
SSLAlert: 'Paneliniz {{ .node }}{{ .ip }}, {{ .num }} SSL sertifikası {{ .day }} gün içinde süresi dolacak. Detaylar için paneline giriş yapın.'
|
||||
DiskUsedAlert: 'Paneliniz {{ .node }}{{ .ip }}, {{ .name }} diski kullanımı {{ .used }}''a ulaştı. Detaylar için paneline giriş yapın.'
|
||||
ResourceAlert: 'Paneliniz {{ .node }}{{ .ip }}, son {{ .time }} dakika içindeki ortalama {{ .name }} kullanım oranı {{ .used }}''dır. Detaylar için paneline giriş yapın.'
|
||||
PanelVersionAlert: 'Paneliniz {{ .node }}{{ .ip }}, en son panel sürümü yükseltme için mevcut. Detaylar için paneline giriş yapın.'
|
||||
PanelPwdExpirationAlert: 'Paneliniz {{ .node }}{{ .ip }}, panel şifresi {{ .day }} gün içinde süresi dolacak. Detaylar için paneline giriş yapın.'
|
||||
CommonAlert: 'Paneliniz {{ .node }}{{ .ip }}, {{ .msg }}. 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.'
|
||||
SSHAndPanelLoginAlert: 'Paneliniz {{ .node }}{{ .ip }}, {{ .loginIp }} adresinden {{ .name }} girişi anormal. Detaylar için paneline giriş yapın.'
|
||||
DeviceNotFound: 'Cihaz {{ .name }} bulunamadı'
|
||||
DeviceIsMounted: 'Cihaz {{ .name }} bağlandı, önce çıkarın'
|
||||
PartitionDiskErr: 'Bölümleme başarısız, {{ .err }}'
|
||||
FormatDiskErr: 'Disk biçimlendirme başarısız, {{ .err }}'
|
||||
MountDiskErr: 'Disk bağlama başarısız, {{ .err }}'
|
||||
XfsNotFound: 'XFS dosya sistemi algılanmadı, lütfen önce xfsprogs''i yükleyin'
|
||||
|
||||
+171
-237
@@ -14,12 +14,9 @@ ErrApiConfigKeyInvalid: 'API 介面金鑰錯誤: {{ .detail }}'
|
||||
ErrApiConfigIPInvalid: '呼叫 API 介面 IP 不在白名單: {{ .detail }}'
|
||||
ErrApiConfigDisable: '此介面禁止使用 API 介面呼叫: {{ .detail }}'
|
||||
ErrApiConfigKeyTimeInvalid: 'API 介面時間戳記錯誤: {{ .detail }}'
|
||||
ErrShutDown: "指令被手動結束!"
|
||||
|
||||
ErrMinQuickJump: "請至少設定一個快速跳轉入口!"
|
||||
ErrMaxQuickJump: "最多可設定四個快速跳轉入口!"
|
||||
|
||||
#common
|
||||
ErrShutDown: '指令被手動結束!'
|
||||
ErrMinQuickJump: '請至少設定一個快速跳轉入口!'
|
||||
ErrMaxQuickJump: '最多可設定四個快速跳轉入口!'
|
||||
ErrUsernameIsExist: '使用者名稱已存在'
|
||||
ErrNameIsExist: '名稱已存在'
|
||||
ErrDemoEnvironment: '示範伺服器,禁止此操作!'
|
||||
@@ -36,37 +33,32 @@ Failed: '失敗'
|
||||
SystemRestart: '系統重新啟動導致任務中斷'
|
||||
ErrGroupIsDefault: '預設分組,無法刪除'
|
||||
ErrGroupIsInWebsiteUse: '分組正在被其他網站使用,無法刪除'
|
||||
Decrypt: "解密"
|
||||
|
||||
#agent
|
||||
ErrAgentAccountBound: '該帳號已綁定到智能體,無法刪除,請檢查後重試!!'
|
||||
ErrAgentAccountUnavailable: '帳號連線資訊不可用,錯誤:{{ .err }},請檢查後重試!'
|
||||
ErrAgentProviderNotSupported: '暫不支援該智能體提供商,請檢查後重試!'
|
||||
Decrypt: '解密'
|
||||
ErrAgentAccountBound: '該帳號已綁定到智能體,無法刪除,請重試。'
|
||||
ErrAgentAccountUnavailable: '帳號連線資訊不可用,錯誤:{{ .err }},請重試'
|
||||
ErrAgentProviderNotSupported: '暫不支援該智能體提供商,請重試'
|
||||
ErrAgentAccountRequired: '請選擇智能體帳號後重試'
|
||||
ErrAgentAccountNotVerified: '帳號未驗證通過,請檢查後重試!'
|
||||
ErrAgentProviderMismatch: '帳號提供商不匹配,請檢查後重試!'
|
||||
ErrAgentBaseURLRequired: 'Base URL 不能為空,請檢查後重試!'
|
||||
ErrAgentApiKeyRequired: 'API Key 不能為空,請檢查後重試!'
|
||||
ErrAgentComposeRequired: '自訂編排內容不能為空,請檢查後重試!'
|
||||
ErrAgentIDRequired: '智能體 ID 不能為空,請檢查後重試!'
|
||||
ErrAgentAccountIDRequired: '帳號 ID 不能為空,請檢查後重試!'
|
||||
|
||||
#backup
|
||||
ErrAgentAccountNotVerified: '帳號未驗證通過,請重試'
|
||||
ErrAgentProviderMismatch: '帳號提供商不符,請重試'
|
||||
ErrAgentBaseURLRequired: 'Base URL 不可為空,請重試'
|
||||
ErrAgentApiKeyRequired: 'API Key 不可為空,請重試'
|
||||
ErrAgentComposeRequired: '自訂編排內容不可為空,請重試'
|
||||
ErrAgentIDRequired: '智能體 ID 不可為空,請重試'
|
||||
ErrAgentAccountIDRequired: '帳號 ID 不可為空,請重試'
|
||||
ErrAgentLimitReached: '社群版最多支援建立 {{ .max }} 個智能體,升級至專業版則無數量限制'
|
||||
Localhost: '本機'
|
||||
ErrBackupInUsed: '此備份帳號已在排程任務中使用,無法刪除'
|
||||
ErrBackupCheck: '備份帳號測試連線失敗{{ .err }}'
|
||||
ErrBackupLocalDelete: '暫時不支援刪除本機伺服器備份帳號'
|
||||
ErrBackupLocalCreate: '暫時不支援建立本機伺服器備份帳號'
|
||||
|
||||
#app
|
||||
ErrPortInUsed: '{{ .detail }} 連接埠已被佔用!'
|
||||
ErrAppLimit: '應用程式超出安裝數量限制'
|
||||
ErrNotInstall: '應用程式未安裝'
|
||||
ErrPortInOtherApp: '{{ .port }} 連接埠已被應用程式{{ .apps }} 佔用!'
|
||||
ErrDbUserNotValid: '存量資料庫,使用者名稱密碼不符!'
|
||||
ErrUpdateBuWebsite: '應用程式更新成功,但網站設定檔修改失敗,請檢查設定! '
|
||||
ErrUpdateBuWebsite: '應用程式更新成功,但網站設定檔修改失敗,請檢查設定!'
|
||||
Err1PanelNetworkFailed: '預設容器網路建立失敗! {{ .detail }}'
|
||||
ErrFileParse: '應用docker-compose 檔案解析失敗!'
|
||||
ErrFileParse: '應用docker-compose 檔解析失敗!'
|
||||
ErrInstallDirNotFound: '安裝目錄不存在,如需移除,請選擇強制移除'
|
||||
AppStoreIsUpToDate: '應用程式商店已經是最新版本'
|
||||
LocalAppVersionNull: '{{ .name }} 應用程式未同步到版本!無法加入到應用程式列表'
|
||||
@@ -82,115 +74,108 @@ ErrHttpReqFailed: '請求失敗{{ .err }}'
|
||||
ErrNoSuchHost: '無法找到請求的伺服器{{ .err }}'
|
||||
ErrHttpReqNotFound: '無法找到要求的資源{{ .err }}'
|
||||
ErrContainerNotFound: '{{ .name }} 容器不存在'
|
||||
ErrContainerMsg: '{{ .name }} 容器異常,請在容器頁面上查看日誌'
|
||||
ErrContainerMsg: '{{ .name }} 容器異常,請在容器頁面上檢視日誌'
|
||||
ErrAppBackup: '{{ .name }} 應用備份失敗 {{ .err }}'
|
||||
ErrVersionTooLow: '目前1Panel 版本過低,無法更新應用程式商店,請升級版本之後操作'
|
||||
ErrVersionTooLow: '目前 1Panel 版本過低,無法更新應用程式商店,請升級版本之後操作'
|
||||
ErrAppNameExist: '應用程式名稱已存在'
|
||||
AppStoreIsSyncing: '應用程式商店正在同步中,請稍後再試'
|
||||
AppStoreIsSyncing: '應用程式商店正在同步中,請稍後重試'
|
||||
ErrGetCompose: 'docker-compose.yml 檔案取得失敗!{{ .detail }}'
|
||||
ErrAppWarn: '狀態異常,請檢視日誌'
|
||||
ErrAppParamKey: '參數{{ .name }} 欄位異常'
|
||||
ErrAppUpgrade: '應用程式{{ .name }} 升級失敗{{ .err }}'
|
||||
AppRecover: '應用程式{{ .name }} 回滾'
|
||||
PullImageStart: '開始拉取鏡像 [{{ .name }}]'
|
||||
PullImageSuccess: '鏡像拉取成功'
|
||||
PullImageStart: '開始拉取映像 [{{ .name }}]'
|
||||
PullImageSuccess: '映像拉取成功'
|
||||
AppStoreSyncSuccess: '應用程式商店同步成功'
|
||||
SyncAppDetail: '同步應用程式設定'
|
||||
AppVersionNotMatch: '{{ .name }} 應用程式需要更高的 1Panel 版本,跳過同步'
|
||||
MoveSiteDir: "檢測到網站目錄變更 需要遷移 OpenResty 網站目錄到 {{ .name }}"
|
||||
MoveSiteDir: '偵測到網站目錄變更 需要遷移 OpenResty 網站目錄到 {{ .name }}'
|
||||
MoveSiteDirSuccess: '遷移網站目錄成功'
|
||||
DeleteRuntimePHP: '刪除PHP 執行環境'
|
||||
CustomAppStoreFileValid: '應用程式商店包需要 .tar.gz 格式'
|
||||
PullImageTimeout: '拉取鏡像逾時,請嘗試增加鏡像加速或更換其他鏡像加速'
|
||||
CustomAppStoreFileValid: '應用程式商店包需要.tar.gz 格式'
|
||||
PullImageTimeout: '拉取映像逾時,請嘗試增加映像加速或更換其他映像加速'
|
||||
ErrAppIsDown: '{{ .name }} 應用程式狀態異常,請檢查'
|
||||
ErrCustomApps: '存在已安裝的應用程式,請先解除安裝'
|
||||
ErrCustomRuntimes: '存在已安裝的運作環境,請先刪除'
|
||||
ErrAppVersionDeprecated: "{{ .name }} 應用不適配目前 1Panel 版本,跳過"
|
||||
ErrDockerFailed: "Docker 狀態異常,請檢查服務狀態"
|
||||
ErrDockerComposeCmdNotFound: "Docker Compose 指令不存在,請先在宿主機安裝此指令"
|
||||
UseExistImage: '拉取映像失敗,使用存量映像'
|
||||
|
||||
#ssh
|
||||
ExportIP: "登入IP"
|
||||
ExportArea: "歸屬地"
|
||||
ExportPort: "埠"
|
||||
ExportAuthMode: "登入方式"
|
||||
ExportUser: "使用者"
|
||||
ExportStatus: "登入狀態"
|
||||
ExportDate: "時間"
|
||||
|
||||
#file
|
||||
ErrAppVersionDeprecated: '{{ .name }} 應用不適配目前 1Panel 版本,跳過'
|
||||
ErrDockerFailed: 'Docker 狀態異常,請檢查服務狀態'
|
||||
ErrDockerComposeCmdNotFound: 'Docker Compose 指令不存在,請先在宿主機安裝此指令'
|
||||
UseExistImage: '映像已存在,使用現有映像'
|
||||
ErrDatabaseNotFound: '資料庫 {{ .name }} 不存在'
|
||||
ExportIP: '登入IP'
|
||||
ExportArea: '歸屬地'
|
||||
ExportPort: '埠'
|
||||
ExportAuthMode: '登入方式'
|
||||
ExportUser: '使用者'
|
||||
ExportStatus: '登入狀態'
|
||||
ExportDate: '時間'
|
||||
ErrFileCanNotRead: '此檔案不支援預覽'
|
||||
ErrFileToLarge: '檔案超過10M,無法開啟'
|
||||
ErrPathNotFound: '目錄不存在'
|
||||
ErrMovePathFailed: '目標路徑不能包含原路徑!'
|
||||
ErrMovePathFailed: '目標路徑不可包含原路徑!'
|
||||
ErrLinkPathNotFound: '目標路徑不存在!'
|
||||
ErrFileIsExist: '檔案或資料夾已存在!'
|
||||
ErrFileUpload: '{{ .name }} 上傳檔案失敗{{ .detail }}'
|
||||
ErrFileDownloadDir: '不支援下載資料夾'
|
||||
ErrCmdNotFound: '{{ .name}} 指令不存在,請先在宿主機安裝此指令'
|
||||
ErrCmdNotFound: '{{ .name }} 指令不存在,請先在宿主機安裝此指令'
|
||||
ErrSourcePathNotFound: '來源目錄不存在'
|
||||
ErrFavoriteExist: '已收藏此路徑'
|
||||
ErrInvalidChar: '禁止使用無效字元'
|
||||
ErrPathNotDelete: '所選目錄不可刪除'
|
||||
ErrLogFileToLarge: "日誌檔案超過 500M,無法打開"
|
||||
FileDropFailed: "清理文件 {{ .name }} 失敗: {{ .err }}"
|
||||
FileDropSuccess: "清理文件 {{ .name }} 成功,清理 {{ .count }} 個文件,釋放 {{ .size }} 磁碟空間"
|
||||
FileDropSum: "文件清理完成,共清理 {{ .count }} 個文件,共釋放 {{ .size }} 磁碟空間"
|
||||
ErrBadDecrypt: "壓縮檔解壓密碼錯誤,解壓失敗,請檢查後重試!!"
|
||||
|
||||
#website
|
||||
ErrLogFileToLarge: '日誌檔案超過 500M,無法開啟'
|
||||
FileDropFailed: '清理檔案 {{ .name }} 失敗: {{ .err }}'
|
||||
FileDropSuccess: '清理檔案 {{ .name }} 成功,清理 {{ .count }} 個檔案,釋放 {{ .size }} 磁碟空間'
|
||||
FileDropSum: '檔案清理完成,共清理 {{ .count }} 個檔案,共釋放 {{ .size }} 磁碟空間'
|
||||
ErrBadDecrypt: '壓縮檔解壓密碼錯誤,解壓失敗,請重試。'
|
||||
ErrAliasIsExist: '代號已存在'
|
||||
ErrBackupMatch: '該備份檔案與目前網站部分資料不符{{ .detail }}'
|
||||
ErrBackupExist: '該備份檔案對應部分來源資料不存在{{ .detail }}'
|
||||
ErrPHPResource: '本機執行環境不支援切換! '
|
||||
ErrPathPermission: 'index 目錄下偵測到非 1000:1000 權限資料夾,可能導致網站存取 Access denied 錯誤,請點擊上方儲存按鈕'
|
||||
ErrPHPResource: '本機執行環境不支援切換!'
|
||||
ErrPathPermission: 'index 目錄下偵測到非 1000:1000 權限資料夾,可能導致網站存取 Access denied 錯誤,請點選上方儲存按鈕'
|
||||
ErrDomainIsUsed: '網域名稱已被網站【{{ .name }}】使用'
|
||||
ErrDomainFormat: '{{ .name }} 網域格式不正確'
|
||||
ErrDefaultAlias: 'default 為保留代號,請使用其他代號'
|
||||
ErrParentWebsite: '需要先移除子網站{{ .name }}'
|
||||
ErrBuildDirNotFound: '建置目錄不存在'
|
||||
ErrImageNotExist: '執行環境{{ .name }} 映像不存在,請重新編輯執行環境'
|
||||
ErrProxyIsUsed: "負載均衡已被反向代理使用,無法刪除"
|
||||
ErrSSLValid: '證書文件異常,請檢查證書狀態!'
|
||||
ErrWebsiteDir: "請選擇網站目錄下的目錄"
|
||||
ErrComposerFileNotFound: "composer.json 文件不存在"
|
||||
ErrRuntimeNoPort: "執行環境未設定埠,請先編輯執行環境"
|
||||
ErrProxyIsUsed: '負載均衡已被反向代理使用,無法刪除'
|
||||
ErrSSLValid: '憑證檔案異常,請檢查憑證狀態!'
|
||||
ErrWebsiteDir: '請選擇網站目錄下的目錄'
|
||||
ErrComposerFileNotFound: 'composer.json 檔案不存在'
|
||||
ErrRuntimeNoPort: '執行環境未設定埠,請先編輯執行環境'
|
||||
Status: '狀態'
|
||||
start: '開啟'
|
||||
stop: '關閉'
|
||||
restart: '重啟'
|
||||
restart: '重新啟動'
|
||||
kill: '強制停止'
|
||||
pause: '暫停'
|
||||
unpause: '恢復'
|
||||
remove: '刪除'
|
||||
delete: '刪除'
|
||||
ErrDefaultWebsite: '已經設置默認網站,請取消後再設置!'
|
||||
ErrDefaultWebsite: '已經設定預設網站,請取消後再設定!'
|
||||
SSL: '憑證'
|
||||
Set: '設定'
|
||||
|
||||
#ssl
|
||||
ErrSSLCannotDelete: '{{ .name }} 憑證正在被網站使用,無法刪除'
|
||||
ErrAccountCannotDelete: '帳號關聯證書,無法刪除'
|
||||
ErrAccountCannotDelete: '帳號關聯憑證,無法刪除'
|
||||
ErrSSLApply: '憑證續簽成功,openresty reload 失敗,請檢查設定!'
|
||||
ErrEmailIsExist: '信箱已存在'
|
||||
ErrSSLKeyNotFound: '私鑰檔案不存在'
|
||||
ErrSSLCertificateNotFound: '憑證檔案不存在'
|
||||
ErrSSLKeyFormat: '私鑰檔案校驗失敗'
|
||||
ErrSSLKeyFormat: '私鑰檔案驗證失敗'
|
||||
ErrSSLCertificateFormat: '憑證檔案格式錯誤,請使用 pem 格式'
|
||||
ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid 或 EabHmacKey 不能為空'
|
||||
ErrOpenrestyNotFound: 'Http 模式需要先安裝Openresty'
|
||||
ApplySSLStart: '開始申請證書,網域名稱[{{ .domain }}] 申請方式[{{ .type }}] '
|
||||
ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid 或 EabHmacKey 不可為空'
|
||||
ErrOpenrestyNotFound: 'Http 模式需要先安裝OpenResty'
|
||||
ApplySSLStart: '開始申請憑證,網域名稱[{{ .domain }}] 申請方式[{{ .type }}]'
|
||||
dnsAccount: 'DNS 自動'
|
||||
dnsManual: 'DNS 手排'
|
||||
http: 'HTTP'
|
||||
ApplySSLFailed: '申請[{{ .domain }}] 憑證失敗, {{ .detail }} '
|
||||
ApplySSLSuccess: '申請[{{ .domain }}] 憑證成功! ! '
|
||||
ApplySSLFailed: '申請[{{ .domain }}] 憑證失敗, {{ .detail }}'
|
||||
ApplySSLSuccess: '申請[{{ .domain }}] 憑證成功!'
|
||||
DNSAccountName: 'DNS 帳號[{{ .name }}] 廠商[{{ .type }}]'
|
||||
PushDirLog: '憑證推送到目錄[{{ .path }}] {{ .status }}'
|
||||
ErrDeleteCAWithSSL: '目前機構下存在已簽發證書,無法刪除'
|
||||
ErrDeleteWithPanelSSL: '面板SSL 配置使用此證書,無法刪除'
|
||||
ErrDefaultCA: '預設機構不能刪除'
|
||||
ErrDeleteCAWithSSL: '目前機構下存在已簽發憑證,無法刪除'
|
||||
ErrDeleteWithPanelSSL: '面板SSL 設定使用此憑證,無法刪除'
|
||||
ErrDefaultCA: '預設機構不可刪除'
|
||||
ApplyWebSiteSSLLog: '開始更新{{ .name }} 網站憑證'
|
||||
ErrUpdateWebsiteSSL: '{{ .name }} 網站更新憑證失敗: {{ .err }}'
|
||||
ApplyWebSiteSSLSuccess: '更新網站憑證成功'
|
||||
@@ -200,105 +185,87 @@ ExecShellSuccess: '腳本執行成功'
|
||||
StartUpdateSystemSSL: '開始更新系統憑證'
|
||||
UpdateSystemSSLSuccess: '更新系統憑證成功'
|
||||
ErrWildcardDomain: 'HTTP 模式無法申請泛網域憑證'
|
||||
ErrApplySSLCanNotDelete: "正在申請的證書 {{.name}} 無法刪除,請稍後再試"
|
||||
StartPushSSLToNode: "開始推送證書到節點"
|
||||
PushSSLToNodeFailed: "推送證書到節點失敗: {{ .err }}"
|
||||
PushSSLToNodeSuccess: "推送證書到節點成功"
|
||||
|
||||
#mysql
|
||||
ErrApplySSLCanNotDelete: '正在申請的憑證 {{ .name }} 無法刪除,請稍後重試'
|
||||
StartPushSSLToNode: '開始推送憑證到節點'
|
||||
PushSSLToNodeFailed: '推送憑證到節點失敗: {{ .err }}'
|
||||
PushSSLToNodeSuccess: '推送憑證到節點成功'
|
||||
ErrUserIsExist: '目前使用者已存在,請重新輸入'
|
||||
ErrDatabaseIsExist: '目前資料庫已存在,請重新輸入'
|
||||
ErrExecTimeOut: 'SQL 執行逾時,請檢查資料庫'
|
||||
ErrRemoteExist: '遠端資料庫已存在該名稱,請修改後重試'
|
||||
ErrLocalExist: '本機資料庫已存在該名稱,請修改後重試'
|
||||
RemoteBackup: "備份遠端資料庫需要先使用映像 {{ .name }} 啟動本機容器資料庫服務,請稍候..."
|
||||
RemoteRecover: "恢復遠端資料庫需要先使用映像 {{ .name }} 啟動本機容器資料庫服務,請稍候..."
|
||||
Arg: "參數"
|
||||
|
||||
#redis
|
||||
RemoteBackup: '備份遠端資料庫需要先使用映像 {{ .name }} 啟動本機容器資料庫服務,請稍候...'
|
||||
RemoteRecover: '復原遠端資料庫需要先使用映像 {{ .name }} 啟動本機容器資料庫服務,請稍候...'
|
||||
Arg: '參數'
|
||||
ErrTypeOfRedis: '復原檔案類型與目前持久化方式不符,請修改後重試'
|
||||
|
||||
#container
|
||||
ErrInUsed: "{{ .detail }} 正被使用,無法刪除!"
|
||||
ErrObjectInUsed: "該對象正被使用,無法刪除!"
|
||||
ErrObjectBeDependent: "該映像正被其他映像所依賴,無法刪除!"
|
||||
ErrPortRules: '連接埠數目不匹配,請重新輸入!'
|
||||
ErrPgImagePull: '鏡像拉取逾時,請配置鏡像加速或手動拉取{{ .name }} 鏡像後重試'
|
||||
PruneHelper: "本次清理 {{ .name }} 釋放磁碟空間 {{ .size }}"
|
||||
ImageRemoveHelper: "刪除鏡像 {{ .name }} ,釋放磁碟空間 {{ .size }}"
|
||||
BuildCache: "構建快取"
|
||||
Volume: "磁碟區"
|
||||
Network: "網路"
|
||||
PruneStart: "清理中,請稍候..."
|
||||
|
||||
#runtime
|
||||
ErrInUsed: '{{ .detail }} 正被使用,無法刪除!'
|
||||
ErrObjectInUsed: '該對象正被使用,無法刪除!'
|
||||
ErrObjectBeDependent: '該映像正被其他映像所依賴,無法刪除!'
|
||||
ErrPortRules: '連接埠數目不符,請重新輸入!'
|
||||
ErrPgImagePull: '映像拉取逾時,請設定映像加速或手動拉取{{ .name }} 映像後重試'
|
||||
PruneHelper: '本次清理 {{ .name }} 釋放磁碟空間 {{ .size }}'
|
||||
ImageRemoveHelper: '刪除映像 {{ .name }} ,釋放磁碟空間 {{ .size }}'
|
||||
BuildCache: '構建快取'
|
||||
Volume: '磁碟區'
|
||||
Network: '網路'
|
||||
PruneStart: '清理中,請稍候...'
|
||||
ErrFileNotExist: '{{ .detail }} 檔案不存在!請檢查來源檔案完整性!'
|
||||
ErrImageBuildErr: '鏡像build 失敗'
|
||||
ErrImageExist: "鏡像已存在!請修改鏡像名稱。"
|
||||
ErrImageBuildErr: '映像build 失敗'
|
||||
ErrImageExist: '映像已存在!請修改映像名稱。'
|
||||
ErrDelWithWebsite: '執行環境已經關聯網站,無法刪除'
|
||||
ErrRuntimeStart: '啟動失敗'
|
||||
ErrPackageJsonNotFound: 'package.json 檔案不存在'
|
||||
ErrScriptsNotFound: '沒有在 package.json 中找到 scripts 設定項'
|
||||
ErrContainerNameNotFound: '無法取得容器名稱,請檢查 .env 檔案'
|
||||
ErrContainerNameNotFound: '無法取得容器名稱,請檢查.env 檔案'
|
||||
ErrNodeModulesNotFound: 'node_modules 資料夾不存在!請編輯執行環境或等待執行環境啟動成功'
|
||||
ErrContainerNameIsNull: '容器名稱不存在'
|
||||
ErrPHPPortIsDefault: "9000 埠為預設埠,請修改後重試"
|
||||
ErrPHPRuntimePortFailed: "{{ .name }} 埠已被目前執行環境使用,請修改後重試"
|
||||
|
||||
#tool
|
||||
ErrPHPPortIsDefault: '9000 埠為預設埠,請修改後重試'
|
||||
ErrPHPRuntimePortFailed: '{{ .name }} 埠已被目前執行環境使用,請修改後重試'
|
||||
ErrConfigNotFound: '設定檔不存在'
|
||||
ErrConfigParse: '設定檔格式有誤'
|
||||
ErrConfigIsNull: '設定檔不允許為空'
|
||||
ErrConfigDirNotFound: '執行目錄不存在'
|
||||
ErrConfigAlreadyExist: '已存在同名設定檔'
|
||||
ErrUserFindErr: '使用者{{ .name }} 尋找失敗{{ .err }}'
|
||||
|
||||
#cronjob
|
||||
CutWebsiteLogSuccess: '{{ .name }} 網站日誌切割成功,備份路徑{{ .path }}'
|
||||
HandleShell: '執行腳本{{ .name }}'
|
||||
HandleCurl: "存取 URL {{ .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: "WAF IP 群組未找到,請先到【進階功能-WAF-黑白名單-IP群組】添加遠端下載方式的IP群組"
|
||||
|
||||
#toolbox
|
||||
UploadFile: '上傳備份檔案 {{ .file }} 到 {{ .backup }}'
|
||||
Upload: '上傳'
|
||||
IgnoreBackupErr: '備份失敗,錯誤:{{ .detail }},忽略本次錯誤...'
|
||||
IgnoreUploadErr: '上傳失敗,錯誤:{{ .detail }},忽略本次錯誤...'
|
||||
LoadBackupFailed: '取得備份帳號連線失敗,錯誤:{{ .detail }}'
|
||||
InExecuting: '目前任務正在執行中,請勿重複執行!'
|
||||
NoSuchResource: '資料庫中未能查詢到備份內容,跳過...'
|
||||
CleanLog: '清理日誌'
|
||||
CleanLogByName: '清理 {{ .name }} 日誌'
|
||||
WafIpGroupNotFound: 'WAF IP 群組未找到,請先到【進階功能-WAF-黑白名單-IP群組】添加遠端下載方式的IP群組'
|
||||
ErrNotExistUser: '目前使用者不存在,請修改後重試!'
|
||||
ErrBanAction: '設定失敗,目前{{ .name }} 服務不可用,請檢查後再試一次!'
|
||||
ErrClamdscanNotFound: '未偵測到clamdscan 指令,請參考文件安裝!'
|
||||
TaskSwapSet: "設定 Swap"
|
||||
SetSwap: "設定 Swap {{ .path }} - {{ .size }}"
|
||||
CreateSwap: "建立 Swap 檔案"
|
||||
FormatSwap: "格式化 Swap 檔案"
|
||||
EnableSwap: "啟用 Swap"
|
||||
|
||||
#tamper
|
||||
CleanTamperSetting: "清理歷史防護設定"
|
||||
SetTamperWithRules: "根據規則啟動目錄防護"
|
||||
ProtectDir: "防護目錄 {{ .name }}"
|
||||
IgnoreFile: "保護文件 {{ .name }}"
|
||||
TamperSetSuccessful: "防護設定完成,開始監聽以下目錄:"
|
||||
|
||||
#waf
|
||||
ErrScope: '不支援修改此配置'
|
||||
ErrBanAction: '設定失敗,目前{{ .name }} 服務不可用,請重試'
|
||||
ErrClamdscanNotFound: '未偵測到clamdscan 指令,請參考檔案安裝!'
|
||||
TaskSwapSet: '設定 Swap'
|
||||
SetSwap: '設定 Swap {{ .path }} - {{ .size }}'
|
||||
CreateSwap: '建立 Swap 檔案'
|
||||
FormatSwap: '格式化 Swap 檔案'
|
||||
EnableSwap: '啟用 Swap'
|
||||
CleanTamperSetting: '清理歷史防護設定'
|
||||
SetTamperWithRules: '根據規則啟動目錄防護'
|
||||
ProtectDir: '防護目錄 {{ .name }}'
|
||||
IgnoreFile: '保護檔案 {{ .name }}'
|
||||
TamperSetSuccessful: '防護設定完成,開始監聽以下目錄:'
|
||||
ErrScope: '不支援修改此設定'
|
||||
ErrStateChange: '狀態修改失敗'
|
||||
ErrRuleExist: '規則已存在'
|
||||
ErrRuleNotExist: '規則不存在'
|
||||
ErrParseIP: 'IP 格式錯誤'
|
||||
ErrDefaultIP: 'default 為保留名稱,請更換其他名稱'
|
||||
ErrGroupInUse: 'IP 群組被黑/白名單使用,無法刪除'
|
||||
ErrIPGroupAclUse: "IP 群組被網站 {{ .name }} 自訂規則使用,無法刪除"
|
||||
ErrIPGroupAclUse: 'IP 群組被網站 {{ .name }} 自訂規則使用,無法刪除'
|
||||
ErrGroupExist: 'IP 群組名稱已存在'
|
||||
ErrIPRange: 'IP 範圍錯誤'
|
||||
ErrIPExist: 'IP 已存在'
|
||||
@@ -309,10 +276,10 @@ xss: 'XSS'
|
||||
phpExec: 'PHP 腳本執行'
|
||||
oneWordTrojan: '一句話木馬'
|
||||
appFilter: '套用危險目錄過濾'
|
||||
webshell: 'Webshell'
|
||||
webShell: 'WebShell'
|
||||
args: '參數規則'
|
||||
protocolFilter: '協定過濾'
|
||||
javaFileter: 'Java 危險檔案過濾'
|
||||
javaFilter: 'Java 危險檔案過濾'
|
||||
scannerFilter: '掃描器過濾'
|
||||
escapeFilter: '轉義過濾'
|
||||
customRule: '自訂規則'
|
||||
@@ -341,11 +308,10 @@ sqlInject: 'SQL 注入'
|
||||
ErrDBNotExist: '資料庫不存在'
|
||||
allow: '允許'
|
||||
deny: '禁止'
|
||||
OpenrestyNotFound: 'Openresty 未安裝'
|
||||
remoteIpIsNull: "IP 列表為空"
|
||||
OpenrestyVersionErr: "Openresty 版本過低,請升級 Openresty 至 1.27.1.2-2-2-focal"
|
||||
|
||||
#task
|
||||
OpenrestyNotFound: 'OpenResty 未安裝'
|
||||
remoteIpIsNull: 'IP 列表為空'
|
||||
OpenrestyVersionErr: 'OpenResty 版本過低,請升級 OpenResty 至 1.27.1.2-2-2-focal'
|
||||
ErrFileTooLarge: '檔案超過 1MB,無法上傳'
|
||||
TaskStart: '{{ .name }} 任務開始[START]'
|
||||
TaskEnd: '{{ .name }} 任務結束[COMPLETED]'
|
||||
TaskFailed: '{{ .name }} 任務失敗'
|
||||
@@ -360,8 +326,8 @@ TaskCreate: '建立'
|
||||
TaskDelete: '刪除'
|
||||
TaskUpgrade: '升級'
|
||||
TaskUpdate: '更新'
|
||||
TaskRestart: '重啟'
|
||||
TaskProtect: "防護"
|
||||
TaskRestart: '重新啟動'
|
||||
TaskProtect: '防護'
|
||||
TaskBackup: '備份'
|
||||
TaskRecover: '復原'
|
||||
TaskRollback: '回滾'
|
||||
@@ -369,16 +335,16 @@ TaskPull: '拉取'
|
||||
TaskCommit: '製作'
|
||||
TaskBuild: '建置'
|
||||
TaskPush: '推送'
|
||||
TaskClean: "清理"
|
||||
TaskClean: '清理'
|
||||
TaskHandle: '執行'
|
||||
TaskImport: "導入"
|
||||
TaskExport: "導出"
|
||||
TaskImport: '匯入'
|
||||
TaskExport: '匯出'
|
||||
Website: '網站'
|
||||
App: '應用程式'
|
||||
Runtime: '運作環境'
|
||||
Database: '資料庫'
|
||||
ConfigFTP: '建立FTP 使用者{{ .name }}'
|
||||
ConfigOpenresty: '建立Openresty 設定檔'
|
||||
ConfigOpenresty: '建立OpenResty 設定檔'
|
||||
InstallAppSuccess: '應用程式{{ .name }} 安裝成功'
|
||||
ConfigRuntime: '設定執行環境'
|
||||
ConfigApp: '設定應用程式'
|
||||
@@ -387,11 +353,11 @@ FailedStatus: '{{ .name }} 失敗{{ .err }}'
|
||||
HandleLink: '處理應用程式關聯'
|
||||
HandleDatabaseApp: '處理應用程式參數'
|
||||
ExecShell: '執行{{ .name }} 腳本'
|
||||
PullImage: '拉取鏡像'
|
||||
PullImage: '拉取映像'
|
||||
Start: '開始'
|
||||
Run: '啟動'
|
||||
Stop: '停止'
|
||||
Image: '鏡像'
|
||||
Image: '映像'
|
||||
Compose: '編排'
|
||||
Container: '容器'
|
||||
AppLink: '關聯應用程式'
|
||||
@@ -404,28 +370,22 @@ RuntimeExtension: '執行環境擴充'
|
||||
TaskIsExecuting: '任務正在運作'
|
||||
CustomAppstore: '自訂應用程式倉庫'
|
||||
TaskExec: '執行'
|
||||
TaskBatch: "批次操作"
|
||||
TaskBatch: '批次操作'
|
||||
FileConvert: '檔案格式轉換'
|
||||
|
||||
# task - clam
|
||||
Clamscan: "掃描 {{ .name }}"
|
||||
TaskScan: "掃描"
|
||||
|
||||
# task - ai
|
||||
OllamaModelPull: '拉取 Ollama 模型{{ .name }} '
|
||||
Clamscan: '掃描 {{ .name }}'
|
||||
TaskScan: '掃描'
|
||||
OllamaModelPull: '拉取 Ollama 模型{{ .name }}'
|
||||
OllamaModelSize: '取得 Ollama 模型{{ .name }} 大小'
|
||||
|
||||
# task - snapshot
|
||||
Snapshot: '快照'
|
||||
SnapDBInfo: '寫入1Panel 資料庫資訊'
|
||||
SnapCopy: '複製檔案&目錄{{ .name }} '
|
||||
SnapCopy: '複製檔案&目錄{{ .name }}'
|
||||
SnapNewDB: '初始化資料庫{{ .name }} 連線'
|
||||
SnapDeleteOperationLog: '刪除操作日誌'
|
||||
SnapDeleteLoginLog: '刪除存取日誌'
|
||||
SnapDeleteMonitor: '刪除監控資料'
|
||||
SnapRemoveSystemIP: '移除系統IP'
|
||||
SnapBaseInfo: '寫入1Panel 基本資料'
|
||||
SnapInstallAppImageEmpty: '目前未勾選應用鏡像,跳過...'
|
||||
SnapInstallAppImageEmpty: '目前未勾選應用映像,跳過...'
|
||||
SnapInstallApp: '備份 1Panel 已安裝應用'
|
||||
SnapDockerSave: '壓縮已安裝應用'
|
||||
SnapLocalBackup: '備份1Panel 本機備份目錄'
|
||||
@@ -441,7 +401,6 @@ SnapCompressSize: '快照檔案大小{{ .name }}'
|
||||
SnapUpload: '上傳快照檔案'
|
||||
SnapUploadTo: '上傳快照檔案到{{ .name }}'
|
||||
SnapUploadRes: '上傳快照檔案到{{ .name }}'
|
||||
|
||||
SnapshotRecover: '快照復原'
|
||||
RecoverDownload: '下載快照檔案'
|
||||
Download: '下載'
|
||||
@@ -449,94 +408,69 @@ RecoverDownloadAccount: '取得快照下載備份帳號{{ .name }}'
|
||||
RecoverDecompress: '解壓縮快照壓縮檔'
|
||||
Decompress: '解壓縮'
|
||||
BackupBeforeRecover: '快照前備份系統相關資料'
|
||||
Readjson: '讀取快照內Json 檔案'
|
||||
ReadjsonPath: '取得快照內Json 檔案路徑'
|
||||
ReadjsonContent: '讀取Json 檔案'
|
||||
ReadjsonMarshal: 'Json 轉義處理'
|
||||
ReadJson: '讀取快照內JSON 檔案'
|
||||
ReadJsonPath: '取得快照內JSON 檔案路徑'
|
||||
ReadJsonContent: '讀取JSON 檔案'
|
||||
ReadJsonMarshal: 'JSON 轉義處理'
|
||||
RecoverApp: '復原已安裝應用程式'
|
||||
RecoverWebsite: '復原網站目錄'
|
||||
RecoverAppImage: '復原快照鏡像備份'
|
||||
RecoverAppImage: '復原快照映像備份'
|
||||
RecoverCompose: '復原其他編排內容'
|
||||
RecoverComposeList: '取得所有待復原編排'
|
||||
RecoverComposeItem: '復原編排{{ .name }}'
|
||||
RecoverAppEmpty: '快照檔案中未發現應用程式鏡像備份'
|
||||
RecoverAppEmpty: '快照檔案中未發現應用程式映像備份'
|
||||
RecoverBaseData: '復原基礎資料及檔案'
|
||||
RecoverDaemonJsonEmpty: '快照檔案及目前機器都不存在容器配置daemon.json 檔案'
|
||||
RecoverDaemonJson: '復原容器配置daemon.json 檔案'
|
||||
RecoverDaemonJsonEmpty: '快照檔案及目前機器都不存在容器設定daemon.json 檔'
|
||||
RecoverDaemonJson: '復原容器設定daemon.json 檔'
|
||||
RecoverDBData: '復原資料庫資料'
|
||||
RecoverBackups: '還原本機備份目錄'
|
||||
RecoverPanelData: '復原資料目錄'
|
||||
|
||||
# task - container
|
||||
ContainerNewCliet: '初始化Docker Client'
|
||||
ContainerImagePull: '拉取容器鏡像{{ .name }}'
|
||||
ContainerImagePull: '拉取容器映像{{ .name }}'
|
||||
ContainerRemoveOld: '刪除原容器{{ .name }}'
|
||||
ContainerImageCheck: '檢查鏡像是否正常拉取'
|
||||
ContainerImageCheck: '檢查映像是否正常拉取'
|
||||
ContainerLoadInfo: '取得容器基本資訊'
|
||||
ContainerRecreate: '容器更新失敗,現在開始復原原容器'
|
||||
ContainerCreate: '建立新容器{{ .name }}'
|
||||
ContainerCreateFailed: '容器建立失敗,刪除失敗容器'
|
||||
ContainerStartCheck: '檢查容器是否已啟動'
|
||||
|
||||
# task - image
|
||||
ImageBuild: '鏡像建置'
|
||||
ImageBuildStdoutCheck: '解析鏡像輸出內容'
|
||||
ImageBuildRes: '鏡像建置輸出:{{ .name }}'
|
||||
ImagePull: '拉取鏡像'
|
||||
ImageBuild: '映像建置'
|
||||
ImagePull: '拉取映像'
|
||||
ImageRepoAuthFromDB: '從資料庫取得倉庫認證資訊'
|
||||
ImaegPullRes: '鏡像拉取輸出:{{ .name }}'
|
||||
ImagePush: '推播鏡像'
|
||||
ImageRenameTag: '修改鏡像Tag'
|
||||
ImageNewTag: '新鏡像Tag {{ .name }}'
|
||||
ImaegPushRes: '鏡像推播輸出:{{ .name }}'
|
||||
ImagePush: '推播映像'
|
||||
ImageRenameTag: '修改映像Tag'
|
||||
ImageNewTag: '新映像Tag {{ .name }}'
|
||||
ComposeCreate: '建立編排'
|
||||
ComposeCreateRes: '編排建立輸出:{{ .name }}'
|
||||
|
||||
# task - website
|
||||
BackupNginxConfig: '備份網站OpenResty 設定檔'
|
||||
CompressFileSuccess: '壓縮目錄成功,壓縮為{{ .name }}'
|
||||
CompressDir: '壓縮目錄'
|
||||
DeCompressFile: '解壓縮檔案{{ .name }}'
|
||||
ErrCheckValid: '校驗備份檔失敗,{{ .name }}'
|
||||
ErrCheckValid: '驗證備份檔失敗,{{ .name }}'
|
||||
Rollback: '回滾'
|
||||
websiteDir: '網站目錄'
|
||||
RecoverFailedStartRollBack: '復原失敗,開始回溯'
|
||||
AppBackupFileIncomplete: '備份檔案不完整缺少 app.json 或 app.tar.gz 檔案'
|
||||
AppAttributesNotMatch: '應用程式類型或名稱不一致'
|
||||
|
||||
#alert
|
||||
ErrAlert: '警告訊息格式錯誤,請檢查後重試!!'
|
||||
ErrAlertPush: '警告訊息推送錯誤,請檢查後重試!!'
|
||||
ErrAlertSave: '警告訊息儲存錯誤,請檢查後重試!!'
|
||||
ErrAlertSync: '警告訊息同步錯誤,請檢查後重試!!'
|
||||
ErrAlertRemote: '警告訊息遠端錯誤,請檢查後重試!!'
|
||||
|
||||
#task - runtime
|
||||
ErrInstallExtension: "已有安裝任務正在進行,請等待任務結束"
|
||||
|
||||
# alert mail template
|
||||
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 }} 面板,過去 {{ .time }} 分鐘內 {{ .name }} 平均使用率為 {{ .used }},詳情請登入面板查看。"
|
||||
PanelVersionAlert: "您的 {{ .node }}{{ .ip }} 面板,已有最新版本可供升級,詳情請登入面板查看。"
|
||||
PanelPwdExpirationAlert: "您的 {{ .node }}{{ .ip }} 面板,面板密碼將於 {{ .day }} 天後到期,詳情請登入面板查看。"
|
||||
CommonAlert: "您的 {{ .node }}{{ .ip }} 面板,{{ .msg }},詳情請登入面板查看。"
|
||||
NodeExceptionAlert: "您的 {{ .node }}{{ .ip }} 面板,{{ .num }} 個節點出現異常,詳情請登入面板查看。"
|
||||
LicenseExceptionAlert: "您的 {{ .node }}{{ .ip }} 面板,{{ .num }} 個授權出現異常,詳情請登入面板查看。"
|
||||
SSHAndPanelLoginAlert: "您的 {{ .node }}{{ .ip }} 面板,來自 {{ .loginIp }} 的 {{ .name }} 登入出現異常,詳情請登入面板查看。"
|
||||
|
||||
#disk
|
||||
DeviceNotFound: "裝置 {{ .name }} 未找到"
|
||||
DeviceIsMounted: "裝置 {{ .name }} 已掛載,請先移除"
|
||||
PartitionDiskErr: "分區失敗,{{ .err }}"
|
||||
FormatDiskErr: "格式化磁碟失敗,{{ .err }}"
|
||||
MountDiskErr: "掛載磁碟失敗,{{ .err }}"
|
||||
UnMountDiskErr: "移除磁碟失敗,{{ .err }}"
|
||||
XfsNotFound: "未檢測到 xfs 文件系統,請先安裝 xfsprogs"
|
||||
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 }} 面板,過去 {{ .time }} 分鐘內 {{ .name }} 平均使用率為 {{ .used }},詳情請登入面板檢視。'
|
||||
PanelVersionAlert: '您的 {{ .node }}{{ .ip }} 面板,已有最新版本可供升級,詳情請登入面板檢視。'
|
||||
PanelPwdExpirationAlert: '您的 {{ .node }}{{ .ip }} 面板,面板密碼將於 {{ .day }} 天後到期,詳情請登入面板檢視。'
|
||||
CommonAlert: '您的 {{ .node }}{{ .ip }} 面板,{{ .msg }},詳情請登入面板檢視。'
|
||||
NodeExceptionAlert: '您的 {{ .node }}{{ .ip }} 面板,{{ .num }} 個節點出現異常,詳情請登入面板檢視。'
|
||||
LicenseExceptionAlert: '您的 {{ .node }}{{ .ip }} 面板,{{ .num }} 個授權出現異常,詳情請登入面板檢視。'
|
||||
SSHAndPanelLoginAlert: '您的 {{ .node }}{{ .ip }} 面板,來自 {{ .loginIp }} 的 {{ .name }} 登入出現異常,詳情請登入面板檢視。'
|
||||
DeviceNotFound: '裝置 {{ .name }} 未找到'
|
||||
DeviceIsMounted: '裝置 {{ .name }} 已掛載,請先移除'
|
||||
PartitionDiskErr: '分區失敗,{{ .err }}'
|
||||
FormatDiskErr: '格式化磁碟失敗,{{ .err }}'
|
||||
MountDiskErr: '掛載磁碟失敗,{{ .err }}'
|
||||
XfsNotFound: '未偵測到 xfs 檔案系統,請先安裝 xfsprogs'
|
||||
|
||||
+100
-110
@@ -1,30 +1,30 @@
|
||||
ErrInvalidParams: "请求参数错误: {{ .detail }}"
|
||||
ErrTokenParse: "Token 生成错误: {{ .detail }}"
|
||||
ErrInvalidParams: "参数错误: {{ .detail }}"
|
||||
ErrTokenParse: "Token 错误: {{ .detail }}"
|
||||
ErrInitialPassword: "原密码错误"
|
||||
ErrInternalServer: "服务内部错误: {{ .detail }}"
|
||||
ErrInternalServer: "服务错误: {{ .detail }}"
|
||||
ErrRecordExist: "记录已存在"
|
||||
ErrRecordNotFound: "记录未能找到"
|
||||
ErrRecordNotFound: "记录不存在"
|
||||
ErrStructTransform: "类型转换失败: {{ .err }}"
|
||||
ErrNotLogin: "用户未登录: {{ .detail }}"
|
||||
ErrPasswordExpired: "当前密码已过期: {{ .detail }}"
|
||||
ErrNotSupportType: "系统暂不支持当前类型: {{ .name }}"
|
||||
ErrProxy: "请求错误,请检查该节点状态: {{ .detail }}"
|
||||
ErrApiConfigStatusInvalid: "API 接口禁止访问: {{ .detail }}"
|
||||
ErrNotSupportType: "不支持当前类型: {{ .name }}"
|
||||
ErrProxy: "请求失败,请检查节点状态: {{ .detail }}"
|
||||
ErrApiConfigStatusInvalid: "API 禁止访问: {{ .detail }}"
|
||||
ErrApiConfigKeyInvalid: "API 接口密钥错误: {{ .detail }}"
|
||||
ErrApiConfigIPInvalid: "调用 API 接口 IP 不在白名单: {{ .detail }}"
|
||||
ErrApiConfigDisable: "此接口禁止使用 API 接口调用: {{ .detail }}"
|
||||
ErrApiConfigKeyTimeInvalid: "API 接口时间戳错误: {{ .detail }}"
|
||||
ErrShutDown: "命令被手动结束!"
|
||||
ErrApiConfigDisable: "此接口禁止 API 调用: {{ .detail }}"
|
||||
ErrApiConfigKeyTimeInvalid: "API 时间戳错误: {{ .detail }}"
|
||||
ErrShutDown: "命令已手动终止"
|
||||
|
||||
ErrMinQuickJump: "请至少设置一个快速跳转入口!"
|
||||
ErrMaxQuickJump: "最多可设置四个快速跳转入口!"
|
||||
ErrMinQuickJump: "至少设置 1 个快速跳转入口"
|
||||
ErrMaxQuickJump: "最多设置 4 个快速跳转入口"
|
||||
|
||||
#common
|
||||
ErrUsernameIsExist: "用户名已存在"
|
||||
ErrNameIsExist: "名称已存在"
|
||||
ErrDemoEnvironment: "演示服务器,禁止此操作!"
|
||||
ErrCmdTimeout: "命令执行超时!"
|
||||
ErrCmdIllegal: "执行命令中存在不合法字符,请修改后重试!"
|
||||
ErrDemoEnvironment: "演示环境,禁止操作"
|
||||
ErrCmdTimeout: "命令超时"
|
||||
ErrCmdIllegal: "命令含非法字符,请修改后重试"
|
||||
ErrPortExist: '{{ .port }} 端口已被 {{ .type }} [{{ .name }}] 占用'
|
||||
TYPE_APP: "应用"
|
||||
TYPE_RUNTIME: "运行环境"
|
||||
@@ -33,23 +33,24 @@ ErrTypePort: '端口 {{ .name }} 格式错误'
|
||||
ErrTypePortRange: '端口范围需要在 1-65535 之间'
|
||||
Success: "成功"
|
||||
Failed: "失败"
|
||||
SystemRestart: "系统重启导致任务中断"
|
||||
ErrGroupIsDefault: "默认分组,无法删除"
|
||||
SystemRestart: "系统重启,任务中断"
|
||||
ErrGroupIsDefault: "默认分组不可删除"
|
||||
ErrGroupIsInWebsiteUse: "分组正在被其他网站使用,无法删除"
|
||||
Decrypt: "解密"
|
||||
|
||||
#agent
|
||||
ErrAgentAccountBound: "该账号已经绑定到智能体,无法删除,请检查后重试!!"
|
||||
ErrAgentAccountUnavailable: "账号连接信息不可用,错误:{{ .err }},请检查后重试!"
|
||||
ErrAgentProviderNotSupported: "暂不支持该智能体提供商,请检查后重试!"
|
||||
ErrAgentAccountBound: "该账号已绑定智能体,无法删除"
|
||||
ErrAgentAccountUnavailable: "账号连接信息不可用: {{ .err }}"
|
||||
ErrAgentProviderNotSupported: "不支持该智能体提供商"
|
||||
ErrAgentAccountRequired: "请选择智能体账号后重试"
|
||||
ErrAgentAccountNotVerified: "账号未验证通过,请检查后重试!"
|
||||
ErrAgentProviderMismatch: "账号提供商不匹配,请检查后重试!"
|
||||
ErrAgentBaseURLRequired: "Base URL 不能为空,请检查后重试!"
|
||||
ErrAgentApiKeyRequired: "API Key 不能为空,请检查后重试!"
|
||||
ErrAgentComposeRequired: "自定义编排内容不能为空,请检查后重试!"
|
||||
ErrAgentIDRequired: "智能体 ID 不能为空,请检查后重试!"
|
||||
ErrAgentAccountIDRequired: "账号 ID 不能为空,请检查后重试!"
|
||||
ErrAgentAccountNotVerified: "账号未通过验证"
|
||||
ErrAgentProviderMismatch: "账号提供商不匹配"
|
||||
ErrAgentBaseURLRequired: "Base URL 不能为空"
|
||||
ErrAgentApiKeyRequired: "API Key 不能为空"
|
||||
ErrAgentComposeRequired: "自定义编排内容不能为空"
|
||||
ErrAgentIDRequired: "智能体 ID 不能为空"
|
||||
ErrAgentAccountIDRequired: "账号 ID 不能为空"
|
||||
ErrAgentLimitReached: "社区版最多支持创建 {{ .max }} 个智能体,升级至专业版无数量限制"
|
||||
|
||||
#backup
|
||||
Localhost: '本机'
|
||||
@@ -60,15 +61,15 @@ ErrBackupLocalCreate: "暂不支持创建本地服务器备份账号"
|
||||
|
||||
#app
|
||||
ErrPortInUsed: "{{ .detail }} 端口已被占用!"
|
||||
ErrAppLimit: "应用超出安装数量限制"
|
||||
ErrAppLimit: "应用安装数量超限"
|
||||
ErrNotInstall: "应用未安装"
|
||||
ErrPortInOtherApp: "{{ .port }} 端口已被应用 {{ .apps }} 占用!"
|
||||
ErrDbUserNotValid: "存量数据库,用户名密码不匹配!"
|
||||
ErrUpdateBuWebsite: '应用更新成功,但是网站配置文件修改失败,请检查配置!'
|
||||
ErrDbUserNotValid: "存量数据库用户名或密码不匹配"
|
||||
ErrUpdateBuWebsite: '应用更新成功,但网站配置文件修改失败,请检查配置'
|
||||
Err1PanelNetworkFailed: '默认容器网络创建失败!{{ .detail }}'
|
||||
ErrFileParse: '应用 docker-compose 文件解析失败!'
|
||||
ErrInstallDirNotFound: '安装目录不存在,如需卸载,请选择强制卸载'
|
||||
AppStoreIsUpToDate: '应用商店已经是最新版本'
|
||||
ErrFileParse: '应用 docker-compose 解析失败'
|
||||
ErrInstallDirNotFound: '安装目录不存在,如需卸载请选强制卸载'
|
||||
AppStoreIsUpToDate: '应用商店已是最新版本'
|
||||
LocalAppVersionNull: '{{ .name }} 应用未同步到版本!无法添加到应用列表'
|
||||
LocalAppVersionErr: '{{ .name }} 同步版本 {{ .version }} 失败!{{ .err }}'
|
||||
ErrFileNotFound: '{{ .name }} 文件不存在'
|
||||
@@ -86,29 +87,29 @@ ErrContainerMsg: '{{ .name }} 容器异常,具体请在容器页面查看日
|
||||
ErrAppBackup: '{{ .name }} 应用备份失败 {{ .err }}'
|
||||
ErrVersionTooLow: '当前 1Panel 版本过低,无法更新应用商店,请升级版本之后操作'
|
||||
ErrAppNameExist: '应用名称已存在'
|
||||
AppStoreIsSyncing: '应用商店正在同步中,请稍后再试'
|
||||
AppStoreIsSyncing: '应用商店同步中,请稍后重试'
|
||||
ErrGetCompose: "docker-compose.yml 文件获取失败!{{ .detail }}"
|
||||
ErrAppWarn: "状态异常,请查看日志"
|
||||
ErrAppParamKey: "参数 {{ .name }} 字段异常"
|
||||
ErrAppUpgrade: "应用 {{ .name }} 升级失败 {{ .err }}"
|
||||
AppRecover: "应用 {{ .name }} 回滚 "
|
||||
AppRecover: "应用 {{ .name }} 回滚"
|
||||
PullImageStart: "开始拉取镜像 [{{ .name }}]"
|
||||
PullImageSuccess: "镜像拉取成功"
|
||||
AppStoreSyncSuccess: "应用商店同步成功"
|
||||
SyncAppDetail: "同步应用配置"
|
||||
AppVersionNotMatch: "{{ .name }} 应用需要更高的 1Panel 版本,跳过"
|
||||
MoveSiteDir: "检测到网站目录变更 需要迁移 OpenResty 网站目录到 {{ .name }}"
|
||||
MoveSiteDir: "检测到网站目录变更,需迁移 OpenResty 网站目录到 {{ .name }}"
|
||||
MoveSiteDirSuccess: "迁移网站目录成功"
|
||||
DeleteRuntimePHP: "删除 PHP 运行环境"
|
||||
CustomAppStoreFileValid: "应用商店包需要 .tar.gz 格式"
|
||||
PullImageTimeout: "拉取镜像超时,请尝试增加镜像加速或者更换其他镜像加速"
|
||||
PullImageTimeout: "拉取镜像超时,请调整镜像加速配置"
|
||||
ErrAppIsDown: "{{ .name }} 应用状态异常,请检查"
|
||||
ErrCustomApps: "存在已经安装的应用,请先卸载"
|
||||
ErrCustomRuntimes: "存在已经安装的运行环境,请先删除"
|
||||
ErrAppVersionDeprecated: " {{ .name }} 应用不适配当前 1Panel 版本,跳过"
|
||||
ErrCustomApps: "存在已安装应用,请先卸载"
|
||||
ErrCustomRuntimes: "存在已安装运行环境,请先删除"
|
||||
ErrAppVersionDeprecated: "{{ .name }} 应用不适配当前 1Panel 版本,跳过"
|
||||
ErrDockerFailed: "Docker 状态异常,请检查服务状态"
|
||||
ErrDockerComposeCmdNotFound: "Docker Compose 命令不存在,请先在宿主机安装此命令"
|
||||
UseExistImage: "拉取镜像失败,使用存量镜像"
|
||||
ErrDockerComposeCmdNotFound: "Docker Compose 命令不存在,请先在宿主机安装"
|
||||
UseExistImage: "镜像已存在,使用存量镜像"
|
||||
ErrDatabaseNotFound: "数据库 {{ .name }} 不存在"
|
||||
|
||||
#ssh
|
||||
@@ -122,30 +123,30 @@ ExportDate: "时间"
|
||||
|
||||
#file
|
||||
ErrFileCanNotRead: "此文件不支持预览"
|
||||
ErrFileToLarge: "文件超过10M,无法打开"
|
||||
ErrFileToLarge: "文件超过 10M,无法打开"
|
||||
ErrPathNotFound: "目录不存在"
|
||||
ErrMovePathFailed: "目标路径不能包含原路径!"
|
||||
ErrLinkPathNotFound: "目标路径不存在!"
|
||||
ErrLinkPathNotFound: "目标路径不存在!"
|
||||
ErrFileIsExist: "文件或文件夹已存在!"
|
||||
ErrFileUpload: "{{ .name }} 上传文件失败 {{ .detail }}"
|
||||
ErrFileDownloadDir: "不支持下载文件夹"
|
||||
ErrCmdNotFound: "{{ .name}} 命令不存在,请先在宿主机安装此命令"
|
||||
ErrFileDownloadDir: "不支持下载目录"
|
||||
ErrCmdNotFound: "{{ .name }} 命令不存在,请先在宿主机安装此命令"
|
||||
ErrSourcePathNotFound: "源目录不存在"
|
||||
ErrFavoriteExist: "已收藏此路径"
|
||||
ErrInvalidChar: "禁止使用非法字符"
|
||||
ErrPathNotDelete: "所选目录不可删除"
|
||||
ErrLogFileToLarge: "日志文件超过 500M,无法打开"
|
||||
FileDropFailed: "清理文件 {{ .name }} 失败 {{ .err }}"
|
||||
FileDropSuccess: "清理文件 {{ .name }} 成功,清理文件 {{ .count }},释放磁盘空间 {{ .size }}"
|
||||
FileDropSum: "文件清理成功,清理文件共计 {{ .count }},释放磁盘空间共计 {{ .size }}"
|
||||
ErrBadDecrypt: "压缩包解压密码错误,解压失败,请检查后重试!!"
|
||||
FileDropSuccess: "清理 {{ .name }} 成功,文件 {{ .count }},释放 {{ .size }}"
|
||||
FileDropSum: "文件清理完成,共 {{ .count }},释放 {{ .size }}"
|
||||
ErrBadDecrypt: "压缩包密码错误,解压失败,请检查后重试"
|
||||
|
||||
#website
|
||||
ErrAliasIsExist: "代号已存在"
|
||||
ErrAliasIsExist: "标识已存在"
|
||||
ErrBackupMatch: '该备份文件与当前网站部分数据不匹配 {{ .detail }}'
|
||||
ErrBackupExist: '该备份文件对应部分源数据不存在 {{ .detail }}'
|
||||
ErrPHPResource: '本地运行环境不支持切换!'
|
||||
ErrPathPermission: 'index 目录下检测到非 1000:1000 权限文件夹,可能导致网站访问 Access denied 错误,请点击上方保存按钮'
|
||||
ErrPathPermission: 'index 目录存在非 1000:1000 权限目录,可能导致 Access denied,请点击上方保存'
|
||||
ErrDomainIsUsed: "域名已被网站【{{ .name }}】使用"
|
||||
ErrDomainFormat: "{{ .name }} 域名格式不正确"
|
||||
ErrDefaultAlias: "default 为保留代号,请使用其他代号"
|
||||
@@ -166,14 +167,14 @@ pause: '暂停'
|
||||
unpause: '恢复'
|
||||
remove: '删除'
|
||||
delete: '删除'
|
||||
ErrDefaultWebsite: "已经设置默认网站,请取消后再设置!"
|
||||
ErrDefaultWebsite: "已设置默认网站,请先取消再设置"
|
||||
SSL: '证书'
|
||||
Set: '设置'
|
||||
|
||||
#ssl
|
||||
ErrSSLCannotDelete: "{{ .name }} 证书正在被网站使用,无法删除"
|
||||
ErrAccountCannotDelete: "账号关联证书,无法删除"
|
||||
ErrSSLApply: "证书续签成功,openresty reload失败,请检查配置!"
|
||||
ErrSSLApply: "证书续签成功,但 OpenResty reload 失败,请检查配置"
|
||||
ErrEmailIsExist: '邮箱已存在'
|
||||
ErrSSLKeyNotFound: '私钥文件不存在'
|
||||
ErrSSLCertificateNotFound: '证书文件不存在'
|
||||
@@ -181,18 +182,18 @@ ErrSSLKeyFormat: '私钥文件校验失败'
|
||||
ErrSSLCertificateFormat: '证书文件格式错误,请使用 pem 格式'
|
||||
ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid 或 EabHmacKey 不能为空'
|
||||
ErrOpenrestyNotFound: 'Http 模式需要首先安装 Openresty'
|
||||
ApplySSLStart: '开始申请证书,域名 [{{ .domain }}] 申请方式 [{{ .type }}] '
|
||||
ApplySSLStart: '开始申请证书,域名 [{{ .domain }}],方式 [{{ .type }}]'
|
||||
dnsAccount: "DNS 自动"
|
||||
dnsManual: "DNS 手动"
|
||||
http: "HTTP"
|
||||
ApplySSLFailed: '申请 [{{ .domain }}] 证书失败, {{ .detail }} '
|
||||
ApplySSLSuccess: '申请 [{{ .domain }}] 证书成功!!'
|
||||
ApplySSLFailed: '申请 [{{ .domain }}] 证书失败,{{ .detail }}'
|
||||
ApplySSLSuccess: '申请 [{{ .domain }}] 证书成功'
|
||||
DNSAccountName: 'DNS 账号 [{{ .name }}] 厂商 [{{ .type }}]'
|
||||
PushDirLog: '证书推送到目录 [{{ .path }}] {{ .status }}'
|
||||
ErrDeleteCAWithSSL: "当前机构下存在已签发证书,无法删除"
|
||||
ErrDeleteWithPanelSSL: "面板 SSL 配置使用此证书,无法删除"
|
||||
ErrDefaultCA: "默认机构不能删除"
|
||||
ApplyWebSiteSSLLog: "开始更新 {{ .name }} 网站证书"
|
||||
ApplyWebSiteSSLLog: "开始更新网站证书 {{ .name }}"
|
||||
ErrUpdateWebsiteSSL: "{{ .name }} 网站更新证书失败: {{ .err }}"
|
||||
ApplyWebSiteSSLSuccess: "更新网站证书成功"
|
||||
ErrExecShell: "执行脚本失败 {{ .err }}"
|
||||
@@ -201,19 +202,19 @@ ExecShellSuccess: "脚本执行成功"
|
||||
StartUpdateSystemSSL: "开始更新系统证书"
|
||||
UpdateSystemSSLSuccess: "更新系统证书成功"
|
||||
ErrWildcardDomain: "HTTP 模式无法申请泛域名证书"
|
||||
ErrApplySSLCanNotDelete: "正在申请的证书{{.name}}无法删除,请稍后再试"
|
||||
ErrApplySSLCanNotDelete: "正在申请的证书{{ .name }}无法删除,请稍后重试"
|
||||
StartPushSSLToNode: "开始推送证书到节点"
|
||||
PushSSLToNodeFailed: "推送证书到节点失败: {{ .err }}"
|
||||
PushSSLToNodeSuccess: "推送证书到节点成功"
|
||||
|
||||
#mysql
|
||||
ErrUserIsExist: "当前用户已存在,请重新输入"
|
||||
ErrDatabaseIsExist: "当前数据库已存在,请重新输入"
|
||||
ErrUserIsExist: "用户已存在,请重新输入"
|
||||
ErrDatabaseIsExist: "数据库已存在,请重新输入"
|
||||
ErrExecTimeOut: "SQL 执行超时,请检查数据库"
|
||||
ErrRemoteExist: "远程数据库已存在该名称,请修改后重试"
|
||||
ErrLocalExist: "本地数据库已存在该名称,请修改后重试"
|
||||
RemoteBackup: "备份远程数据库需要先使用镜像 {{ .name }} 启动本地容器数据库服务,请稍候..."
|
||||
RemoteRecover: "恢复远程数据库需要先使用镜像 {{ .name }} 启动本地容器数据库服务,请稍候..."
|
||||
RemoteBackup: "备份远程数据库前需先用镜像 {{ .name }} 启动本地容器数据库服务,请稍候"
|
||||
RemoteRecover: "恢复远程数据库前需先用镜像 {{ .name }} 启动本地容器数据库服务,请稍候"
|
||||
Arg: "参数"
|
||||
|
||||
#redis
|
||||
@@ -224,7 +225,7 @@ ErrInUsed: "{{ .detail }} 正被使用,无法删除!"
|
||||
ErrObjectInUsed: "该对象正被使用,无法删除!"
|
||||
ErrObjectBeDependent: "该镜像正被其他镜像所依赖,无法删除!"
|
||||
ErrPortRules: "端口数目不匹配,请重新输入!"
|
||||
ErrPgImagePull: "镜像拉取超时,请配置镜像加速或手动拉取 {{ .name }} 镜像后重试"
|
||||
ErrPgImagePull: "镜像拉取超时,请配置镜像加速或手动拉取 {{ .name }} 后重试"
|
||||
PruneHelper: "本次清理 {{ .name }} 释放磁盘空间 {{ .size }}"
|
||||
ImageRemoveHelper: "删除镜像 {{ .name }} ,释放磁盘空间 {{ .size }}"
|
||||
BuildCache: "构建缓存"
|
||||
@@ -241,7 +242,7 @@ ErrRuntimeStart: "启动失败"
|
||||
ErrPackageJsonNotFound: "package.json 文件不存在"
|
||||
ErrScriptsNotFound: "没有在 package.json 中找到 scripts 配置项"
|
||||
ErrContainerNameNotFound: "无法获取容器名称,请检查 .env 文件"
|
||||
ErrNodeModulesNotFound: "node_modules 文件夹不存在!请编辑运行环境或者等待运行环境启动成功"
|
||||
ErrNodeModulesNotFound: "node_modules 文件夹不存在!请编辑运行环境或等待运行环境启动成功"
|
||||
ErrContainerNameIsNull: "容器名称不存在"
|
||||
ErrPHPPortIsDefault: "9000 端口为默认端口,请修改后重试"
|
||||
ErrPHPRuntimePortFailed: "{{ .name }} 端口已被当前运行环境使用,请修改后重试"
|
||||
@@ -268,16 +269,16 @@ Upload: "上传"
|
||||
IgnoreBackupErr: "备份失败,错误:{{ .detail }},忽略本次错误..."
|
||||
IgnoreUploadErr: "上传失败,错误:{{ .detail }},忽略本次错误..."
|
||||
LoadBackupFailed: "获取备份账号连接失败,错误:{{ .detail }}"
|
||||
InExecuting: "当前任务正在执行中,请勿重复执行!"
|
||||
NoSuchResource: "数据库中未能查询到备份内容,跳过..."
|
||||
InExecuting: "任务执行中,请勿重复执行"
|
||||
NoSuchResource: "数据库未查询到备份内容,跳过"
|
||||
CleanLog: "清理日志"
|
||||
CleanLogByName: "清理 {{.name}} 日志"
|
||||
CleanLogByName: "清理 {{ .name }} 日志"
|
||||
WafIpGroupNotFound: "WAF IP组未找到,请先到【高级功能-WAF-黑白名单-IP组】添加远程下载方式的IP组"
|
||||
|
||||
#toolbox
|
||||
ErrNotExistUser: "当前用户不存在,请修改后重试!"
|
||||
ErrBanAction: "设置失败,当前 {{ .name }} 服务不可用,请检查后重试!!"
|
||||
ErrClamdscanNotFound: "未检测到 clamdscan 命令,请参考文档安装!"
|
||||
ErrBanAction: "设置失败,{{ .name }} 服务不可用,请检查后重试"
|
||||
ErrClamdscanNotFound: "未检测到 clamdscan 命令,请按文档安装"
|
||||
TaskSwapSet: "设置 Swap"
|
||||
SetSwap: "设置 Swap {{ .path }} - {{ .size }}"
|
||||
CreateSwap: "创建 Swap 文件"
|
||||
@@ -310,10 +311,10 @@ xss: 'XSS'
|
||||
phpExec: 'PHP 脚本执行'
|
||||
oneWordTrojan: '一句话木马'
|
||||
appFilter: '应用危险目录过滤'
|
||||
webshell: 'Webshell'
|
||||
webShell: 'WebShell'
|
||||
args: '参数规则'
|
||||
protocolFilter: '协议过滤'
|
||||
javaFileter: 'Java 危险文件过滤'
|
||||
javaFilter: 'Java 危险文件过滤'
|
||||
scannerFilter: '扫描器过滤'
|
||||
escapeFilter: '转义过滤'
|
||||
customRule: '自定义规则'
|
||||
@@ -344,8 +345,8 @@ allow: "允许"
|
||||
deny: "禁止"
|
||||
OpenrestyNotFound: "Openresty 未安装"
|
||||
remoteIpIsNull: "IP 列表为空"
|
||||
OpenrestyVersionErr: "Openresty 版本过低,请升级 Openresty 至 1.27.1.2-2-2-focal"
|
||||
ErrFileTooLarge: "文件超过 1MB 无法上传"
|
||||
OpenrestyVersionErr: "OpenResty 版本过低,请升级到 1.27.1.2-2-2-focal"
|
||||
ErrFileTooLarge: "文件超过 1MB,无法上传"
|
||||
|
||||
#task
|
||||
TaskStart: "{{ .name }} 任务开始 [START]"
|
||||
@@ -403,7 +404,7 @@ TaskSync: "同步"
|
||||
LocalApp: "本地应用"
|
||||
SubTask: "子任务"
|
||||
RuntimeExtension: "运行环境扩展"
|
||||
TaskIsExecuting: "任务正在运行"
|
||||
TaskIsExecuting: "任务运行中"
|
||||
CustomAppstore: "自定义应用仓库"
|
||||
TaskExec: "执行"
|
||||
TaskBatch: "批量操作"
|
||||
@@ -414,14 +415,14 @@ Clamscan: "扫描 {{ .name }}"
|
||||
TaskScan: "扫描"
|
||||
|
||||
# task - ai
|
||||
OllamaModelPull: "拉取 Ollama 模型 {{ .name }} "
|
||||
OllamaModelSize: "获取 Ollama 模型 {{ .name }} 大小 "
|
||||
OllamaModelPull: "拉取 Ollama 模型 {{ .name }}"
|
||||
OllamaModelSize: "获取 Ollama 模型 {{ .name }} 大小"
|
||||
|
||||
# task - snapshot
|
||||
Snapshot: "快照"
|
||||
SnapDBInfo: "写入 1Panel 数据库信息"
|
||||
SnapCopy: "复制文件&目录 {{ .name }} "
|
||||
SnapNewDB: "初始化数据库 {{ .name }} 连接 "
|
||||
SnapCopy: "复制文件/目录 {{ .name }}"
|
||||
SnapNewDB: "初始化数据库 {{ .name }} 连接"
|
||||
SnapDeleteOperationLog: "删除操作日志"
|
||||
SnapDeleteLoginLog: "删除访问日志"
|
||||
SnapDeleteMonitor: "删除监控数据"
|
||||
@@ -451,10 +452,10 @@ RecoverDownloadAccount: "获取快照下载备份账号 {{ .name }}"
|
||||
RecoverDecompress: "解压快照压缩文件"
|
||||
Decompress: "解压"
|
||||
BackupBeforeRecover: "快照前备份系统相关数据"
|
||||
Readjson: "读取快照内 Json 文件"
|
||||
ReadjsonPath: "获取快照内 Json 文件路径"
|
||||
ReadjsonContent: "读取 Json 文件"
|
||||
ReadjsonMarshal: "Json 转义处理"
|
||||
ReadJson: "读取快照内 Json 文件"
|
||||
ReadJsonPath: "获取快照内 Json 文件路径"
|
||||
ReadJsonContent: "读取 Json 文件"
|
||||
ReadJsonMarshal: "Json 转义处理"
|
||||
RecoverApp: "恢复已安装应用"
|
||||
RecoverWebsite: "恢复网站目录"
|
||||
RecoverAppImage: "恢复快照镜像备份"
|
||||
@@ -470,7 +471,6 @@ RecoverBackups: "恢复本地备份目录"
|
||||
RecoverPanelData: "恢复数据目录"
|
||||
|
||||
# task - container
|
||||
ContainerNewCliet: "初始化 Docker Client"
|
||||
ContainerImagePull: "拉取容器镜像 {{ .name }}"
|
||||
ContainerRemoveOld: "删除原容器 {{ .name }}"
|
||||
ContainerImageCheck: "检查镜像是否正常拉取"
|
||||
@@ -482,17 +482,12 @@ ContainerStartCheck: "检查容器是否已启动"
|
||||
|
||||
# task - image
|
||||
ImageBuild: "镜像构建"
|
||||
ImageBuildStdoutCheck: "解析镜像输出内容"
|
||||
ImageBuildRes: "镜像构建输出:{{ .name }}"
|
||||
ImagePull: "拉取镜像"
|
||||
ImageRepoAuthFromDB: "从数据库获取仓库认证信息"
|
||||
ImaegPullRes: "镜像拉取输出:{{ .name }}"
|
||||
ImagePush: "推送镜像"
|
||||
ImageRenameTag: "修改镜像 Tag"
|
||||
ImageNewTag: "新镜像 Tag {{ .name }}"
|
||||
ImaegPushRes: "镜像推送输出:{{ .name }}"
|
||||
ComposeCreate: "创建编排"
|
||||
ComposeCreateRes: "编排创建输出:{{ .name }}"
|
||||
|
||||
# task - website
|
||||
BackupNginxConfig: "备份网站 OpenResty 配置文件"
|
||||
@@ -503,15 +498,11 @@ ErrCheckValid: "校验备份文件失败,{{ .name }}"
|
||||
Rollback: "回滚"
|
||||
websiteDir: "网站目录"
|
||||
RecoverFailedStartRollBack: "恢复失败,开始回滚"
|
||||
AppBackupFileIncomplete: "备份文件不完整 缺少 app.json 或者 app.tar.gz 文件"
|
||||
AppAttributesNotMatch: "应用类型或者名称不一致"
|
||||
AppBackupFileIncomplete: "备份文件不完整,缺少 app.json 或 app.tar.gz 文件"
|
||||
AppAttributesNotMatch: "应用类型或名称不一致"
|
||||
|
||||
#alert
|
||||
ErrAlert: "告警信息格式错误,请检查后重试!!"
|
||||
ErrAlertPush: "告警信息推送错误,请检查后重试!!"
|
||||
ErrAlertSave: "告警信息保存错误,请检查后重试!!"
|
||||
ErrAlertSync: "告警信息同步错误,请检查后重试!!"
|
||||
ErrAlertRemote: "告警信息远端错误,请检查后重试!!"
|
||||
ErrAlertSync: "告警信息同步错误,请检查后重试"
|
||||
|
||||
#task - runtime
|
||||
ErrInstallExtension: "已有安装任务正在进行,请等待任务结束"
|
||||
@@ -519,20 +510,20 @@ ErrInstallExtension: "已有安装任务正在进行,请等待任务结束"
|
||||
# alert mail template
|
||||
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 }} 面板,平均 {{ .time }} 分钟内的 {{ .name }} 使用率为 {{ .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 }}异常,详情请登录面板查看。"
|
||||
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 }} 面板,平均 {{ .time }} 分钟内的 {{ .name }} 使用率为 {{ .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 }} 异常,请登录面板查看详情。"
|
||||
|
||||
#disk
|
||||
DeviceNotFound: "设备 {{ .name }} 未找到"
|
||||
@@ -540,5 +531,4 @@ DeviceIsMounted: "设备 {{ .name }} 已挂载,请先卸载"
|
||||
PartitionDiskErr: "分区失败,{{ .err }}"
|
||||
FormatDiskErr: "格式化磁盘失败,{{ .err }}"
|
||||
MountDiskErr: "挂载磁盘失败,{{ .err }}"
|
||||
UnMountDiskErr: "卸载磁盘失败,{{ .err }}"
|
||||
XfsNotFound: "未检测到 xfs 文件系统,请先安装 xfsprogs"
|
||||
|
||||
@@ -27,11 +27,12 @@ func Init() {
|
||||
|
||||
initDockerConf()
|
||||
initAlertTask()
|
||||
initMonitorDB()
|
||||
}
|
||||
|
||||
func initGlobalData() {
|
||||
settingRepo := repo.NewISettingRepo()
|
||||
if _, err := settingRepo.Get(settingRepo.WithByKey("SystemStatus")); err != nil {
|
||||
if _, err := settingRepo.GetValueByKey("SystemStatus"); err != nil {
|
||||
_ = settingRepo.Create("SystemStatus", "Free")
|
||||
}
|
||||
if err := settingRepo.Update("SystemStatus", "Free"); err != nil {
|
||||
@@ -42,6 +43,7 @@ func initGlobalData() {
|
||||
_ = settingRepo.Update("SystemVersion", node.Version)
|
||||
}
|
||||
global.CONF.Base.Version = node.Version
|
||||
global.CONF.Base.Edition, _ = settingRepo.GetValueByKey("Edition")
|
||||
global.CONF.Base.EncryptKey, _ = settingRepo.GetValueByKey("EncryptKey")
|
||||
}
|
||||
|
||||
@@ -151,3 +153,8 @@ func initDockerConf() {
|
||||
func initAlertTask() {
|
||||
service.NewIAlertTaskHelper().ResetTask()
|
||||
}
|
||||
|
||||
func initMonitorDB() {
|
||||
_ = global.MonitorDB.AutoMigrate(&model.MonitorBase{}, &model.MonitorNetwork{}, &model.MonitorGPU{}, &model.MonitorIO{})
|
||||
_ = global.TaskDB.AutoMigrate(&model.Task{})
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ func loadRestorePath(upgradeDir string) (string, error) {
|
||||
}
|
||||
|
||||
func downloadLangFromRemote(fileOp files.FileOp) {
|
||||
path := fmt.Sprintf("%s/language/lang.tar.gz", global.CONF.RemoteURL.RepoUrl)
|
||||
path := fmt.Sprintf("%s/language/lang.tar.gz", global.RepoURL())
|
||||
if err := fileOp.DownloadFile(path, "/usr/local/bin/lang.tar.gz"); err != nil {
|
||||
global.LOG.Errorf("download lang.tar.gz failed, err: %v", err)
|
||||
return
|
||||
@@ -123,7 +123,7 @@ func downloadLangFromRemote(fileOp files.FileOp) {
|
||||
}
|
||||
func downloadGeoFromRemote(fileOp files.FileOp, targetPath string) {
|
||||
_ = os.MkdirAll(path.Dir(targetPath), os.ModePerm)
|
||||
pathItem := fmt.Sprintf("%s/geo/GeoIP.mmdb", global.CONF.RemoteURL.RepoUrl)
|
||||
pathItem := fmt.Sprintf("%s/geo/GeoIP.mmdb", global.RepoURL())
|
||||
if err := fileOp.DownloadFile(pathItem, targetPath); err != nil {
|
||||
global.LOG.Errorf("download geo ip failed, err: %v", err)
|
||||
return
|
||||
|
||||
@@ -66,6 +66,12 @@ func InitAgentDB() {
|
||||
migrations.AddAgentTables,
|
||||
migrations.MigrateOpenclawAgents,
|
||||
migrations.AddAgentCustomModelFields,
|
||||
migrations.AddAppInstallSortOrder,
|
||||
migrations.AddAgentAccountRememberAPIKey,
|
||||
migrations.AddEditionSetting,
|
||||
migrations.AddAgentTypeForAgents,
|
||||
migrations.NormalizeAgentAccountVerifiedStatus,
|
||||
migrations.NormalizeOllamaAccountAPIType,
|
||||
})
|
||||
if err := m.Migrate(); err != nil {
|
||||
global.LOG.Error(err)
|
||||
|
||||
@@ -128,7 +128,8 @@ var InitSetting = &gormigrate.Migration{
|
||||
if err := tx.Create(&model.Setting{Key: "SystemStatus", Value: "Free"}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Create(&model.Setting{Key: "Language", Value: "zh"}).Error; err != nil {
|
||||
lang := common.LoadParamsWithoutPanic("LANGUAGE")
|
||||
if err := tx.Create(&model.Setting{Key: "Language", Value: lang}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Create(&model.Setting{Key: "SystemIP", Value: ""}).Error; err != nil {
|
||||
@@ -957,3 +958,79 @@ var AddAgentCustomModelFields = &gormigrate.Migration{
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var AddAppInstallSortOrder = &gormigrate.Migration{
|
||||
ID: "20260222-add-app-install-sort-order",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
return tx.AutoMigrate(&model.AppInstall{})
|
||||
},
|
||||
}
|
||||
|
||||
var AddAgentAccountRememberAPIKey = &gormigrate.Migration{
|
||||
ID: "20260225-add-agent-account-remember-api-key",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
if err := tx.AutoMigrate(&model.AgentAccount{}); err != nil {
|
||||
return err
|
||||
}
|
||||
return tx.Model(&model.AgentAccount{}).Where("remember_api_key IS NULL").Update("remember_api_key", true).Error
|
||||
},
|
||||
}
|
||||
|
||||
var AddEditionSetting = &gormigrate.Migration{
|
||||
ID: "20260224-add-edition-setting",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
var setting model.Setting
|
||||
edition := common.LoadParamsWithoutPanic("PANEL_EDITION")
|
||||
if err := tx.Where("key = ?", "Edition").First(&setting).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return tx.Create(&model.Setting{Key: "Edition", Value: edition}).Error
|
||||
}
|
||||
return err
|
||||
}
|
||||
if setting.Value == "" {
|
||||
return tx.Model(&model.Setting{}).Where("key = ?", "Edition").Update("value", edition).Error
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var AddAgentTypeForAgents = &gormigrate.Migration{
|
||||
ID: "20260302-add-agent-type-for-agents",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
if err := tx.AutoMigrate(&model.Agent{}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Model(&model.Agent{}).Where("agent_type = '' OR agent_type IS NULL").Update("agent_type", constant.AppOpenclaw).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return tx.Exec(
|
||||
"UPDATE agents SET agent_type = ? WHERE app_install_id IN (SELECT ai.id FROM app_installs ai JOIN apps a ON ai.app_id = a.id WHERE a.key = ?)",
|
||||
constant.AppCopaw,
|
||||
constant.AppCopaw,
|
||||
).Error
|
||||
},
|
||||
}
|
||||
|
||||
var NormalizeAgentAccountVerifiedStatus = &gormigrate.Migration{
|
||||
ID: "20260303-normalize-agent-account-verified-status",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
if err := tx.AutoMigrate(&model.AgentAccount{}); err != nil {
|
||||
return err
|
||||
}
|
||||
return tx.Model(&model.AgentAccount{}).
|
||||
Where("provider IN ?", []string{"custom", "ollama", "kimi-coding"}).
|
||||
Update("verified", false).Error
|
||||
},
|
||||
}
|
||||
|
||||
var NormalizeOllamaAccountAPIType = &gormigrate.Migration{
|
||||
ID: "20260304-normalize-ollama-account-api-type",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
if err := tx.AutoMigrate(&model.AgentAccount{}); err != nil {
|
||||
return err
|
||||
}
|
||||
return tx.Model(&model.AgentAccount{}).
|
||||
Where("provider = ?", "ollama").
|
||||
Update("api_type", "openai-responses").Error
|
||||
},
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ func Routers() *gin.Engine {
|
||||
if !global.IsMaster {
|
||||
PrivateGroup.Use(middleware.Certificate())
|
||||
}
|
||||
PrivateGroup.Use(middleware.OperationResolveMeta())
|
||||
for _, router := range rou.RouterGroupApp {
|
||||
router.InitRouter(PrivateGroup)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,206 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"mime"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"path"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/cmd/server/docs"
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/re"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/glebarez/sqlite"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const (
|
||||
headerNeedOperationResolve = "X-Need-Op-Resolve"
|
||||
headerOperationResolved = "X-Op-Resolved"
|
||||
)
|
||||
|
||||
var (
|
||||
logMetaOnce sync.Once
|
||||
logMetaData map[string]operationMeta
|
||||
logMetaLoadErr error
|
||||
)
|
||||
|
||||
type operationMeta struct {
|
||||
BodyKeys []string `json:"bodyKeys"`
|
||||
BeforeFunctions []functionInfo `json:"beforeFunctions"`
|
||||
}
|
||||
|
||||
type functionInfo struct {
|
||||
InputColumn string `json:"input_column"`
|
||||
InputValue string `json:"input_value"`
|
||||
IsList bool `json:"isList"`
|
||||
DB string `json:"db"`
|
||||
OutputColumn string `json:"output_column"`
|
||||
OutputValue string `json:"output_value"`
|
||||
}
|
||||
|
||||
func OperationResolveMeta() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
if c.GetHeader(headerNeedOperationResolve) != "1" {
|
||||
c.Next()
|
||||
return
|
||||
}
|
||||
|
||||
metaMap, err := loadOperationMeta()
|
||||
if err != nil {
|
||||
c.Next()
|
||||
return
|
||||
}
|
||||
reqPath := strings.TrimPrefix(c.Request.URL.Path, "/api/v2")
|
||||
meta, ok := metaMap[reqPath]
|
||||
if !ok || len(meta.BeforeFunctions) == 0 {
|
||||
c.Next()
|
||||
return
|
||||
}
|
||||
|
||||
values := make(map[string]interface{})
|
||||
if len(meta.BodyKeys) > 0 {
|
||||
body, err := io.ReadAll(c.Request.Body)
|
||||
if err == nil {
|
||||
c.Request.Body = io.NopCloser(bytes.NewBuffer(body))
|
||||
bodyMap := make(map[string]interface{})
|
||||
if strings.Contains(c.Request.Header.Get("Content-Type"), "multipart/form-data") {
|
||||
bodyMap, _ = parseMultipart(body, c.Request.Header.Get("Content-Type"))
|
||||
} else {
|
||||
_ = json.Unmarshal(body, &bodyMap)
|
||||
}
|
||||
for _, key := range meta.BodyKeys {
|
||||
if value, ok := bodyMap[key]; ok {
|
||||
values[key] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resolved, err := resolveOperationValues(reqPath, values, meta.BeforeFunctions)
|
||||
if err == nil && len(resolved) > 0 {
|
||||
if data, err := json.Marshal(resolved); err == nil {
|
||||
c.Header(headerOperationResolved, base64.RawURLEncoding.EncodeToString(data))
|
||||
}
|
||||
}
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
func loadOperationMeta() (map[string]operationMeta, error) {
|
||||
logMetaOnce.Do(func() {
|
||||
logMetaData = make(map[string]operationMeta)
|
||||
logMetaLoadErr = json.Unmarshal(docs.XLogJson, &logMetaData)
|
||||
})
|
||||
return logMetaData, logMetaLoadErr
|
||||
}
|
||||
|
||||
func parseMultipart(formData []byte, contentType string) (map[string]interface{}, error) {
|
||||
d, params, err := mime.ParseMediaType(contentType)
|
||||
if err != nil || d != "multipart/form-data" {
|
||||
return nil, http.ErrNotMultipart
|
||||
}
|
||||
boundary, ok := params["boundary"]
|
||||
if !ok {
|
||||
return nil, http.ErrMissingBoundary
|
||||
}
|
||||
reader := multipart.NewReader(bytes.NewReader(formData), boundary)
|
||||
ret := make(map[string]interface{})
|
||||
|
||||
f, err := reader.ReadForm(32 << 20)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for k, v := range f.Value {
|
||||
if len(v) > 0 {
|
||||
ret[k] = v[0]
|
||||
}
|
||||
}
|
||||
for k, v := range f.File {
|
||||
if len(v) > 0 {
|
||||
ret[k] = v[0].Filename
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func resolveOperationValues(pathItem string, values map[string]interface{}, beforeFunctions []functionInfo) (map[string]string, error) {
|
||||
dbItem, err := newResolveDB(pathItem)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer closeResolveDB(dbItem)
|
||||
|
||||
resolved := make(map[string]string)
|
||||
for _, funcs := range beforeFunctions {
|
||||
if !isSafeIdentifier(funcs.DB) || !isSafeIdentifier(funcs.InputColumn) || !isSafeIdentifier(funcs.OutputColumn) {
|
||||
continue
|
||||
}
|
||||
for key, value := range values {
|
||||
if funcs.InputValue != key {
|
||||
continue
|
||||
}
|
||||
var names []string
|
||||
if funcs.IsList {
|
||||
sql := fmt.Sprintf("SELECT %s FROM %s where %s in (?);", funcs.OutputColumn, funcs.DB, funcs.InputColumn)
|
||||
_ = dbItem.Raw(sql, value).Scan(&names)
|
||||
} else {
|
||||
sql := fmt.Sprintf("SELECT %s FROM %s where %s = ?;", funcs.OutputColumn, funcs.DB, funcs.InputColumn)
|
||||
_ = dbItem.Raw(sql, value).Scan(&names)
|
||||
}
|
||||
outputValue := strings.Join(names, ",")
|
||||
resolved[funcs.OutputValue] = outputValue
|
||||
values[funcs.OutputValue] = outputValue
|
||||
break
|
||||
}
|
||||
}
|
||||
return resolved, nil
|
||||
}
|
||||
|
||||
func newResolveDB(pathItem string) (*gorm.DB, error) {
|
||||
dbFile := ""
|
||||
switch {
|
||||
case strings.HasPrefix(pathItem, "/core"):
|
||||
dbFile = path.Join(global.CONF.Base.InstallDir, "1panel/db/core.db")
|
||||
case strings.HasPrefix(pathItem, "/xpack"):
|
||||
dbFile = path.Join(global.CONF.Base.InstallDir, "1panel/db/xpack.db")
|
||||
default:
|
||||
dbFile = path.Join(global.CONF.Base.InstallDir, "1panel/db/agent.db")
|
||||
}
|
||||
|
||||
db, err := gorm.Open(sqlite.Open(dbFile), &gorm.Config{
|
||||
DisableForeignKeyConstraintWhenMigrating: true,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sqlDB, err := db.DB()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sqlDB.SetMaxOpenConns(4)
|
||||
sqlDB.SetMaxIdleConns(1)
|
||||
sqlDB.SetConnMaxIdleTime(15 * time.Minute)
|
||||
sqlDB.SetConnMaxLifetime(time.Hour)
|
||||
return db, nil
|
||||
}
|
||||
|
||||
func closeResolveDB(db *gorm.DB) {
|
||||
sqlDB, err := db.DB()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
_ = sqlDB.Close()
|
||||
}
|
||||
|
||||
func isSafeIdentifier(val string) bool {
|
||||
return re.GetRegex(re.SQLIdentifierPattern).MatchString(val)
|
||||
}
|
||||
@@ -54,5 +54,18 @@ func (a *AIToolsRouter) InitRouter(Router *gin.RouterGroup) {
|
||||
aiToolsRouter.POST("/agents/channel/feishu/get", baseApi.GetAgentFeishuConfig)
|
||||
aiToolsRouter.POST("/agents/channel/feishu/update", baseApi.UpdateAgentFeishuConfig)
|
||||
aiToolsRouter.POST("/agents/channel/feishu/approve", baseApi.ApproveAgentFeishuPairing)
|
||||
aiToolsRouter.POST("/agents/channel/telegram/get", baseApi.GetAgentTelegramConfig)
|
||||
aiToolsRouter.POST("/agents/channel/telegram/update", baseApi.UpdateAgentTelegramConfig)
|
||||
aiToolsRouter.POST("/agents/channel/discord/get", baseApi.GetAgentDiscordConfig)
|
||||
aiToolsRouter.POST("/agents/channel/discord/update", baseApi.UpdateAgentDiscordConfig)
|
||||
aiToolsRouter.POST("/agents/channel/qqbot/get", baseApi.GetAgentQQBotConfig)
|
||||
aiToolsRouter.POST("/agents/channel/qqbot/update", baseApi.UpdateAgentQQBotConfig)
|
||||
aiToolsRouter.POST("/agents/plugin/install", baseApi.InstallAgentPlugin)
|
||||
aiToolsRouter.POST("/agents/plugin/check", baseApi.CheckAgentPlugin)
|
||||
aiToolsRouter.POST("/agents/browser/get", baseApi.GetAgentBrowserConfig)
|
||||
aiToolsRouter.POST("/agents/browser/update", baseApi.UpdateAgentBrowserConfig)
|
||||
aiToolsRouter.POST("/agents/other/get", baseApi.GetAgentOtherConfig)
|
||||
aiToolsRouter.POST("/agents/other/update", baseApi.UpdateAgentOtherConfig)
|
||||
aiToolsRouter.POST("/agents/channel/pairing/approve", baseApi.ApproveAgentChannelPairing)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ func (a *AppRouter) InitRouter(Router *gin.RouterGroup) {
|
||||
appRouter.POST("/installed/params/update", baseApi.UpdateInstalled)
|
||||
appRouter.POST("/installed/update/versions", baseApi.GetUpdateVersions)
|
||||
appRouter.POST("/installed/config/update", baseApi.UpdateAppConfig)
|
||||
appRouter.POST("/installed/sort/update", baseApi.UpdateAppInstallSort)
|
||||
appRouter.GET("/installed/info/:appInstallId", baseApi.GetAppInstallInfo)
|
||||
|
||||
appRouter.POST("/installed/ignore", baseApi.IgnoreAppUpgrade)
|
||||
|
||||
@@ -15,7 +15,6 @@ func (s *ContainerRouter) InitRouter(Router *gin.RouterGroup) {
|
||||
baRouter.GET("/stats/:id", baseApi.ContainerStats)
|
||||
|
||||
baRouter.POST("", baseApi.ContainerCreate)
|
||||
baRouter.POST("command", baseApi.ContainerCreateByCommand)
|
||||
baRouter.POST("/update", baseApi.ContainerUpdate)
|
||||
baRouter.POST("/upgrade", baseApi.ContainerUpgrade)
|
||||
baRouter.POST("/info", baseApi.ContainerInfo)
|
||||
|
||||
@@ -54,6 +54,8 @@ func (a *WebsiteRouter) InitRouter(Router *gin.RouterGroup) {
|
||||
|
||||
websiteRouter.POST("/proxies", baseApi.GetProxyConfig)
|
||||
websiteRouter.POST("/proxies/update", baseApi.UpdateProxyConfig)
|
||||
websiteRouter.POST("/proxies/delete", baseApi.DeleteProxyConfig)
|
||||
websiteRouter.POST("/proxies/status", baseApi.UpdateProxyConfigStatus)
|
||||
websiteRouter.POST("/proxies/file", baseApi.UpdateProxyConfigFile)
|
||||
websiteRouter.POST("/proxy/config", baseApi.UpdateProxyCache)
|
||||
websiteRouter.GET("/proxy/config/:id", baseApi.GetProxyCache)
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/psutil"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/re"
|
||||
"github.com/jinzhu/copier"
|
||||
"mime"
|
||||
network "net"
|
||||
"net/http"
|
||||
"os"
|
||||
@@ -71,13 +72,14 @@ func CreateEmailAlertLog(create dto.AlertLogCreate, alert dto.AlertDTO, params [
|
||||
if username == "" {
|
||||
username = emailInfo.Sender
|
||||
}
|
||||
encodedDisplayName := mime.BEncoding.Encode("UTF-8", emailInfo.DisplayName)
|
||||
smtpConfig := email.SMTPConfig{
|
||||
Host: emailInfo.Host,
|
||||
Port: emailInfo.Port,
|
||||
Sender: emailInfo.Sender,
|
||||
Username: username,
|
||||
Password: emailInfo.Password,
|
||||
From: fmt.Sprintf(`"%s" <%s>`, emailInfo.DisplayName, emailInfo.Sender),
|
||||
From: fmt.Sprintf(`"%s" <%s>`, encodedDisplayName, emailInfo.Sender),
|
||||
Encryption: emailInfo.Encryption,
|
||||
Recipient: emailInfo.Recipient,
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"io"
|
||||
mathRand "math/rand"
|
||||
"math/big"
|
||||
"net"
|
||||
"os/exec"
|
||||
"reflect"
|
||||
@@ -135,13 +135,6 @@ func isDigit(r rune) bool {
|
||||
return r >= '0' && r <= '9'
|
||||
}
|
||||
|
||||
func max(x, y int) int {
|
||||
if x > y {
|
||||
return x
|
||||
}
|
||||
return y
|
||||
}
|
||||
|
||||
func GetSortedVersions(versions []string) []string {
|
||||
sort.Slice(versions, func(i, j int) bool {
|
||||
return CompareVersion(versions[i], versions[j])
|
||||
@@ -169,21 +162,29 @@ var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456
|
||||
|
||||
func RandStr(n int) string {
|
||||
b := make([]rune, n)
|
||||
max := big.NewInt(int64(len(letters)))
|
||||
for i := range b {
|
||||
b[i] = letters[mathRand.Intn(len(letters))]
|
||||
num, err := rand.Int(rand.Reader, max)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
b[i] = letters[num.Int64()]
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func RandStrAndNum(n int) string {
|
||||
source := mathRand.NewSource(time.Now().UnixNano())
|
||||
randGen := mathRand.New(source)
|
||||
const charset = "abcdefghijklmnopqrstuvwxyz0123456789"
|
||||
b := make([]byte, n)
|
||||
max := big.NewInt(int64(len(charset)))
|
||||
for i := range b {
|
||||
b[i] = charset[randGen.Intn(len(charset)-1)]
|
||||
num, err := rand.Int(rand.Reader, max)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
b[i] = charset[num.Int64()]
|
||||
}
|
||||
return (string(b))
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func ScanPort(port int) bool {
|
||||
@@ -191,7 +192,7 @@ func ScanPort(port int) bool {
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
defer ln.Close()
|
||||
defer func() { _ = ln.Close() }()
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -200,7 +201,7 @@ func ScanUDPPort(port int) bool {
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
defer ln.Close()
|
||||
defer func() { _ = ln.Close() }()
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -225,7 +226,7 @@ func ScanPortWithIP(ip string, port int) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
defer conn.Close()
|
||||
defer func() { _ = conn.Close() }()
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -419,3 +420,22 @@ func GetDockerComposeCommand() string {
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func LoadParams(param string) string {
|
||||
stdout, err := cmd.RunDefaultWithStdoutBashCf("grep '^%s=' /usr/local/bin/1pctl | cut -d'=' -f2", param)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
info := strings.ReplaceAll(stdout, "\n", "")
|
||||
if len(info) == 0 || info == `""` {
|
||||
panic(fmt.Sprintf("error `%s` find in /usr/local/bin/1pctl", param))
|
||||
}
|
||||
return info
|
||||
}
|
||||
func LoadParamsWithoutPanic(param string) string {
|
||||
stdout, err := cmd.RunDefaultWithStdoutBashCf("grep '^%s=' /usr/local/bin/1pctl | cut -d'=' -f2", param)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return strings.ReplaceAll(stdout, "\n", "")
|
||||
}
|
||||
|
||||
@@ -67,14 +67,29 @@ func GetDBWithPath(dbPath string) (*gorm.DB, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sqlDB, dbError := db.DB()
|
||||
if dbError != nil {
|
||||
return nil, dbError
|
||||
|
||||
sqlDB, err := db.DB()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sqlDB.SetMaxOpenConns(4)
|
||||
sqlDB.SetMaxIdleConns(1)
|
||||
sqlDB.SetConnMaxIdleTime(15 * time.Minute)
|
||||
sqlDB.SetConnMaxLifetime(time.Hour)
|
||||
sqlDB.SetConnMaxLifetime(0)
|
||||
sqlDB.SetConnMaxIdleTime(0)
|
||||
|
||||
if err := db.Exec("PRAGMA journal_mode = WAL;").Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := db.Exec("PRAGMA synchronous = NORMAL;").Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := db.Exec("PRAGMA busy_timeout = 5000;").Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := db.Exec("PRAGMA temp_store = MEMORY;").Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return db, nil
|
||||
}
|
||||
|
||||
|
||||
+101
-19
@@ -1,6 +1,7 @@
|
||||
package compose
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
@@ -15,7 +16,6 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/common"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/docker"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func checkCmd() error {
|
||||
@@ -29,31 +29,37 @@ func checkCmd() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func getComposeBaseCmd() (string, []string) {
|
||||
cmdStr := strings.TrimSpace(global.CONF.DockerConfig.Command)
|
||||
parts := strings.Fields(cmdStr)
|
||||
if len(parts) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
return parts[0], parts[1:]
|
||||
}
|
||||
|
||||
func Up(filePath string) (string, error) {
|
||||
if err := checkCmd(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return cmd.NewCommandMgr(cmd.WithTimeout(20*time.Minute)).RunWithStdoutBashCf("%s %s up -d", global.CONF.DockerConfig.Command, loadFiles(filePath))
|
||||
base, extra := getComposeBaseCmd()
|
||||
args := append(extra, strings.Fields(loadFiles(filePath))...)
|
||||
args = append(args, "up", "-d")
|
||||
return cmd.NewCommandMgr(cmd.WithTimeout(20*time.Minute)).RunWithStdout(base, args...)
|
||||
}
|
||||
|
||||
func UpWithTask(filePath string, task *task.Task, forcePull bool) error {
|
||||
if err := pullComposeImages(filePath, forcePull, task); err != nil {
|
||||
return err
|
||||
}
|
||||
return cmd.NewCommandMgr(cmd.WithTask(*task)).RunBashCf("%s %s up -d", global.CONF.DockerConfig.Command, loadFiles(filePath))
|
||||
base, extra := getComposeBaseCmd()
|
||||
args := append(extra, strings.Fields(loadFiles(filePath))...)
|
||||
args = append(args, "up", "-d")
|
||||
return cmd.NewCommandMgr(cmd.WithTask(*task)).Run(base, args...)
|
||||
}
|
||||
|
||||
func pullComposeImages(filePath string, forcePull bool, task *task.Task) error {
|
||||
content, err := os.ReadFile(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
env, _ := os.ReadFile(path.Join(path.Dir(filePath), ".env"))
|
||||
var compose docker.ComposeProject
|
||||
if err := yaml.Unmarshal(content, &compose); err != nil {
|
||||
return fmt.Errorf("parse docker-compose file failed: %v", err)
|
||||
}
|
||||
images, err := docker.GetImagesFromDockerCompose(env, content)
|
||||
images, err := GetComposeImages(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -110,32 +116,103 @@ func pullComposeImages(filePath string, forcePull bool, task *task.Task) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetComposeImages(filePath string) ([]string, error) {
|
||||
images, err := getComposeImagesByCommand(filePath)
|
||||
if err == nil {
|
||||
return images, nil
|
||||
}
|
||||
|
||||
content, readErr := os.ReadFile(filePath)
|
||||
if readErr != nil {
|
||||
return nil, readErr
|
||||
}
|
||||
env, _ := os.ReadFile(path.Join(path.Dir(filePath), ".env"))
|
||||
images, parseErr := docker.GetImagesFromDockerCompose(env, content)
|
||||
if parseErr != nil {
|
||||
return nil, fmt.Errorf("get compose images failed, cmd err: %v, parse err: %v", err, parseErr)
|
||||
}
|
||||
return images, nil
|
||||
}
|
||||
|
||||
func getComposeImagesByCommand(filePath string) ([]string, error) {
|
||||
if err := checkCmd(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
base, extra := getComposeBaseCmd()
|
||||
args := append(extra, strings.Fields(loadFiles(filePath))...)
|
||||
args = append(args, "config", "--format", "json", "--no-normalize")
|
||||
stdout, err := cmd.NewCommandMgr(cmd.WithTimeout(5*time.Minute)).
|
||||
RunWithStdout(base, args...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("run compose config --format json --no-normalize failed, std: %s, err: %v", stdout, err)
|
||||
}
|
||||
|
||||
var composeConfig struct {
|
||||
Services map[string]struct {
|
||||
Image string `json:"image"`
|
||||
} `json:"services"`
|
||||
}
|
||||
if err = json.Unmarshal([]byte(stdout), &composeConfig); err != nil {
|
||||
return nil, fmt.Errorf("parse compose config json failed, std: %s, err: %v", stdout, err)
|
||||
}
|
||||
|
||||
var images []string
|
||||
seen := make(map[string]struct{})
|
||||
for _, service := range composeConfig.Services {
|
||||
image := strings.TrimSpace(service.Image)
|
||||
if image == "" {
|
||||
continue
|
||||
}
|
||||
if _, ok := seen[image]; ok {
|
||||
continue
|
||||
}
|
||||
seen[image] = struct{}{}
|
||||
images = append(images, image)
|
||||
}
|
||||
if len(images) == 0 {
|
||||
return nil, errors.New("no images found from compose config json")
|
||||
}
|
||||
return images, nil
|
||||
}
|
||||
|
||||
func Down(filePath string) (string, error) {
|
||||
if err := checkCmd(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return cmd.NewCommandMgr(cmd.WithTimeout(20*time.Minute)).RunWithStdoutBashCf("%s %s down --remove-orphans", global.CONF.DockerConfig.Command, loadFiles(filePath))
|
||||
base, extra := getComposeBaseCmd()
|
||||
args := append(extra, strings.Fields(loadFiles(filePath))...)
|
||||
args = append(args, "down", "--remove-orphans")
|
||||
return cmd.NewCommandMgr(cmd.WithTimeout(20*time.Minute)).RunWithStdout(base, args...)
|
||||
}
|
||||
|
||||
func Stop(filePath string) (string, error) {
|
||||
if err := checkCmd(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return cmd.NewCommandMgr(cmd.WithTimeout(20*time.Minute)).RunWithStdoutBashCf("%s %s stop", global.CONF.DockerConfig.Command, loadFiles(filePath))
|
||||
base, extra := getComposeBaseCmd()
|
||||
args := append(extra, strings.Fields(loadFiles(filePath))...)
|
||||
args = append(args, "stop")
|
||||
return cmd.NewCommandMgr(cmd.WithTimeout(20*time.Minute)).RunWithStdout(base, args...)
|
||||
}
|
||||
|
||||
func Restart(filePath string) (string, error) {
|
||||
if err := checkCmd(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return cmd.NewCommandMgr(cmd.WithTimeout(20*time.Minute)).RunWithStdoutBashCf("%s %s restart", global.CONF.DockerConfig.Command, loadFiles(filePath))
|
||||
base, extra := getComposeBaseCmd()
|
||||
args := append(extra, strings.Fields(loadFiles(filePath))...)
|
||||
args = append(args, "restart")
|
||||
return cmd.NewCommandMgr(cmd.WithTimeout(20*time.Minute)).RunWithStdout(base, args...)
|
||||
}
|
||||
|
||||
func Operate(filePath, operation string) (string, error) {
|
||||
if err := checkCmd(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return cmd.NewCommandMgr(cmd.WithTimeout(20*time.Minute)).RunWithStdoutBashCf("%s %s %s", global.CONF.DockerConfig.Command, loadFiles(filePath), operation)
|
||||
base, extra := getComposeBaseCmd()
|
||||
args := append(extra, strings.Fields(loadFiles(filePath))...)
|
||||
args = append(args, operation)
|
||||
return cmd.NewCommandMgr(cmd.WithTimeout(20*time.Minute)).RunWithStdout(base, args...)
|
||||
}
|
||||
|
||||
func DownAndUp(filePath string) (string, error) {
|
||||
@@ -143,11 +220,16 @@ func DownAndUp(filePath string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(20 * time.Minute))
|
||||
stdout, err := cmdMgr.RunWithStdoutBashCf("%s %s down", global.CONF.DockerConfig.Command, loadFiles(filePath))
|
||||
base, extra := getComposeBaseCmd()
|
||||
argsDown := append(extra, strings.Fields(loadFiles(filePath))...)
|
||||
argsDown = append(argsDown, "down")
|
||||
stdout, err := cmdMgr.RunWithStdout(base, argsDown...)
|
||||
if err != nil {
|
||||
return stdout, err
|
||||
}
|
||||
stdout, err = cmdMgr.RunWithStdoutBashCf("%s %s up -d", global.CONF.DockerConfig.Command, loadFiles(filePath))
|
||||
argsUp := append(extra, strings.Fields(loadFiles(filePath))...)
|
||||
argsUp = append(argsUp, "up", "-d")
|
||||
stdout, err = cmdMgr.RunWithStdout(base, argsUp...)
|
||||
return stdout, err
|
||||
}
|
||||
|
||||
|
||||
@@ -120,8 +120,7 @@ func parseRecipients(recipient string) []string {
|
||||
|
||||
func buildMessage(config SMTPConfig, message EmailMessage, toList []string) (string, error) {
|
||||
headers := make(map[string]string)
|
||||
encodedFrom := mime.BEncoding.Encode("UTF-8", config.From)
|
||||
headers["From"] = encodedFrom
|
||||
headers["From"] = config.From
|
||||
encodedSubject := mime.BEncoding.Encode("UTF-8", message.Subject)
|
||||
headers["Subject"] = encodedSubject
|
||||
headers["To"] = strings.Join(toList, ",")
|
||||
|
||||
@@ -118,10 +118,24 @@ func padding(plaintext []byte, blockSize int) []byte {
|
||||
return append(plaintext, padtext...)
|
||||
}
|
||||
|
||||
func unPadding(origData []byte) []byte {
|
||||
func unPadding(origData []byte) ([]byte, error) {
|
||||
length := len(origData)
|
||||
if length == 0 {
|
||||
return nil, fmt.Errorf("invalid padding size")
|
||||
}
|
||||
|
||||
unpadding := int(origData[length-1])
|
||||
return origData[:(length - unpadding)]
|
||||
if unpadding == 0 || unpadding > length {
|
||||
return nil, fmt.Errorf("invalid padding")
|
||||
}
|
||||
|
||||
for i := 0; i < unpadding; i++ {
|
||||
if origData[length-1-i] != byte(unpadding) {
|
||||
return nil, fmt.Errorf("invalid padding")
|
||||
}
|
||||
}
|
||||
|
||||
return origData[:(length - unpadding)], nil
|
||||
}
|
||||
|
||||
func aesEncryptWithSalt(key, plaintext []byte) ([]byte, error) {
|
||||
@@ -152,6 +166,10 @@ func aesDecryptWithSalt(key, ciphertext []byte) ([]byte, error) {
|
||||
ciphertext = ciphertext[aes.BlockSize:]
|
||||
cbc := cipher.NewCBCDecrypter(block, iv)
|
||||
cbc.CryptBlocks(ciphertext, ciphertext)
|
||||
ciphertext = unPadding(ciphertext)
|
||||
return ciphertext, nil
|
||||
|
||||
unpadded, err := unPadding(ciphertext)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return unpadded, nil
|
||||
}
|
||||
|
||||
Vendored
+17
-4
@@ -31,10 +31,10 @@ func Marshal(envMap map[string]string) (string, error) {
|
||||
for k, v := range envMap {
|
||||
if d, err := strconv.Atoi(v); err == nil && !isStartWithZero(v) {
|
||||
lines = append(lines, fmt.Sprintf(`%s=%d`, k, d))
|
||||
} else if hasEvenDoubleQuotes(v) {
|
||||
} else if shouldUseSingleQuotes(v) {
|
||||
lines = append(lines, fmt.Sprintf(`%s='%s'`, k, v))
|
||||
} else {
|
||||
lines = append(lines, fmt.Sprintf(`%s="%s"`, k, v))
|
||||
lines = append(lines, fmt.Sprintf(`%s="%s"`, k, escapeDoubleQuotedEnvValue(v)))
|
||||
}
|
||||
}
|
||||
return strings.Join(lines, "\n"), nil
|
||||
@@ -88,10 +88,10 @@ func MarshalWithOrder(envMap map[string]string, orders []string) (string, error)
|
||||
func formatEnvLine(k, v string) string {
|
||||
if d, err := strconv.Atoi(v); err == nil && !isStartWithZero(v) {
|
||||
return fmt.Sprintf(`%s=%d`, k, d)
|
||||
} else if hasEvenDoubleQuotes(v) {
|
||||
} else if shouldUseSingleQuotes(v) {
|
||||
return fmt.Sprintf(`%s='%s'`, k, v)
|
||||
} else {
|
||||
return fmt.Sprintf(`%s="%s"`, k, v)
|
||||
return fmt.Sprintf(`%s="%s"`, k, escapeDoubleQuotedEnvValue(v))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,3 +123,16 @@ func hasEvenDoubleQuotes(s string) bool {
|
||||
}
|
||||
return count%2 == 0
|
||||
}
|
||||
|
||||
func shouldUseSingleQuotes(s string) bool {
|
||||
return hasEvenDoubleQuotes(s) && !strings.Contains(s, `\`) && !strings.Contains(s, `'`)
|
||||
}
|
||||
|
||||
func escapeDoubleQuotedEnvValue(s string) string {
|
||||
replacer := strings.NewReplacer(
|
||||
`\`, `\\`,
|
||||
`"`, `\"`,
|
||||
"\n", `\n`,
|
||||
)
|
||||
return replacer.Replace(s)
|
||||
}
|
||||
|
||||
@@ -233,7 +233,7 @@ func (r *Local) Backup(info BackupInfo) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("open file %s failed, err: %v", path.Join(info.TargetDir, info.FileName), err)
|
||||
}
|
||||
defer outfile.Close()
|
||||
defer func() { _ = outfile.Close() }()
|
||||
dumpCmd := "mysqldump"
|
||||
if r.Type == constant.AppMariaDB {
|
||||
dumpCmd = "mariadb-dump"
|
||||
@@ -268,7 +268,7 @@ func (r *Local) Backup(info BackupInfo) error {
|
||||
|
||||
func (r *Local) Recover(info RecoverInfo) error {
|
||||
fi, _ := os.Open(info.SourceFile)
|
||||
defer fi.Close()
|
||||
defer func() { _ = fi.Close() }()
|
||||
mysqlCli := r.Type
|
||||
if mysqlCli == "mysql-cluster" {
|
||||
mysqlCli = "mysql"
|
||||
@@ -280,12 +280,12 @@ func (r *Local) Recover(info RecoverInfo) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer gzipFile.Close()
|
||||
defer func() { _ = gzipFile.Close() }()
|
||||
gzipReader, err := gzip.NewReader(gzipFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer gzipReader.Close()
|
||||
defer func() { _ = gzipReader.Close() }()
|
||||
cmd.Stdin = gzipReader
|
||||
} else {
|
||||
cmd.Stdin = fi
|
||||
|
||||
@@ -248,7 +248,7 @@ func (r *Remote) Backup(info BackupInfo) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("open file %s failed, err: %v", path.Join(info.TargetDir, info.FileName), err)
|
||||
}
|
||||
defer outfile.Close()
|
||||
defer func() { _ = outfile.Close() }()
|
||||
dumpCmd := "mysqldump"
|
||||
if r.Type == constant.AppMariaDB {
|
||||
dumpCmd = "mariadb-dump"
|
||||
@@ -293,7 +293,7 @@ func (r *Remote) Recover(info RecoverInfo) error {
|
||||
return buserr.New("ErrCmdIllegal")
|
||||
}
|
||||
fi, _ := os.Open(info.SourceFile)
|
||||
defer fi.Close()
|
||||
defer func() { _ = fi.Close() }()
|
||||
|
||||
image, err := loadImage(info.Type, info.Version)
|
||||
if err != nil {
|
||||
@@ -311,12 +311,12 @@ func (r *Remote) Recover(info RecoverInfo) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer gzipFile.Close()
|
||||
defer func() { _ = gzipFile.Close() }()
|
||||
gzipReader, err := gzip.NewReader(gzipFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer gzipReader.Close()
|
||||
defer func() { _ = gzipReader.Close() }()
|
||||
cmd.Stdin = gzipReader
|
||||
} else {
|
||||
cmd.Stdin = fi
|
||||
@@ -336,7 +336,7 @@ func (r *Remote) SyncDB(version string) ([]SyncDBInfo, error) {
|
||||
if err != nil {
|
||||
return datas, err
|
||||
}
|
||||
defer rows.Close()
|
||||
defer func() { _ = rows.Close() }()
|
||||
|
||||
for rows.Next() {
|
||||
var dbName, charsetName, collation string
|
||||
@@ -431,7 +431,7 @@ func (r *Remote) LoadFormatCollation(timeout uint) ([]dto.MysqlFormatCollationOp
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
defer func() { _ = rows.Close() }()
|
||||
|
||||
formatMap := make(map[string][]string)
|
||||
for rows.Next() {
|
||||
@@ -471,6 +471,7 @@ func (r *Remote) ExecSQLForHosts(timeout uint) ([]string, error) {
|
||||
return nil, buserr.New("ErrExecTimeOut")
|
||||
}
|
||||
var rows []string
|
||||
defer func() { _ = results.Close() }()
|
||||
for results.Next() {
|
||||
var host string
|
||||
if err := results.Scan(&host); err != nil {
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -99,6 +100,13 @@ func (r *Local) CreateUser(info CreateInfo, withDeleteDB bool) error {
|
||||
|
||||
func (r *Local) Delete(info DeleteInfo) error {
|
||||
if len(info.Name) != 0 {
|
||||
inUse, err := r.isDatabaseInUse(info.Name, info.Timeout)
|
||||
if err != nil && !info.ForceDelete {
|
||||
return fmt.Errorf("check database connections failed, err: %v", err)
|
||||
}
|
||||
if inUse && !info.ForceDelete {
|
||||
return buserr.WithDetail("ErrInUsed", info.Name, nil)
|
||||
}
|
||||
dropSql := fmt.Sprintf("DROP DATABASE \"%s\"", info.Name)
|
||||
if err := r.ExecSQL(dropSql, info.Timeout); err != nil && !info.ForceDelete {
|
||||
return fmt.Errorf("drop database failed, err: %v", err)
|
||||
@@ -203,6 +211,30 @@ func (r *Local) SyncDB() ([]SyncDBInfo, error) {
|
||||
|
||||
func (r *Local) Close() {}
|
||||
|
||||
func (r *Local) isDatabaseInUse(name string, timeout uint) (bool, error) {
|
||||
escapedName := strings.ReplaceAll(name, "'", "''")
|
||||
checkSQL := fmt.Sprintf(
|
||||
"SELECT COUNT(*) FROM pg_stat_activity WHERE datname='%s' AND pid <> pg_backend_pid()",
|
||||
escapedName,
|
||||
)
|
||||
lines, err := r.ExecSQLForRows(checkSQL, timeout)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
for _, line := range lines {
|
||||
countStr := strings.TrimSpace(line)
|
||||
if len(countStr) == 0 {
|
||||
continue
|
||||
}
|
||||
count, parseErr := strconv.Atoi(countStr)
|
||||
if parseErr != nil {
|
||||
return false, parseErr
|
||||
}
|
||||
return count > 0, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (r *Local) ExecSQL(command string, timeout uint) error {
|
||||
itemCommand := r.PrefixCommand[:]
|
||||
itemCommand = append(itemCommand, command)
|
||||
|
||||
@@ -95,6 +95,13 @@ func (r *Remote) CreateUser(info CreateInfo, withDeleteDB bool) error {
|
||||
|
||||
func (r *Remote) Delete(info DeleteInfo) error {
|
||||
if len(info.Name) != 0 {
|
||||
inUse, err := r.isDatabaseInUse(info.Name, info.Timeout)
|
||||
if err != nil && !info.ForceDelete {
|
||||
return fmt.Errorf("check database connections failed, err: %v", err)
|
||||
}
|
||||
if inUse && !info.ForceDelete {
|
||||
return buserr.WithDetail("ErrInUsed", info.Name, nil)
|
||||
}
|
||||
dropSql := fmt.Sprintf("DROP DATABASE \"%s\"", info.Name)
|
||||
if err := r.ExecSQL(dropSql, info.Timeout); err != nil && !info.ForceDelete {
|
||||
return fmt.Errorf("drop database failed, err: %v", err)
|
||||
@@ -107,6 +114,24 @@ func (r *Remote) Delete(info DeleteInfo) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Remote) isDatabaseInUse(name string, timeout uint) (bool, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second)
|
||||
defer cancel()
|
||||
|
||||
var count int
|
||||
if err := r.Client.QueryRowContext(
|
||||
ctx,
|
||||
"SELECT COUNT(*) FROM pg_stat_activity WHERE datname = $1 AND pid <> pg_backend_pid()",
|
||||
name,
|
||||
).Scan(&count); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if errors.Is(ctx.Err(), context.DeadlineExceeded) {
|
||||
return false, buserr.New("ErrExecTimeOut")
|
||||
}
|
||||
return count > 0, nil
|
||||
}
|
||||
|
||||
func (r *Remote) ChangePrivileges(info Privileges) error {
|
||||
super := "SUPERUSER"
|
||||
if !info.SuperUser {
|
||||
|
||||
@@ -29,6 +29,9 @@ const (
|
||||
AnsiEscapePattern = "\x1b\\[[0-9;?]*[A-Za-z]|\x1b=|\x1b>"
|
||||
RecycleBinFilePattern = `_1p_file_1p_(.+)_p_(\d+)_(\d+)`
|
||||
OrderByValidationPattern = `^[a-zA-Z_][a-zA-Z0-9_]*$`
|
||||
SQLIdentifierPattern = `^[A-Za-z_][A-Za-z0-9_]*$`
|
||||
NginxHostPattern = `^[a-zA-Z0-9.-]+(:[0-9]+)?$`
|
||||
NginxPathPattern = `^/[a-zA-Z0-9._/\-]*$`
|
||||
)
|
||||
|
||||
var regexMap = make(map[string]*regexp.Regexp)
|
||||
@@ -58,6 +61,9 @@ func Init() {
|
||||
AnsiEscapePattern,
|
||||
RecycleBinFilePattern,
|
||||
OrderByValidationPattern,
|
||||
SQLIdentifierPattern,
|
||||
NginxHostPattern,
|
||||
NginxPathPattern,
|
||||
}
|
||||
|
||||
for _, pattern := range patterns {
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
"github.com/go-acme/lego/v4/providers/dns/regru"
|
||||
"github.com/go-acme/lego/v4/providers/dns/route53"
|
||||
"github.com/go-acme/lego/v4/providers/dns/spaceship"
|
||||
"github.com/go-acme/lego/v4/providers/dns/technitium"
|
||||
"github.com/go-acme/lego/v4/providers/dns/tencentcloud"
|
||||
"github.com/go-acme/lego/v4/providers/dns/vercel"
|
||||
"github.com/go-acme/lego/v4/providers/dns/volcengine"
|
||||
@@ -59,6 +60,7 @@ const (
|
||||
Ovh DnsType = "Ovh"
|
||||
AcmeDNS DnsType = "AcmeDNS"
|
||||
PorkBun DnsType = "PorkBun"
|
||||
Technitium DnsType = "Technitium"
|
||||
)
|
||||
|
||||
type DNSParam struct {
|
||||
@@ -301,6 +303,14 @@ func getDNSProviderConfig(dnsType DnsType, params string) (challenge.Provider, e
|
||||
config.PollingInterval = pollingInterval
|
||||
config.TTL = ttl
|
||||
p, err = porkbun.NewDNSProviderConfig(config)
|
||||
case Technitium:
|
||||
config := technitium.NewDefaultConfig()
|
||||
config.BaseURL = param.BaseURL
|
||||
config.APIToken = param.Token
|
||||
config.PropagationTimeout = propagationTimeout
|
||||
config.PollingInterval = pollingInterval
|
||||
config.TTL = ttl
|
||||
p, err = technitium.NewDNSProviderConfig(config)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
||||
@@ -74,15 +74,15 @@ func (f *Fail2ban) Operate(operate string) error {
|
||||
|
||||
func (f *Fail2ban) ReBanIPs(ips []string) error {
|
||||
ipItems, _ := f.ListBanned()
|
||||
stdout, err := cmd.RunDefaultWithStdoutBashCfAndTimeOut("fail2ban-client unban --all", 10*time.Minute)
|
||||
stdout, err := cmd.NewCommandMgr(cmd.WithTimeout(10*time.Minute)).RunWithStdout("fail2ban-client", "unban", "--all")
|
||||
if err != nil {
|
||||
stdout1, err := cmd.RunDefaultWithStdoutBashCfAndTimeOut("fail2ban-client set sshd banip %s", 10*time.Minute, strings.Join(ipItems, " "))
|
||||
stdout1, err := cmd.NewCommandMgr(cmd.WithTimeout(10*time.Minute)).RunWithStdout("fail2ban-client", "set", "sshd", "banip", strings.Join(ipItems, " "))
|
||||
if err != nil {
|
||||
global.LOG.Errorf("rebanip after fail2ban-client unban --all failed, err: %s", stdout1)
|
||||
}
|
||||
return fmt.Errorf("fail2ban-client unban --all failed, err: %s", stdout)
|
||||
}
|
||||
stdout, err = cmd.RunDefaultWithStdoutBashCfAndTimeOut("fail2ban-client set sshd banip %s", 10*time.Minute, strings.Join(ips, " "))
|
||||
stdout, err = cmd.NewCommandMgr(cmd.WithTimeout(10*time.Minute)).RunWithStdout("fail2ban-client", "set", "sshd", "banip", strings.Join(ips, " "))
|
||||
if err != nil {
|
||||
return fmt.Errorf("handle `fail2ban-client set sshd banip %s` failed, err: %s", strings.Join(ips, " "), stdout)
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ func GetUpgradeVersionInfo() (*dto.UpgradeInfo, error) {
|
||||
if strings.Contains(itemVersion, "beta") {
|
||||
mode = "beta"
|
||||
}
|
||||
notes, err := loadReleaseNotes(fmt.Sprintf("%s/%s/%s/release/1panel-%s-release-notes", global.CONF.RemoteURL.RepoUrl, mode, itemVersion, itemVersion))
|
||||
notes, err := loadReleaseNotes(fmt.Sprintf("%s/%s/%s/release/1panel-%s-release-notes", global.RepoURL(), mode, itemVersion, itemVersion))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("load releases-notes of version %s failed, err: %v", itemVersion, err)
|
||||
}
|
||||
@@ -101,9 +101,9 @@ func loadVersionByMode(developer, currentVersion string) (string, string, string
|
||||
}
|
||||
|
||||
func loadVersion(isLatest bool, currentVersion, mode string) string {
|
||||
path := fmt.Sprintf("%s/%s/latest", global.CONF.RemoteURL.RepoUrl, mode)
|
||||
path := fmt.Sprintf("%s/%s/latest", global.RepoURL(), mode)
|
||||
if !isLatest {
|
||||
path = fmt.Sprintf("%s/%s/latest.current", global.CONF.RemoteURL.RepoUrl, mode)
|
||||
path = fmt.Sprintf("%s/%s/latest.current", global.RepoURL(), mode)
|
||||
}
|
||||
_, latestVersionRes, err := HandleRequest(path, http.MethodGet, constant.TimeOut20s)
|
||||
if err != nil {
|
||||
|
||||
@@ -4,17 +4,15 @@ package xpack
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/model"
|
||||
"github.com/1Panel-dev/1Panel/agent/buserr"
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/common"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
@@ -26,25 +24,13 @@ func StartClam(startClam *model.Clam, isUpdate bool) (int, error) {
|
||||
|
||||
func LoadNodeInfo(isBase bool) (model.NodeInfo, error) {
|
||||
var info model.NodeInfo
|
||||
info.BaseDir = loadParams("BASE_DIR")
|
||||
info.Version = loadParams("ORIGINAL_VERSION")
|
||||
info.BaseDir = common.LoadParams("BASE_DIR")
|
||||
info.Version = common.LoadParams("ORIGINAL_VERSION")
|
||||
info.Scope = "master"
|
||||
global.IsMaster = true
|
||||
return info, nil
|
||||
}
|
||||
|
||||
func loadParams(param string) string {
|
||||
stdout, err := cmd.RunDefaultWithStdoutBashCf("grep '^%s=' /usr/local/bin/1pctl | cut -d'=' -f2", param)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
info := strings.ReplaceAll(stdout, "\n", "")
|
||||
if len(info) == 0 || info == `""` {
|
||||
panic(fmt.Sprintf("error `%s` find in /usr/local/bin/1pctl", param))
|
||||
}
|
||||
return info
|
||||
}
|
||||
|
||||
func GetImagePrefix() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
+17
-3
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/core/app/api/v2/helper"
|
||||
"github.com/1Panel-dev/1Panel/core/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/core/app/model"
|
||||
"github.com/1Panel-dev/1Panel/core/buserr"
|
||||
"github.com/1Panel-dev/1Panel/core/constant"
|
||||
"github.com/1Panel-dev/1Panel/core/global"
|
||||
"github.com/1Panel-dev/1Panel/core/utils/captcha"
|
||||
@@ -53,7 +54,9 @@ func (b *BaseApi) Login(c *gin.Context) {
|
||||
}
|
||||
|
||||
user, msgKey, err := authService.Login(c, req, string(entrance))
|
||||
go saveLoginLogs(c, err)
|
||||
if user == nil || user.MfaStatus != constant.StatusEnable {
|
||||
go saveLoginLogs(c, wrapLoginErr(msgKey, err))
|
||||
}
|
||||
if msgKey == "ErrAuth" || msgKey == "ErrEntrance" {
|
||||
if msgKey == "ErrAuth" {
|
||||
global.IPTracker.SetNeedCaptcha(ip)
|
||||
@@ -90,6 +93,7 @@ func (b *BaseApi) MFALogin(c *gin.Context) {
|
||||
}
|
||||
|
||||
user, msgKey, err := authService.MFALogin(c, req, string(entrance))
|
||||
go saveLoginLogs(c, wrapLoginErr(msgKey, err))
|
||||
if msgKey == "ErrAuth" {
|
||||
helper.BadAuth(c, msgKey, err)
|
||||
return
|
||||
@@ -135,7 +139,7 @@ func (b *BaseApi) PasskeyFinishLogin(c *gin.Context) {
|
||||
sessionID := c.GetHeader("Passkey-Session")
|
||||
entrance := loadEntranceFromRequest(c)
|
||||
user, msgKey, err := authService.PasskeyFinishLogin(c, sessionID, entrance)
|
||||
go saveLoginLogs(c, err)
|
||||
go saveLoginLogs(c, wrapLoginErr(msgKey, err))
|
||||
if msgKey == "ErrAuth" || msgKey == "ErrEntrance" {
|
||||
if msgKey == "ErrAuth" {
|
||||
global.IPTracker.SetNeedCaptcha(common.GetRealClientIP(c))
|
||||
@@ -211,7 +215,7 @@ func (b *BaseApi) GetLoginSetting(c *gin.Context) {
|
||||
needCaptcha := global.IPTracker.NeedCaptcha(ip)
|
||||
res := &dto.LoginSetting{
|
||||
IsDemo: global.CONF.Base.IsDemo,
|
||||
IsIntl: global.CONF.Base.IsIntl,
|
||||
IsIntl: global.CONF.Base.Edition == "intl",
|
||||
IsFxplay: global.CONF.Base.IsFxplay,
|
||||
IsOffLine: global.CONF.Base.IsOffLine,
|
||||
Language: settingInfo.Language,
|
||||
@@ -237,6 +241,16 @@ func saveLoginLogs(c *gin.Context, err error) {
|
||||
_ = logService.CreateLoginLog(logs)
|
||||
}
|
||||
|
||||
func wrapLoginErr(msgKey string, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if msgKey == "ErrAuth" || msgKey == "ErrEntrance" {
|
||||
return buserr.New(msgKey)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func loadEntranceFromRequest(c *gin.Context) string {
|
||||
entranceItem := c.Request.Header.Get("EntranceCode")
|
||||
var entrance []byte
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/core/buserr"
|
||||
"github.com/1Panel-dev/1Panel/core/constant"
|
||||
"github.com/1Panel-dev/1Panel/core/global"
|
||||
"github.com/1Panel-dev/1Panel/core/utils/common"
|
||||
"github.com/1Panel-dev/1Panel/core/utils/mfa"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
@@ -98,6 +99,14 @@ func (b *BaseApi) UpdateSetting(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
}
|
||||
if req.Key == "PasskeyTrustedProxies" {
|
||||
value, err := normalizePasskeyTrustedProxies(req.Value)
|
||||
if err != nil {
|
||||
helper.BadRequest(c, err)
|
||||
return
|
||||
}
|
||||
req.Value = value
|
||||
}
|
||||
|
||||
if err := settingService.Update(req.Key, req.Value); err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
@@ -666,3 +675,26 @@ func checkEntrancePattern(val string) bool {
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func normalizePasskeyTrustedProxies(value string) (string, error) {
|
||||
if strings.TrimSpace(value) == "" {
|
||||
return "", nil
|
||||
}
|
||||
lines := strings.Split(value, "\n")
|
||||
validLines := make([]string, 0, len(lines))
|
||||
for _, line := range lines {
|
||||
line = strings.TrimSpace(line)
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
validLines = append(validLines, line)
|
||||
}
|
||||
if len(validLines) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
normalized := strings.Join(validLines, "\n")
|
||||
if _, err := common.HandleIPList(normalized); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return normalized, nil
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ type SettingInfo struct {
|
||||
Ipv6 string `json:"ipv6"`
|
||||
BindAddress string `json:"bindAddress"`
|
||||
PanelName string `json:"panelName"`
|
||||
Edition string `json:"edition"`
|
||||
Theme string `json:"theme"`
|
||||
MenuTabs string `json:"menuTabs"`
|
||||
Language string `json:"language"`
|
||||
@@ -23,6 +24,7 @@ type SettingInfo struct {
|
||||
SSL string `json:"ssl"`
|
||||
SSLType string `json:"sslType"`
|
||||
BindDomain string `json:"bindDomain"`
|
||||
PasskeyTrustedProxies string `json:"passkeyTrustedProxies"`
|
||||
AllowIPs string `json:"allowIPs"`
|
||||
SecurityEntrance string `json:"securityEntrance"`
|
||||
DashboardMemoVisible string `json:"dashboardMemoVisible"`
|
||||
@@ -31,7 +33,6 @@ type SettingInfo struct {
|
||||
ExpirationTime string `json:"expirationTime"`
|
||||
ComplexityVerification string `json:"complexityVerification"`
|
||||
MFAStatus string `json:"mfaStatus"`
|
||||
MFASecret string `json:"mfaSecret"`
|
||||
MFAInterval string `json:"mfaInterval"`
|
||||
|
||||
AppStoreVersion string `json:"appStoreVersion"`
|
||||
@@ -226,6 +227,9 @@ type TerminalInfo struct {
|
||||
LineHeight string `json:"lineHeight"`
|
||||
LetterSpacing string `json:"letterSpacing"`
|
||||
FontSize string `json:"fontSize"`
|
||||
FontFamily string `json:"fontFamily"`
|
||||
BackgroundColor string `json:"backgroundColor"`
|
||||
ForegroundColor string `json:"foregroundColor"`
|
||||
CursorBlink string `json:"cursorBlink"`
|
||||
CursorStyle string `json:"cursorStyle"`
|
||||
Scrollback string `json:"scrollback"`
|
||||
|
||||
@@ -2,14 +2,22 @@ package repo
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/core/app/model"
|
||||
"github.com/1Panel-dev/1Panel/core/global"
|
||||
"github.com/1Panel-dev/1Panel/core/init/migration/helper"
|
||||
"github.com/patrickmn/go-cache"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type SettingRepo struct{}
|
||||
|
||||
var (
|
||||
settingCache = cache.New(5*time.Minute, 10*time.Minute)
|
||||
settingTTL = 5 * time.Minute
|
||||
)
|
||||
|
||||
type ISettingRepo interface {
|
||||
List(opts ...global.DBOption) ([]model.Setting, error)
|
||||
Get(opts ...global.DBOption) (model.Setting, error)
|
||||
@@ -39,7 +47,11 @@ func (u *SettingRepo) Create(key, value string) error {
|
||||
Key: key,
|
||||
Value: value,
|
||||
}
|
||||
return global.DB.Create(setting).Error
|
||||
if err := global.DB.Create(setting).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
settingCache.Set(key, value, settingTTL)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *SettingRepo) Get(opts ...global.DBOption) (model.Setting, error) {
|
||||
@@ -48,20 +60,33 @@ func (u *SettingRepo) Get(opts ...global.DBOption) (model.Setting, error) {
|
||||
for _, opt := range opts {
|
||||
db = opt(db)
|
||||
}
|
||||
|
||||
err := db.First(&settings).Error
|
||||
if err == nil && settings.Key != "" {
|
||||
settingCache.Set(settings.Key, settings.Value, settingTTL)
|
||||
}
|
||||
return settings, err
|
||||
}
|
||||
|
||||
func (u *SettingRepo) GetValueByKey(key string) (string, error) {
|
||||
if val, found := settingCache.Get(key); found {
|
||||
return val.(string), nil
|
||||
}
|
||||
|
||||
var setting model.Setting
|
||||
if err := global.DB.Model(&model.Setting{}).Where("key = ?", key).First(&setting).Error; err != nil {
|
||||
return "", err
|
||||
}
|
||||
settingCache.Set(key, setting.Value, settingTTL)
|
||||
return setting.Value, nil
|
||||
}
|
||||
|
||||
func (u *SettingRepo) Update(key, value string) error {
|
||||
return global.DB.Model(&model.Setting{}).Where("key = ?", key).Updates(map[string]interface{}{"value": value}).Error
|
||||
if err := global.DB.Model(&model.Setting{}).Where("key = ?", key).Updates(map[string]interface{}{"value": value}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
settingCache.Set(key, value, settingTTL)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *SettingRepo) UpdateOrCreate(key, value string) error {
|
||||
@@ -69,15 +94,28 @@ func (u *SettingRepo) UpdateOrCreate(key, value string) error {
|
||||
result := global.DB.Where("key = ?", key).First(&setting)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return global.DB.Create(&model.Setting{Key: key, Value: value}).Error
|
||||
if err := global.DB.Create(&model.Setting{Key: key, Value: value}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
settingCache.Set(key, value, settingTTL)
|
||||
return nil
|
||||
}
|
||||
return result.Error
|
||||
}
|
||||
return global.DB.Model(&setting).UpdateColumn("value", value).Error
|
||||
if err := global.DB.Model(&setting).UpdateColumn("value", value).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
settingCache.Set(key, value, settingTTL)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *SettingRepo) DefaultMenu() error {
|
||||
return global.DB.Model(&model.Setting{}).
|
||||
menus := helper.LoadMenus()
|
||||
if err := global.DB.Model(&model.Setting{}).
|
||||
Where("key = ?", "HideMenu").
|
||||
Update("value", helper.LoadMenus()).Error
|
||||
Update("value", menus).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
settingCache.Set("HideMenu", menus, settingTTL)
|
||||
return nil
|
||||
}
|
||||
|
||||
+108
-8
@@ -5,6 +5,7 @@ import (
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
@@ -22,6 +23,7 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/go-webauthn/webauthn/protocol"
|
||||
"github.com/go-webauthn/webauthn/webauthn"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type AuthService struct{}
|
||||
@@ -114,7 +116,7 @@ func (u *AuthService) MFALogin(c *gin.Context, info dto.MFALogin, entrance strin
|
||||
}
|
||||
success := mfa.ValidCode(info.Code, mfaInterval.Value, mfaSecret.Value)
|
||||
if !success {
|
||||
return nil, "ErrAuth", nil
|
||||
return nil, "ErrMFA", nil
|
||||
}
|
||||
res, err := u.generateSession(c, info.Name)
|
||||
if err != nil {
|
||||
@@ -454,13 +456,6 @@ func (u *AuthService) PasskeyDelete(id string) error {
|
||||
}
|
||||
|
||||
func (u *AuthService) passkeyEnabled(c *gin.Context) (bool, error) {
|
||||
sslSetting, err := settingRepo.Get(repo.WithByKey("SSL"))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if sslSetting.Value == constant.StatusDisable {
|
||||
return false, nil
|
||||
}
|
||||
return strings.EqualFold(passkeyRequestScheme(c), "https"), nil
|
||||
}
|
||||
|
||||
@@ -679,9 +674,114 @@ func passkeyRequestScheme(c *gin.Context) string {
|
||||
if c.Request.TLS != nil {
|
||||
return "https"
|
||||
}
|
||||
if !passkeyIsFromTrustedProxy(c) {
|
||||
return "http"
|
||||
}
|
||||
if proto := passkeyForwardedProto(c.GetHeader("Forwarded")); proto != "" {
|
||||
return proto
|
||||
}
|
||||
if proto := passkeyXForwardedProto(c.GetHeader("X-Forwarded-Proto")); proto != "" {
|
||||
return proto
|
||||
}
|
||||
return "http"
|
||||
}
|
||||
|
||||
func passkeyIsFromTrustedProxy(c *gin.Context) bool {
|
||||
remoteIP := passkeyRemoteIP(c.Request.RemoteAddr)
|
||||
if remoteIP == nil {
|
||||
return false
|
||||
}
|
||||
proxies, err := loadPasskeyTrustedProxies()
|
||||
if err != nil {
|
||||
global.LOG.Errorf("load passkey trusted proxies failed, err: %v", err)
|
||||
return false
|
||||
}
|
||||
for _, cidr := range proxies {
|
||||
if cidr.Contains(remoteIP) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func passkeyRemoteIP(remoteAddr string) net.IP {
|
||||
if host, _, err := net.SplitHostPort(strings.TrimSpace(remoteAddr)); err == nil {
|
||||
return net.ParseIP(host)
|
||||
}
|
||||
return net.ParseIP(strings.TrimSpace(remoteAddr))
|
||||
}
|
||||
|
||||
func loadPasskeyTrustedProxies() ([]*net.IPNet, error) {
|
||||
setting, err := settingRepo.Get(repo.WithByKey("PasskeyTrustedProxies"))
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return parsePasskeyTrustedProxies("127.0.0.1\n::1")
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return parsePasskeyTrustedProxies(setting.Value)
|
||||
}
|
||||
|
||||
func parsePasskeyTrustedProxies(value string) ([]*net.IPNet, error) {
|
||||
lines := strings.Split(strings.TrimSpace(value), "\n")
|
||||
if len(lines) == 0 {
|
||||
return []*net.IPNet{}, nil
|
||||
}
|
||||
cidrs := make([]*net.IPNet, 0, len(lines))
|
||||
for _, line := range lines {
|
||||
item := strings.TrimSpace(line)
|
||||
if item == "" {
|
||||
continue
|
||||
}
|
||||
if ip := net.ParseIP(item); ip != nil {
|
||||
if ip.To4() != nil {
|
||||
item += "/32"
|
||||
} else {
|
||||
item += "/128"
|
||||
}
|
||||
}
|
||||
_, ipNet, err := net.ParseCIDR(item)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cidrs = append(cidrs, ipNet)
|
||||
}
|
||||
return cidrs, nil
|
||||
}
|
||||
|
||||
func passkeyForwardedProto(value string) string {
|
||||
if value == "" {
|
||||
return ""
|
||||
}
|
||||
for _, item := range strings.Split(value, ",") {
|
||||
for _, part := range strings.Split(item, ";") {
|
||||
kv := strings.SplitN(strings.TrimSpace(part), "=", 2)
|
||||
if len(kv) != 2 {
|
||||
continue
|
||||
}
|
||||
if !strings.EqualFold(strings.TrimSpace(kv[0]), "proto") {
|
||||
continue
|
||||
}
|
||||
proto := strings.ToLower(strings.Trim(strings.TrimSpace(kv[1]), `"`))
|
||||
if proto == "http" || proto == "https" {
|
||||
return proto
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func passkeyXForwardedProto(value string) string {
|
||||
if value == "" {
|
||||
return ""
|
||||
}
|
||||
proto := strings.ToLower(strings.TrimSpace(strings.Split(value, ",")[0]))
|
||||
if proto == "http" || proto == "https" {
|
||||
return proto
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func stripHostPort(hostport string) string {
|
||||
if hostport == "" {
|
||||
return hostport
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
mathRand "math/rand"
|
||||
"math/big"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
@@ -172,7 +173,17 @@ func StartSync() {
|
||||
service := NewIScriptService()
|
||||
scriptSync, _ := repo.NewISettingRepo().GetValueByKey("ScriptSync")
|
||||
if !global.CONF.Base.IsOffLine && scriptSync == constant.StatusEnable {
|
||||
id, err := global.Cron.AddJob(fmt.Sprintf("%v %v * * *", mathRand.Intn(60), mathRand.Intn(3)), service)
|
||||
minuteRand, err := rand.Int(rand.Reader, big.NewInt(60))
|
||||
if err != nil {
|
||||
global.LOG.Errorf("generate random minute failed: %v", err)
|
||||
minuteRand = big.NewInt(0)
|
||||
}
|
||||
hourRand, err := rand.Int(rand.Reader, big.NewInt(3))
|
||||
if err != nil {
|
||||
global.LOG.Errorf("generate random hour failed: %v", err)
|
||||
hourRand = big.NewInt(0)
|
||||
}
|
||||
id, err := global.Cron.AddJob(fmt.Sprintf("%v %v * * *", minuteRand.Int64(), hourRand.Int64()), service)
|
||||
if err != nil {
|
||||
global.LOG.Errorf("[core] can not add script sync corn job: %s", err.Error())
|
||||
}
|
||||
@@ -201,7 +212,7 @@ func (u *ScriptService) Sync(req dto.OperateByTaskID) error {
|
||||
}
|
||||
|
||||
syncTask.AddSubTask(task.GetTaskName(i18n.GetMsgByKey("RemoteScriptLibrary"), task.TaskSync, task.TaskScopeScript), func(t *task.Task) (err error) {
|
||||
versionUrl := fmt.Sprintf("%s/scripts/version.txt", global.CONF.RemoteURL.ResourceURL)
|
||||
versionUrl := fmt.Sprintf("%s/scripts/version.txt", global.ResourceURL())
|
||||
_, versionRes, err := req_helper.HandleRequestWithProxy(versionUrl, http.MethodGet, constant.TimeOut20s)
|
||||
if err != nil {
|
||||
return fmt.Errorf("load scripts version from remote failed, err: %v", err)
|
||||
@@ -216,7 +227,7 @@ func (u *ScriptService) Sync(req dto.OperateByTaskID) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
dataUrl := fmt.Sprintf("%s/scripts/data.yaml", global.CONF.RemoteURL.ResourceURL)
|
||||
dataUrl := fmt.Sprintf("%s/scripts/data.yaml", global.ResourceURL())
|
||||
_, dataRes, err := req_helper.HandleRequestWithProxy(dataUrl, http.MethodGet, constant.TimeOut20s)
|
||||
syncTask.LogWithStatus(i18n.GetMsgByKey("DownloadData"), err)
|
||||
if err != nil {
|
||||
@@ -232,7 +243,7 @@ func (u *ScriptService) Sync(req dto.OperateByTaskID) error {
|
||||
if _, err := os.Stat(tmpDir); err != nil {
|
||||
_ = os.MkdirAll(tmpDir, 0755)
|
||||
}
|
||||
scriptsUrl := fmt.Sprintf("%s/scripts/scripts.tar.gz", global.CONF.RemoteURL.ResourceURL)
|
||||
scriptsUrl := fmt.Sprintf("%s/scripts/scripts.tar.gz", global.ResourceURL())
|
||||
err = files.DownloadFileWithProxyStream(scriptsUrl, tmpDir+"/scripts.tar.gz")
|
||||
syncTask.LogWithStatus(i18n.GetMsgByKey("DownloadPackage"), err)
|
||||
if err != nil {
|
||||
|
||||
+52
-28
@@ -16,6 +16,7 @@ import (
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -61,8 +62,6 @@ type ISettingService interface {
|
||||
UpdateSystemSSL() error
|
||||
GenerateRSAKey() error
|
||||
|
||||
GetLoginSetting() (*dto.SystemSetting, error)
|
||||
|
||||
UpdateAppstoreConfig(req dto.AppstoreUpdate) error
|
||||
GetAppstoreConfig() (*dto.AppstoreConfig, error)
|
||||
DefaultMenu() error
|
||||
@@ -84,6 +83,15 @@ func (u *SettingService) GetSettingInfo() (*dto.SettingInfo, error) {
|
||||
for _, set := range setting {
|
||||
settingMap[set.Key] = set.Value
|
||||
}
|
||||
if hideMenu, ok := settingMap["HideMenu"]; ok && len(hideMenu) > 0 {
|
||||
var menus []dto.ShowMenu
|
||||
if err := json.Unmarshal([]byte(hideMenu), &menus); err == nil {
|
||||
sortShowMenus(menus)
|
||||
if sortedBytes, err := json.Marshal(menus); err == nil {
|
||||
settingMap["HideMenu"] = string(sortedBytes)
|
||||
}
|
||||
}
|
||||
}
|
||||
var info dto.SettingInfo
|
||||
arr, err := json.Marshal(settingMap)
|
||||
if err != nil {
|
||||
@@ -92,6 +100,10 @@ func (u *SettingService) GetSettingInfo() (*dto.SettingInfo, error) {
|
||||
if err := json.Unmarshal(arr, &info); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if info.Edition == "" {
|
||||
info.Edition = "cn"
|
||||
_ = settingRepo.UpdateOrCreate("Edition", info.Edition)
|
||||
}
|
||||
if info.ProxyPasswdKeep != constant.StatusEnable {
|
||||
info.ProxyPasswd = ""
|
||||
} else {
|
||||
@@ -101,6 +113,20 @@ func (u *SettingService) GetSettingInfo() (*dto.SettingInfo, error) {
|
||||
return &info, err
|
||||
}
|
||||
|
||||
func sortShowMenus(menus []dto.ShowMenu) {
|
||||
for i := range menus {
|
||||
if len(menus[i].Children) > 0 {
|
||||
sortShowMenus(menus[i].Children)
|
||||
}
|
||||
}
|
||||
sort.SliceStable(menus, func(i, j int) bool {
|
||||
if menus[i].Sort == menus[j].Sort {
|
||||
return menus[i].ID < menus[j].ID
|
||||
}
|
||||
return menus[i].Sort < menus[j].Sort
|
||||
})
|
||||
}
|
||||
|
||||
func (u *SettingService) Update(key, value string) error {
|
||||
oldVal, err := settingRepo.Get(repo.WithByKey(key))
|
||||
if err != nil {
|
||||
@@ -168,6 +194,11 @@ func (u *SettingService) Update(key, value string) error {
|
||||
} else {
|
||||
global.Cron.Remove(global.ScriptSyncJobID)
|
||||
}
|
||||
case "Edition":
|
||||
global.CONF.Base.Edition = value
|
||||
if err := xpack.Sync(constant.SyncEdition); err != nil {
|
||||
global.LOG.Errorf("sync edition to node failed, err: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -283,9 +314,6 @@ func (u *SettingService) UpdateSSL(c *gin.Context, req dto.SSLUpdate) error {
|
||||
if err := settingRepo.Update("SSLType", "self"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := u.clearPasskeySettings(); err != nil {
|
||||
return err
|
||||
}
|
||||
_ = os.Remove(path.Join(secretDir, "server.crt"))
|
||||
_ = os.Remove(path.Join(secretDir, "server.key"))
|
||||
go func() {
|
||||
@@ -391,9 +419,6 @@ func (u *SettingService) UpdateSSL(c *gin.Context, req dto.SSLUpdate) error {
|
||||
if err := settingRepo.Update("SSL", req.SSL); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := u.clearPasskeySettings(); err != nil {
|
||||
return err
|
||||
}
|
||||
return u.UpdateSystemSSL()
|
||||
}
|
||||
|
||||
@@ -500,25 +525,37 @@ func (u *SettingService) GetTerminalInfo() (*dto.TerminalInfo, error) {
|
||||
return &info, err
|
||||
}
|
||||
func (u *SettingService) UpdateTerminal(req dto.TerminalInfo) error {
|
||||
if err := settingRepo.Update("LineHeight", req.LineHeight); err != nil {
|
||||
if err := settingRepo.UpdateOrCreate("LineHeight", req.LineHeight); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := settingRepo.Update("LetterSpacing", req.LetterSpacing); err != nil {
|
||||
if err := settingRepo.UpdateOrCreate("LetterSpacing", req.LetterSpacing); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := settingRepo.Update("FontSize", req.FontSize); err != nil {
|
||||
if err := settingRepo.UpdateOrCreate("FontSize", req.FontSize); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := settingRepo.Update("CursorBlink", req.CursorBlink); err != nil {
|
||||
if err := settingRepo.UpdateOrCreate("FontFamily", req.FontFamily); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := settingRepo.Update("CursorStyle", req.CursorStyle); err != nil {
|
||||
if err := settingRepo.UpdateOrCreate("CursorBlink", req.CursorBlink); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := settingRepo.Update("Scrollback", req.Scrollback); err != nil {
|
||||
if err := settingRepo.UpdateOrCreate("BackgroundColor", req.BackgroundColor); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := settingRepo.Update("ScrollSensitivity", req.ScrollSensitivity); err != nil {
|
||||
if err := settingRepo.UpdateOrCreate("ForegroundColor", req.ForegroundColor); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := settingRepo.UpdateOrCreate("CursorBlink", req.CursorBlink); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := settingRepo.UpdateOrCreate("CursorStyle", req.CursorStyle); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := settingRepo.UpdateOrCreate("Scrollback", req.Scrollback); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := settingRepo.UpdateOrCreate("ScrollSensitivity", req.ScrollSensitivity); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -673,19 +710,6 @@ func (u *SettingService) GenerateRSAKey() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *SettingService) GetLoginSetting() (*dto.SystemSetting, error) {
|
||||
settingInfo, err := u.GetSettingInfo()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res := &dto.SystemSetting{
|
||||
Language: settingInfo.Language,
|
||||
IsDemo: global.CONF.Base.IsDemo,
|
||||
IsIntl: global.CONF.Base.IsIntl,
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (u *SettingService) UpdateAppstoreConfig(req dto.AppstoreUpdate) error {
|
||||
return settingRepo.UpdateOrCreate(req.Scope, req.Status)
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ func (u *UpgradeService) SearchUpgrade() (*dto.UpgradeInfo, error) {
|
||||
if strings.HasPrefix(upgrade.TestVersion, upgrade.LatestVersion+"-beta") {
|
||||
upgrade.TestVersion = ""
|
||||
}
|
||||
notes, err := u.loadReleaseNotes(fmt.Sprintf("%s/%s/%s/release/1panel-%s-release-notes", global.CONF.RemoteURL.RepoUrl, mode, itemVersion, itemVersion))
|
||||
notes, err := u.loadReleaseNotes(fmt.Sprintf("%s/%s/%s/release/1panel-%s-release-notes", global.RepoURL(), mode, itemVersion, itemVersion))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("load releases-notes of version %s failed, err: %v", itemVersion, err)
|
||||
}
|
||||
@@ -130,7 +130,7 @@ func (u *UpgradeService) LoadNotes(req dto.Upgrade) (string, error) {
|
||||
if strings.Contains(req.Version, "beta") {
|
||||
mode = "beta"
|
||||
}
|
||||
notes, err := u.loadReleaseNotes(fmt.Sprintf("%s/%s/%s/release/1panel-%s-release-notes", global.CONF.RemoteURL.RepoUrl, mode, req.Version, req.Version))
|
||||
notes, err := u.loadReleaseNotes(fmt.Sprintf("%s/%s/%s/release/1panel-%s-release-notes", global.RepoURL(), mode, req.Version, req.Version))
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("load releases-notes of version %s failed, err: %v", req.Version, err)
|
||||
}
|
||||
@@ -162,7 +162,7 @@ func (u *UpgradeService) Upgrade(req dto.Upgrade) error {
|
||||
if strings.Contains(req.Version, "beta") {
|
||||
mode = "beta"
|
||||
}
|
||||
downloadPath := fmt.Sprintf("%s/%s/%s/release", global.CONF.RemoteURL.RepoUrl, mode, req.Version)
|
||||
downloadPath := fmt.Sprintf("%s/%s/%s/release", global.RepoURL(), mode, req.Version)
|
||||
fileName := fmt.Sprintf("1panel-%s-%s-%s.tar.gz", req.Version, "linux", itemArch)
|
||||
_ = settingRepo.Update("SystemStatus", "Upgrading")
|
||||
go func() {
|
||||
@@ -287,7 +287,11 @@ type noteDetailHelper struct {
|
||||
|
||||
func (u *UpgradeService) LoadRelease() ([]dto.ReleasesNotes, error) {
|
||||
var notes []dto.ReleasesNotes
|
||||
resp, err := req_helper.HandleGet("https://1panel.cn/docs/v2/search/search_index.json")
|
||||
url := "https://docs.1panel.pro/v2/search/search_index.json"
|
||||
if global.CONF.Base.Edition != "intl" {
|
||||
url = "https://1panel.cn/docs/v2/search/search_index.json"
|
||||
}
|
||||
resp, err := req_helper.HandleGet(url)
|
||||
if err != nil {
|
||||
return notes, err
|
||||
}
|
||||
@@ -321,13 +325,13 @@ func analyzeDoc(version, content string) dto.ReleasesNotes {
|
||||
}
|
||||
item.CreatedAt = strings.ReplaceAll(strings.TrimSpace(parts[1]), "</p>", "")
|
||||
for i := 1; i < len(parts); i++ {
|
||||
if strings.Contains(parts[i], "问题修复") {
|
||||
if strings.Contains(parts[i], "问题修复") || strings.Contains(parts[i], "Bug Fixes") {
|
||||
item.FixCount = strings.Count(parts[i], "<li>")
|
||||
}
|
||||
if strings.Contains(parts[i], "新增功能") {
|
||||
if strings.Contains(parts[i], "新增功能") || strings.Contains(parts[i], "New Features") {
|
||||
item.NewCount = strings.Count(parts[i], "<li>")
|
||||
}
|
||||
if strings.Contains(parts[i], "功能优化") {
|
||||
if strings.Contains(parts[i], "功能优化") || strings.Contains(parts[i], "Improvements") {
|
||||
item.OptimizationCount = strings.Count(parts[i], "<li>")
|
||||
}
|
||||
}
|
||||
@@ -442,9 +446,9 @@ func (u *UpgradeService) loadVersionByMode(developer, currentVersion string) (st
|
||||
}
|
||||
|
||||
func (u *UpgradeService) loadVersion(isLatest bool, currentVersion, mode string) string {
|
||||
path := fmt.Sprintf("%s/%s/latest", global.CONF.RemoteURL.RepoUrl, mode)
|
||||
path := fmt.Sprintf("%s/%s/latest", global.RepoURL(), mode)
|
||||
if !isLatest {
|
||||
path = fmt.Sprintf("%s/%s/latest.current", global.CONF.RemoteURL.RepoUrl, mode)
|
||||
path = fmt.Sprintf("%s/%s/latest.current", global.RepoURL(), mode)
|
||||
}
|
||||
_, latestVersionRes, err := req_helper.HandleRequestWithProxy(path, http.MethodGet, constant.TimeOut20s)
|
||||
if err != nil {
|
||||
|
||||
@@ -62,7 +62,10 @@ var resetSSLCmd = &cobra.Command{
|
||||
return err
|
||||
}
|
||||
|
||||
return setSettingByKey(db, "SSL", constant.StatusDisable)
|
||||
if err := setSettingByKey(db, "SSL", constant.StatusDisable); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
var resetEntranceCmd = &cobra.Command{
|
||||
@@ -94,7 +97,10 @@ var resetBindIpsCmd = &cobra.Command{
|
||||
return err
|
||||
}
|
||||
|
||||
return setSettingByKey(db, "AllowIPs", "")
|
||||
if err := setSettingByKey(db, "AllowIPs", ""); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
var resetDomainCmd = &cobra.Command{
|
||||
@@ -110,7 +116,10 @@ var resetDomainCmd = &cobra.Command{
|
||||
return err
|
||||
}
|
||||
|
||||
return setSettingByKey(db, "BindDomain", "")
|
||||
if err := setSettingByKey(db, "BindDomain", ""); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -92,9 +92,16 @@ var restoreCmd = &cobra.Command{
|
||||
fmt.Println(i18n.GetMsgByKeyForCmd("RestoreStep4"))
|
||||
if _, err := os.Stat(path.Join(tmpPath, "db")); err == nil {
|
||||
dbPath := path.Join(baseDir, "1panel")
|
||||
targetDBDir := path.Join(dbPath, "db")
|
||||
if err := os.RemoveAll(targetDBDir); err != nil {
|
||||
global.LOG.Errorf("rollback 1panel db cleanup failed, err: %v", err)
|
||||
}
|
||||
if err := files.CopyItem(true, true, path.Join(tmpPath, "db"), dbPath); err != nil {
|
||||
global.LOG.Errorf("rollback 1panel db failed, err: %v", err)
|
||||
}
|
||||
if err := cleanOrphanSQLiteSidecars(targetDBDir); err != nil {
|
||||
global.LOG.Errorf("rollback 1panel db sidecar cleanup failed, err: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println(i18n.GetMsgByKeyForCmd("RestoreStep5"))
|
||||
@@ -140,3 +147,41 @@ func loadRollbackVersion(upgradeDir string) string {
|
||||
}
|
||||
return info
|
||||
}
|
||||
|
||||
func cleanOrphanSQLiteSidecars(dbDir string) error {
|
||||
entries, err := os.ReadDir(dbDir)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
for _, entry := range entries {
|
||||
if entry.IsDir() {
|
||||
continue
|
||||
}
|
||||
|
||||
name := entry.Name()
|
||||
var mainDB string
|
||||
switch {
|
||||
case strings.HasSuffix(name, ".db-wal"):
|
||||
mainDB = strings.TrimSuffix(name, "-wal")
|
||||
case strings.HasSuffix(name, ".db-shm"):
|
||||
mainDB = strings.TrimSuffix(name, "-shm")
|
||||
default:
|
||||
continue
|
||||
}
|
||||
|
||||
if _, statErr := os.Stat(path.Join(dbDir, mainDB)); statErr != nil {
|
||||
if !os.IsNotExist(statErr) {
|
||||
return statErr
|
||||
}
|
||||
if removeErr := os.Remove(path.Join(dbDir, name)); removeErr != nil && !os.IsNotExist(removeErr) {
|
||||
return removeErr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -258,7 +258,7 @@ func isValidPassword(password string) bool {
|
||||
}
|
||||
}
|
||||
|
||||
if len(password) < 8 && len(password) > 30 {
|
||||
if len(password) < 8 || len(password) > 30 {
|
||||
return false
|
||||
}
|
||||
if (numCount == 0 && alphaCount == 0) || (alphaCount == 0 && specialCount == 0) || (numCount == 0 && specialCount == 0) {
|
||||
|
||||
@@ -2,7 +2,6 @@ base:
|
||||
install_dir: /opt
|
||||
mode: dev
|
||||
is_demo: false
|
||||
is_intl: false
|
||||
is_offline: false
|
||||
is_fxplay: false
|
||||
port: 9999
|
||||
@@ -10,11 +9,6 @@ base:
|
||||
password: admin123
|
||||
version: v2.0.0
|
||||
|
||||
remote_url:
|
||||
app_repo: https://apps-assets.fit2cloud.com
|
||||
repo_url: https://resource.fit2cloud.com/1panel/package/v2
|
||||
resource_url: https://resource.fit2cloud.com/1panel/resource/v2
|
||||
|
||||
log:
|
||||
level: debug
|
||||
time_zone: Asia/Shanghai
|
||||
|
||||
+2323
-62
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user