Compare commits

...
93 Commits
Author SHA1 Message Date
王贺 c986b04667 Update installation script URL in README (#12065) 2026-03-04 18:11:06 +08:00
CityFun 754e016f20 feat: Optimize the Ollama configuration workflow (#12063) 2026-03-04 08:39:03 +00:00
ssongliu f67ce75492 fix: update hook initialization handling (#12062) 2026-03-04 16:38:59 +08:00
ssongliu e236ca5607 fix(swagger): correct api annotation types and methods (#12060) 2026-03-04 07:13:02 +00:00
CityFun 10e74c4fe4 feat: add agent analytics req (#12059) 2026-03-04 07:01:03 +00:00
MoeShin 473c0a5ff2 chore: optimize website proxy api and log (#12052) 2026-03-04 14:35:05 +08:00
ssongliu 7fbe6e4091 fix(auth): update 1panel token hash validation (#12056) 2026-03-04 14:30:17 +08:00
ssongliu 65dbb53a07 fix(terminal): remove command completion protocol (#12055) 2026-03-04 06:25:05 +00:00
KOMATA c21910c203 feat: enhance container compose view with additional status indicators and environment configuration options (#12042)
- Added visual indicators for container status and creation date.
- Introduced a new radio button for environment configuration alongside existing options.
- Improved layout and styling for better user experience.
- Adjusted table column widths and added a class for styling.
2026-03-03 18:31:47 +08:00
CityFun 1728511bad feat: update kimi-coding logic (#12049) 2026-03-03 09:32:03 +00:00
ssongliu e63f6672f8 fix: persist terminal font settings (#12047) 2026-03-03 09:30:03 +00:00
ssongliu 7fa9754ce7 refine passkey prerequisite checks and i18n guidance 2026-03-03 17:08:06 +08:00
王贺 475e4ca629 ci: configure Go dependency cache (#12046)
Add cache dependency path for Go setup
2026-03-03 16:04:26 +08:00
ssongliu 32dee74edf fix: update intl domain links to 1panel.pro (#12045) 2026-03-03 07:20:02 +00:00
CityFun 6715559925 feat: support z.ai agent account (#12044) 2026-03-03 15:18:24 +08:00
KOMATA 2f380c9f2f feat: enhance app synchronization with concurrent processing and detailed result handling (#12041)
- Introduced concurrent processing for app synchronization tasks to improve performance.
- Added structures for managing app work items and results.
- Implemented detailed logging of synchronization progress and HTTP request outcomes.
- Enhanced error handling for icon downloads and app details updates.
2026-03-03 13:46:22 +08:00
CityFun 0aebb0d2db [Feature] Add App Store status check on the Agent page (#12039) 2026-03-03 12:02:42 +08:00
CityFun b7cf9aab2b feat(ai-agents): support ollama apiType selection (#12037) 2026-03-03 11:57:17 +08:00
Rowan Chen ea2f1875bc fix: disable favorite toggle during sort mode and fix drag rebound issue (#12026)
* Optimize sorting-related issues, disable the "favorite stars" function during sorting, and optimize sorting behavior caused by DOM conflicts.

* fix: prevent app icon from being squished in detail drawer
2026-03-03 11:06:53 +08:00
KOMATA 83524940ed refactor: remove unused pprof import from main.go (#12031) 2026-03-03 11:05:26 +08:00
MoeShin 8c33eb8409 feat: Operate website proxy config (#12005)
* feat: Operate website proxy config

* chore: Update api comment

* chore: update swagger

* chore: update x-log

* feat: split api
2026-03-03 11:05:00 +08:00
ssongliu 644655af86 feat: add extra_hosts support for container config (#12035)
Related: https://github.com/1Panel-dev/1Panel/issues/11861
2026-03-03 03:02:02 +00:00
CityFun 8082f4d2ca fix(ai-agents): mark skipped-verification accounts as unverified and normalize legacy status (#12034) 2026-03-03 11:00:53 +08:00
ssongliu 3c896bc5f8 fix: improve MFA interval compatibility i18n hints (#12033)
Related: https://github.com/1Panel-dev/1Panel/issues/11915
2026-03-03 03:00:02 +00:00
ssongliu 5c7ce6d8d4 fix: add PostgreSQL recreation and DB host env sync in app restore (#12029) 2026-03-03 02:58:01 +00:00
CityFun 222702f66b feat(ai-agents): Add ark coding plan for agent account (#12027) 2026-03-02 22:04:57 +08:00
ssongliu b3b3feb1b9 feat: improve container log viewer and download options (#12025)
#11898
2026-03-02 14:04:02 +00:00
ssongliu 133140040b fix: store loadingText as key and localize on render (#12022) 2026-03-02 10:32:01 +00:00
ssongliu d70f903432 fix: hide upage for intl and reload after edition switch (#12021) 2026-03-02 10:30:00 +00:00
CityFun f77f305316 feat(ai-agents): add time zone config for openclaw (#12020) 2026-03-02 10:28:01 +00:00
ssongliu 13b5908442 fix: handle sqlite wal/shm mismatch during restore (#12024) 2026-03-02 18:27:38 +08:00
CityFun d1335db986 fix(ai-agents): fixed issue with minimax-m2.5 is not work for bailian-coding-plan (#12023) 2026-03-02 18:27:25 +08:00
KOMATA 1e8836ad95 feat: add passkey prerequisites messages and update passkey settings UI (#12018)
* feat: add passkey prerequisites messages and update passkey settings UI

* refactor: enhance passkey settings UI by restructuring alert component and adding prerequisite checks
2026-03-02 16:05:55 +08:00
CityFun d155217ce3 feat(ai-agents): Add copaw type for agent (#12017) 2026-03-02 06:53:58 +00:00
ssongliu 9ddb996a44 fix: fix menu sort mismatch between load and migration (#12016) 2026-03-02 06:25:58 +00:00
ssongliu 226eccf5f1 fix: fix terminal extra line after settings change (#12015) 2026-03-02 06:24:00 +00:00
CityFun 4b2d6f0ef2 feat(ai-agents): add bailian-coding-plan account support (#12014) 2026-03-02 14:22:09 +08:00
蘭 f1c9ad45a7 feat: Improve file decompression processing (#12012) 2026-03-02 05:53:58 +00:00
KOMATA 93489c85fa feat: Enhance compose item interaction and styling (#12008)
- Updated the compose item to include a new class for active state, improving visual feedback.
- Refactored action buttons into a dedicated container for better organization and hover effects.
- Added CSS transitions for smoother interactions on hover and active states.
2026-03-02 13:43:34 +08:00
CityFun 8cead06d7b feat(ai-agents): add anthropic-messages support for custom account apiType (#12013) 2026-03-02 13:43:06 +08:00
ssongliu 625cd9f32f chore: update installation package path (#12009) 2026-03-02 04:05:59 +00:00
dependabot[bot] 9aab3b42af chore(deps): bump go.opentelemetry.io/otel/sdk in /agent (#12010)
Bumps [go.opentelemetry.io/otel/sdk](https://github.com/open-telemetry/opentelemetry-go) from 1.38.0 to 1.40.0.
- [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.38.0...v1.40.0)

---
updated-dependencies:
- dependency-name: go.opentelemetry.io/otel/sdk
  dependency-version: 1.40.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-02 12:04:30 +08:00
A_Words 6684cd57d7 fix: open compressed files in decompress drawer and improve archive detection (#11997) 2026-03-02 11:29:19 +08:00
A_Words 00d95d6e19 fix(mkdown-editor): avoid pre-sanitizing markdown source (#11998) (#12004) 2026-03-02 10:54:25 +08:00
ssongliu 36f03e5daf chore: refine partial i18n copy (#11992) 2026-02-28 15:01:54 +00:00
ssongliu 7c395a6bf8 fix: resolve GPU menu selected state style issue 2026-02-28 18:58:18 +08:00
zhengkunwang223 e9a7cac5fd fix(frontend): change table style 2026-02-28 18:58:06 +08:00
zhengkunwang223 9f00b431d4 fix(frontend): stabilize installed app card name truncation 2026-02-28 18:35:34 +08:00
maninhill 1705d44378 Update README.md 2026-02-28 17:54:03 +08:00
CityFun 537e2c730c feat: preserve Feishu account map on config updates (#11990) 2026-02-28 09:19:52 +00:00
ssongliu b4dc6b1ab0 chore: optimize runtime region description (#11989) 2026-02-28 09:17:53 +00:00
CityFun 1f22285cf4 chore: refine other language i18n wording (#11988) 2026-02-28 16:41:28 +08:00
A_Words 1d546236e4 fix: restore subsite nginx config on start to avoid stale stop page (#11978) 2026-02-28 15:25:18 +08:00
Kadxy 982e0bbd3e feat: add copy connection URL button to database connection info drawers (#11981)
Add a copy connection URL button to the MySQL, PostgreSQL, and Redis connection info drawers, allowing users to one-click copy the full connection URI for both container and remote connections.
2026-02-28 15:13:58 +08:00
CityFun 5a67a62733 chore: refine en and zh-Hant i18n wording (#11987) 2026-02-28 07:11:52 +00:00
ssongliu 961ebd30a1 fix: resolve overseas script repository sync failure (#11985) 2026-02-28 10:38:35 +08:00
ssongliu 9819546694 chore: optimize internationalization content (#11980) 2026-02-27 14:57:50 +00:00
ssongliu 5c8d391a73 fix: resolve partial application restore failure (#11979)
Refs #11716
2026-02-27 14:43:50 +00:00
CityFun 0e84b9a2a7 feat: fix error after deleting website deployed via deployment for "openclaw" (#11975) 2026-02-27 17:54:19 +08:00
王贺 1f58da501e ci: update build workflow (#11976) 2026-02-27 17:53:52 +08:00
ssongliu 0041184a3e fix: resolve version synchronization issue (#11971) 2026-02-27 07:17:51 +00:00
ssongliu 112468949d feat: Update sqlite connection settings (#11969) 2026-02-27 15:16:59 +08:00
KOMATA 7e03e94460 chore: remove stylelint configuration and ignore files, update lint-staged for stylelint removal (#11968) 2026-02-27 15:08:37 +08:00
ssongliu fd9b299b14 chore: update Edition key (#11962) 2026-02-26 10:05:46 +00:00
ssongliu 37932d7fb2 chore: Complete system security upgrade (#11961) 2026-02-26 10:01:47 +00:00
CityFun f0f2087f54 feat: add browser config for Agent (#11958) 2026-02-26 09:59:48 +00:00
CityFun f3de09e5d7 feat: Add discord channel for Agent (#11950) 2026-02-25 13:59:46 +00:00
maninhill 1a8c1613a4 Update README to eliminate redundant text
Removed duplicate description of 1Panel.
2026-02-25 16:56:40 +08:00
KOMATA 5209275f28 feat: Implement caching for settings retrieval and update logic (#11886)
* feat: Implement caching for settings retrieval and update logic

- Introduced a caching mechanism for settings using go-cache to improve performance.
- Updated the Create, Update, and UpdateOrCreate methods to cache values after database operations.
- Modified the Get and GetValueByKey methods to utilize the cache for faster access.
- Adjusted middleware to use the new GetValueByKey method for retrieving settings, enhancing code consistency.

* feat: Enhance setting cache management with dynamic TTL

- Introduced a function to determine cache TTL based on setting keys, allowing critical settings to have shorter cache durations.
- Updated cache logic in Create, Update, Get, and GetValueByKey methods to utilize the new TTL management, improving performance and consistency in settings retrieval.

* refactor: Simplify setting cache TTL management

- Removed the dynamic TTL function and standardized the cache TTL to a fixed duration for all settings.
- Updated cache logic in Create, Update, Get, and GetValueByKey methods to use the new fixed TTL, enhancing code clarity and maintainability.
- Added a new function to restart the core service after resetting settings, improving the reset command's functionality.

* refactor: Remove core restart functionality from reset commands

- Eliminated the restartCoreAfterReset function to simplify the reset command logic.
- Updated reset commands to return nil after setting changes, enhancing clarity and reducing unnecessary complexity.
2026-02-25 16:40:20 +08:00
ssongliu 924e59d948 fix: Fix login log recording abnormality in some scenarios (#11948) 2026-02-25 08:39:46 +00:00
CityFun 87a39cab3a feat: Add telegram channel for Agent (#11947) 2026-02-25 16:38:34 +08:00
CityFun f9a70757a1 feat: add rememberApiKey for AgentAccount (#11945) 2026-02-25 05:53:45 +00:00
ssongliu 741acee393 fix: Modify command invocation method (#11944) 2026-02-25 05:51:44 +00:00
dependabot[bot] c964a02088 chore(deps): bump filippo.io/edwards25519 from 1.1.0 to 1.1.1 in /agent (#11946)
Bumps [filippo.io/edwards25519](https://github.com/FiloSottile/edwards25519) from 1.1.0 to 1.1.1.
- [Commits](https://github.com/FiloSottile/edwards25519/compare/v1.1.0...v1.1.1)

---
updated-dependencies:
- dependency-name: filippo.io/edwards25519
  dependency-version: 1.1.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-25 11:58:33 +08:00
ssongliu ba71613ae6 fix: Fix docker compose parsing failure issue (#11942)
Refs #11934
2026-02-25 03:51:44 +00:00
ssongliu 5493b41381 fix: Modify monitoring interval prompt information (#11940)
Refs #11918
2026-02-25 02:57:47 +00:00
ssongliu c3f45d4787 feat: v2 supports international version (#11939) 2026-02-25 10:56:06 +08:00
rowanchen-com a8a92da483 Added the ability to sort installed applications. (#11936) 2026-02-25 10:35:29 +08:00
CityFun a77e61a861 feat: Agent Model Account support custom config (#11933)
* feat: Agent Model Account support custom config

* feat: Add agent gatewayControlUi config
2026-02-24 18:26:02 +08:00
kgbow e589728987 refactor(website-ssl): improve API flexibility for WebsiteSSLSearch validation (#11926) 2026-02-24 17:30:37 +08:00
maninhill cc3cdef5f3 Revise 1Panel description and add feature highlights
Updated the description of 1Panel to clarify its purpose and features.
2026-02-24 17:28:14 +08:00
A_Words 7101af0594 fix: Allow wildcard domains in domainOrIP validator for SSL form (#11923) 2026-02-24 17:22:30 +08:00
KOMATA df6cda7143 chore: change esbuild to native version (#11904)
* chore: change esbuild to native version

* chore: add @parcel/watcher and esbuild to trustedDependencies
2026-02-24 17:21:20 +08:00
KOMATA 62beb534d2 feat: enhance passkey function 2026-02-24 17:19:13 +08:00
adriandadri 9a70bf1c2d feat: Add support for Technitium DNS (#11896)
Co-authored-by: adri <adri@digitalunited.net>
2026-02-24 17:13:59 +08:00
KOMATA 6f4559c7cd style: Update Prettier configuration and adjust SCSS formatting (#11885)
- Added iconfont directory to .prettierignore
- Removed jsxBracketSameLine option from .prettierrc.js
- Fixed indentation in common.scss and reset.scss files
2026-02-24 17:03:20 +08:00
KOMATA 8b2bcdc814 feat: Enhance domain handling in website creation (#11884)
* feat: Enhance domain handling in website creation

* fix: Improve domain trimming and validation in website alias assignment
2026-02-24 16:58:30 +08:00
maninhill 0f6ddf26fd Refine README.md content for conciseness
Removed redundant phrases for clarity.
2026-02-24 14:11:31 +08:00
王贺 ebe472a9db feat(i18n): refine translations (#11931) 2026-02-24 13:42:10 +08:00
ssongliu c1a87baad7 feat: Terminal supports foreground and background colors (#11929) 2026-02-24 13:39:02 +08:00
Scars c7f185a184 feat: Terminal supports custom fonts (#11889) 2026-02-13 18:15:12 +08:00
蘭 4ca2ba5482 feat: File editing supports last opened file (#11893)
#11572
2026-02-13 10:01:14 +00:00
蘭 727b74895d ref: Adjust the column widths of the file system (#11887)
#11699
2026-02-13 09:59:13 +00:00
257 changed files with 15054 additions and 6363 deletions
@@ -1,33 +1,43 @@
name: Create Release And Upload Cloudflare R2 name: Build And Publish (OSS + R2)
on: on:
push: push:
tags: tags:
- 'v*' - 'v*'
jobs: jobs:
create-release: create-release:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout Code - name: Checkout Code
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v4 uses: actions/setup-node@v4
with: with:
node-version: '22.19.0' node-version: '22.19.0'
- name: Build Web - name: Build Web
run: | run: |
cd frontend && npm install && npm run build:pro cd frontend && npm install && npm run build:pro
env: env:
NODE_OPTIONS: --max-old-space-size=8192 NODE_OPTIONS: --max-old-space-size=8192
- name: Setup Go - name: Setup Go
uses: actions/setup-go@v5 uses: actions/setup-go@v5
with: with:
go-version: '1.24' go-version: '1.24'
cache-dependency-path: |
core/go.sum
agent/go.sum
- name: Build Release - name: Build Release
uses: goreleaser/goreleaser-action@v6 uses: goreleaser/goreleaser-action@v6
with: with:
distribution: goreleaser distribution: goreleaser
version: '~> v2' version: '~> v2'
args: release --skip=publish --clean args: release --skip=publish --clean
- name: Upload Assets - name: Upload Assets
uses: softprops/action-gh-release@v1 uses: softprops/action-gh-release@v1
if: startsWith(github.ref, 'refs/tags/') if: startsWith(github.ref, 'refs/tags/')
@@ -36,10 +46,24 @@ jobs:
files: | files: |
dist/*.tar.gz dist/*.tar.gz
dist/checksums.txt 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 - name: Setup Rclone
uses: AnimMouse/setup-rclone@v1 uses: AnimMouse/setup-rclone@v1
with: with:
rclone_config: ${{ secrets.RCLONE_CONFIG }} rclone_config: ${{ secrets.RCLONE_CONFIG }}
- name: Upload to Cloudflare R2 - name: Upload to Cloudflare R2
run: | run: |
rclone copy dist/ cloudflare_r2:package/v2/stable/${{ github.ref_name }}/release/ --include "*.tar.gz" --include "checksums.txt" --progress 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
+9 -19
View File
@@ -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> <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"> <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> <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> </p>
@@ -31,34 +32,23 @@
------------------------------ ------------------------------
## What is 1Panel? ## 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 ## Key Features
🔹 **AI Integration** - **One-Click OpenClaw Deployment**: Seamlessly deploy OpenClaw agents, host local LLMs using Ollama, and monitor GPU utilization—all within a unified workspace.  
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 (Nextcloud, Bitwarden, Umami, and more) with a single click.  
🔹 **One-Click Website Deployment** - **Centralized Server Management**: Monitor system resources and manage files, databases, containers, and services effortlessly through a unified, intuitive dashboard.  
Launch production-ready websites instantly with automatic domain binding, SSL certificate provisioning, and configuration—zero manual setup required. - **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.  
🔹 **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.
## Quick Start ## Quick Start
Execute the script below and follow the prompts to install 1Panel: Execute the script below and follow the prompts to install 1Panel:
```bash ```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 ## Screenshot
+185 -1
View File
@@ -113,7 +113,7 @@ func (b *BaseApi) UpdateAgentModelConfig(c *gin.Context) {
// @Tags AI // @Tags AI
// @Summary Get Providers // @Summary Get Providers
// @Success 200 {object} []dto.ProviderInfo // @Success 200 {array} dto.ProviderInfo
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Security Timestamp // @Security Timestamp
// @Router /ai/agents/providers [get] // @Router /ai/agents/providers [get]
@@ -271,6 +271,170 @@ func (b *BaseApi) UpdateAgentFeishuConfig(c *gin.Context) {
helper.Success(c) 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 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 // @Tags AI
// @Summary Approve Agent Feishu pairing code // @Summary Approve Agent Feishu pairing code
// @Accept json // @Accept json
@@ -290,3 +454,23 @@ func (b *BaseApi) ApproveAgentFeishuPairing(c *gin.Context) {
} }
helper.Success(c) 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)
}
+13 -1
View File
@@ -109,7 +109,7 @@ func (b *BaseApi) LoadPort(c *gin.Context) {
// @Success 200 {object} response.DatabaseConn // @Success 200 {object} response.DatabaseConn
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Security Timestamp // @Security Timestamp
// @Router /apps/installed/conninfo [POST] // @Router /apps/installed/conninfo [post]
func (b *BaseApi) LoadConnInfo(c *gin.Context) { func (b *BaseApi) LoadConnInfo(c *gin.Context) {
var req dto.OperationWithNameAndType var req dto.OperationWithNameAndType
if err := helper.CheckBindAndValidate(&req, c); err != nil { if err := helper.CheckBindAndValidate(&req, c); err != nil {
@@ -349,3 +349,15 @@ func (b *BaseApi) GetAppInstallInfo(c *gin.Context) {
} }
helper.SuccessWithData(c, info) 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)
}
-21
View File
@@ -306,27 +306,6 @@ func (b *BaseApi) ContainerCreate(c *gin.Context) {
helper.Success(c) 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 // @Tags Container
// @Summary Upgrade container // @Summary Upgrade container
// @Accept json // @Accept json
+2 -2
View File
@@ -12,7 +12,7 @@ import (
// @Tags Container Docker // @Tags Container Docker
// @Summary Load docker status // @Summary Load docker status
// @Produce json // @Produce json
// @Success 200 {string} dto.DockerStatus // @Success 200 {object} dto.DockerStatus
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Security Timestamp // @Security Timestamp
// @Router /containers/docker/status [get] // @Router /containers/docker/status [get]
@@ -24,7 +24,7 @@ func (b *BaseApi) LoadDockerStatus(c *gin.Context) {
// @Tags Container Docker // @Tags Container Docker
// @Summary Load docker daemon.json // @Summary Load docker daemon.json
// @Produce json // @Produce json
// @Success 200 {object} string // @Success 200 {string} string
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Security Timestamp // @Security Timestamp
// @Router /containers/daemonjson/file [get] // @Router /containers/daemonjson/file [get]
+1 -1
View File
@@ -32,7 +32,7 @@ func (b *BaseApi) PageTasks(c *gin.Context) {
// @Tags TaskLog // @Tags TaskLog
// @Summary Get the number of executing tasks // @Summary Get the number of executing tasks
// @Success 200 {object} int64 // @Success 200 {integer} int64
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Security Timestamp // @Security Timestamp
// @Router /logs/tasks/executing/count [get] // @Router /logs/tasks/executing/count [get]
+46 -2
View File
@@ -506,7 +506,7 @@ func (b *BaseApi) GetProxyConfig(c *gin.Context) {
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Security Timestamp // @Security Timestamp
// @Router /websites/proxies/update [post] // @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) { func (b *BaseApi) UpdateProxyConfig(c *gin.Context) {
var req request.WebsiteProxyConfig var req request.WebsiteProxyConfig
if err := helper.CheckBindAndValidate(&req, c); err != nil { if err := helper.CheckBindAndValidate(&req, c); err != nil {
@@ -520,6 +520,50 @@ func (b *BaseApi) UpdateProxyConfig(c *gin.Context) {
helper.Success(c) 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 // @Tags Website
// @Summary Update proxy file // @Summary Update proxy file
// @Accept json // @Accept json
@@ -528,7 +572,7 @@ func (b *BaseApi) UpdateProxyConfig(c *gin.Context) {
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Security Timestamp // @Security Timestamp
// @Router /websites/proxies/file [post] // @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) { func (b *BaseApi) UpdateProxyConfigFile(c *gin.Context) {
var req request.NginxProxyUpdate var req request.NginxProxyUpdate
if err := helper.CheckBindAndValidate(&req, c); err != nil { if err := helper.CheckBindAndValidate(&req, c); err != nil {
+145 -43
View File
@@ -6,9 +6,13 @@ type AgentCreateReq struct {
Name string `json:"name" validate:"required"` Name string `json:"name" validate:"required"`
AppVersion string `json:"appVersion" validate:"required"` AppVersion string `json:"appVersion" validate:"required"`
WebUIPort int `json:"webUIPort" validate:"required"` WebUIPort int `json:"webUIPort" validate:"required"`
BridgePort int `json:"bridgePort" validate:"required"` BridgePort int `json:"bridgePort"`
Provider string `json:"provider" validate:"required"` AgentType string `json:"agentType"`
Model string `json:"model" validate:"required"` Provider string `json:"provider"`
Model string `json:"model"`
APIType string `json:"apiType"`
MaxTokens int `json:"maxTokens"`
ContextWindow int `json:"contextWindow"`
AccountID uint `json:"accountId"` AccountID uint `json:"accountId"`
APIKey string `json:"apiKey"` APIKey string `json:"apiKey"`
BaseURL string `json:"baseURL"` BaseURL string `json:"baseURL"`
@@ -28,26 +32,30 @@ type AgentCreateReq struct {
} }
type AgentItem struct { type AgentItem struct {
ID uint `json:"id"` ID uint `json:"id"`
Name string `json:"name"` Name string `json:"name"`
Provider string `json:"provider"` AgentType string `json:"agentType"`
ProviderName string `json:"providerName"` Provider string `json:"provider"`
Model string `json:"model"` ProviderName string `json:"providerName"`
BaseURL string `json:"baseUrl"` Model string `json:"model"`
APIKey string `json:"apiKey"` APIType string `json:"apiType"`
Token string `json:"token"` MaxTokens int `json:"maxTokens"`
Status string `json:"status"` ContextWindow int `json:"contextWindow"`
Message string `json:"message"` BaseURL string `json:"baseUrl"`
AppInstallID uint `json:"appInstallId"` APIKey string `json:"apiKey"`
AccountID uint `json:"accountId"` Token string `json:"token"`
AppVersion string `json:"appVersion"` Status string `json:"status"`
Container string `json:"containerName"` Message string `json:"message"`
WebUIPort int `json:"webUIPort"` AppInstallID uint `json:"appInstallId"`
BridgePort int `json:"bridgePort"` AccountID uint `json:"accountId"`
Path string `json:"path"` AppVersion string `json:"appVersion"`
ConfigPath string `json:"configPath"` Container string `json:"containerName"`
Upgradable bool `json:"upgradable"` WebUIPort int `json:"webUIPort"`
CreatedAt time.Time `json:"createdAt"` BridgePort int `json:"bridgePort"`
Path string `json:"path"`
ConfigPath string `json:"configPath"`
Upgradable bool `json:"upgradable"`
CreatedAt time.Time `json:"createdAt"`
} }
type AgentDeleteReq struct { type AgentDeleteReq struct {
@@ -67,20 +75,30 @@ type AgentModelConfigUpdateReq struct {
} }
type AgentAccountCreateReq struct { type AgentAccountCreateReq struct {
Provider string `json:"provider" validate:"required"` Provider string `json:"provider" validate:"required"`
Name string `json:"name" validate:"required"` Name string `json:"name" validate:"required"`
APIKey string `json:"apiKey" validate:"required"` APIKey string `json:"apiKey" validate:"required"`
BaseURL string `json:"baseURL"` RememberAPIKey bool `json:"rememberApiKey"`
Remark string `json:"remark"` 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 { type AgentAccountUpdateReq struct {
ID uint `json:"id" validate:"required"` ID uint `json:"id" validate:"required"`
Name string `json:"name" validate:"required"` Name string `json:"name" validate:"required"`
APIKey string `json:"apiKey" validate:"required"` APIKey string `json:"apiKey" validate:"required"`
BaseURL string `json:"baseURL"` RememberAPIKey bool `json:"rememberApiKey"`
Remark string `json:"remark"` BaseURL string `json:"baseURL"`
SyncAgents bool `json:"syncAgents"` 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 { type AgentAccountVerifyReq struct {
@@ -100,15 +118,20 @@ type AgentAccountSearch struct {
} }
type AgentAccountInfo struct { type AgentAccountInfo struct {
ID uint `json:"id"` ID uint `json:"id"`
Provider string `json:"provider"` Provider string `json:"provider"`
ProviderName string `json:"providerName"` ProviderName string `json:"providerName"`
Name string `json:"name"` Name string `json:"name"`
APIKey string `json:"apiKey"` APIKey string `json:"apiKey"`
BaseURL string `json:"baseUrl"` RememberAPIKey bool `json:"rememberApiKey"`
Verified bool `json:"verified"` BaseURL string `json:"baseUrl"`
Remark string `json:"remark"` Model string `json:"model"`
CreatedAt time.Time `json:"createdAt"` 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 { type ProviderModelInfo struct {
@@ -149,3 +172,82 @@ type AgentFeishuConfig struct {
AppID string `json:"appId"` AppID string `json:"appId"`
AppSecret string `json:"appSecret"` 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 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"`
}
+6
View File
@@ -95,10 +95,16 @@ type ContainerOperate struct {
Privileged bool `json:"privileged"` Privileged bool `json:"privileged"`
AutoRemove bool `json:"autoRemove"` AutoRemove bool `json:"autoRemove"`
Volumes []VolumeHelper `json:"volumes"` Volumes []VolumeHelper `json:"volumes"`
ExtraHosts []ExtraHost `json:"extraHosts"`
Labels []string `json:"labels"` Labels []string `json:"labels"`
Env []string `json:"env"` Env []string `json:"env"`
RestartPolicy string `json:"restartPolicy"` RestartPolicy string `json:"restartPolicy"`
} }
type ExtraHost struct {
Hostname string `json:"hostname"`
IP string `json:"ip"`
}
type ContainerNetwork struct { type ContainerNetwork struct {
Network string `json:"network"` Network string `json:"network"`
Ipv4 string `json:"ipv4"` Ipv4 string `json:"ipv4"`
+9
View File
@@ -138,3 +138,12 @@ type AppUpdateVersion struct {
AppInstallID uint `json:"appInstallID" validate:"required"` AppInstallID uint `json:"appInstallID" validate:"required"`
UpdateVersion string `json:"updateVersion"` UpdateVersion string `json:"updateVersion"`
} }
type AppInstallSortItem struct {
InstallID uint `json:"installID"`
SortOrder int `json:"sortOrder"`
}
type AppInstallSort struct {
Items []AppInstallSortItem `json:"items" validate:"required"`
}
+11
View File
@@ -272,6 +272,17 @@ type WebsiteProxyConfig struct {
CorsConfig 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 { type CorsConfig struct {
Cors bool `json:"cors"` Cors bool `json:"cors"`
AllowOrigins string `json:"allowOrigins"` AllowOrigins string `json:"allowOrigins"`
+2 -2
View File
@@ -6,8 +6,8 @@ type WebsiteSSLSearch struct {
dto.PageInfo dto.PageInfo
AcmeAccountID string `json:"acmeAccountID"` AcmeAccountID string `json:"acmeAccountID"`
Domain string `json:"domain"` Domain string `json:"domain"`
OrderBy string `json:"orderBy" validate:"required,oneof=expire_date"` OrderBy string `json:"orderBy" validate:"omitempty,oneof=created_at expire_date"`
Order string `json:"order" validate:"required,oneof=null ascending descending"` Order string `json:"order" validate:"omitempty,oneof=null ascending descending"`
} }
type WebsiteSSLListReq struct { type WebsiteSSLListReq struct {
+1
View File
@@ -126,6 +126,7 @@ type AppInstallDTO struct {
WebUI string `json:"webUI"` WebUI string `json:"webUI"`
CreatedAt time.Time `json:"createdAt"` CreatedAt time.Time `json:"createdAt"`
Favorite bool `json:"favorite"` Favorite bool `json:"favorite"`
SortOrder int `json:"sortOrder"`
App AppDetail `json:"app"` App AppDetail `json:"app"`
Container string `json:"container"` Container string `json:"container"`
IsEdit bool `json:"isEdit"` IsEdit bool `json:"isEdit"`
+15 -11
View File
@@ -2,15 +2,19 @@ package model
type Agent struct { type Agent struct {
BaseModel BaseModel
Name string `json:"name" gorm:"not null;unique"` Name string `json:"name" gorm:"not null;unique"`
Provider string `json:"provider"` AgentType string `json:"agentType" gorm:"default:openclaw"`
Model string `json:"model"` Provider string `json:"provider"`
BaseURL string `json:"baseUrl"` Model string `json:"model"`
APIKey string `json:"apiKey"` APIType string `json:"apiType"`
Token string `json:"token"` MaxTokens int `json:"maxTokens"`
Status string `json:"status"` ContextWindow int `json:"contextWindow"`
Message string `json:"message"` BaseURL string `json:"baseUrl"`
AppInstallID uint `json:"appInstallId"` APIKey string `json:"apiKey"`
AccountID uint `json:"accountId"` Token string `json:"token"`
ConfigPath string `json:"configPath"` Status string `json:"status"`
Message string `json:"message"`
AppInstallID uint `json:"appInstallId"`
AccountID uint `json:"accountId"`
ConfigPath string `json:"configPath"`
} }
+11 -6
View File
@@ -2,12 +2,17 @@ package model
type AgentAccount struct { type AgentAccount struct {
BaseModel BaseModel
Provider string `json:"provider"` Provider string `json:"provider"`
Name string `json:"name"` Name string `json:"name"`
APIKey string `json:"apiKey"` APIKey string `json:"apiKey"`
BaseURL string `json:"baseUrl"` BaseURL string `json:"baseUrl"`
Verified bool `json:"verified"` Model string `json:"model"`
Remark string `json:"remark"` 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 { func (AgentAccount) TableName() string {
+1
View File
@@ -26,6 +26,7 @@ type AppInstall struct {
HttpsPort int `json:"httpsPort"` HttpsPort int `json:"httpsPort"`
WebUI string `json:"webUI"` WebUI string `json:"webUI"`
Favorite bool `json:"favorite"` Favorite bool `json:"favorite"`
SortOrder int `json:"sortOrder" gorm:"default:0"`
App App `json:"app" gorm:"-:migration"` App App `json:"app" gorm:"-:migration"`
} }
+71 -12
View File
@@ -1,6 +1,8 @@
package provider package provider
import "strings" import (
"strings"
)
type Model struct { type Model struct {
ID string ID string
@@ -21,13 +23,13 @@ var catalog = map[string]Meta{
"ollama": { "ollama": {
Key: "ollama", Key: "ollama",
DisplayName: "Ollama", DisplayName: "Ollama",
Sort: 1, Sort: 10,
Enabled: true, Enabled: true,
}, },
"deepseek": { "deepseek": {
Key: "deepseek", Key: "deepseek",
DisplayName: "DeepSeek", DisplayName: "DeepSeek",
Sort: 2, Sort: 20,
DefaultBaseURL: "https://api.deepseek.com/v1", DefaultBaseURL: "https://api.deepseek.com/v1",
EnvKey: "DEEPSEEK_API_KEY", EnvKey: "DEEPSEEK_API_KEY",
Enabled: true, Enabled: true,
@@ -37,10 +39,19 @@ var catalog = map[string]Meta{
{ID: "deepseek/deepseek-r1:1.5b", Name: "DeepSeek R1 1.5B"}, {ID: "deepseek/deepseek-r1:1.5b", Name: "DeepSeek R1 1.5B"},
}, },
}, },
"custom": {
Key: "custom",
DisplayName: "Custom",
Sort: 30,
DefaultBaseURL: "",
EnvKey: "CUSTOM_API_KEY",
Enabled: true,
Models: []Model{},
},
"openai": { "openai": {
Key: "openai", Key: "openai",
DisplayName: "OpenAI", DisplayName: "OpenAI",
Sort: 3, Sort: 40,
DefaultBaseURL: "https://api.openai.com/v1", DefaultBaseURL: "https://api.openai.com/v1",
EnvKey: "OPENAI_API_KEY", EnvKey: "OPENAI_API_KEY",
Enabled: true, Enabled: true,
@@ -56,7 +67,7 @@ var catalog = map[string]Meta{
"anthropic": { "anthropic": {
Key: "anthropic", Key: "anthropic",
DisplayName: "Anthropic", DisplayName: "Anthropic",
Sort: 4, Sort: 50,
DefaultBaseURL: "https://api.anthropic.com", DefaultBaseURL: "https://api.anthropic.com",
EnvKey: "ANTHROPIC_API_KEY", EnvKey: "ANTHROPIC_API_KEY",
Enabled: true, Enabled: true,
@@ -71,7 +82,7 @@ var catalog = map[string]Meta{
"gemini": { "gemini": {
Key: "gemini", Key: "gemini",
DisplayName: "Gemini", DisplayName: "Gemini",
Sort: 5, Sort: 60,
DefaultBaseURL: "https://generativelanguage.googleapis.com", DefaultBaseURL: "https://generativelanguage.googleapis.com",
EnvKey: "GEMINI_API_KEY", EnvKey: "GEMINI_API_KEY",
Enabled: true, Enabled: true,
@@ -87,7 +98,7 @@ var catalog = map[string]Meta{
"minimax": { "minimax": {
Key: "minimax", Key: "minimax",
DisplayName: "MiniMax (CN)", DisplayName: "MiniMax (CN)",
Sort: 6, Sort: 70,
DefaultBaseURL: "https://api.minimaxi.com/anthropic", DefaultBaseURL: "https://api.minimaxi.com/anthropic",
EnvKey: "MINIMAX_API_KEY", EnvKey: "MINIMAX_API_KEY",
Enabled: true, Enabled: true,
@@ -99,7 +110,7 @@ var catalog = map[string]Meta{
"moonshot": { "moonshot": {
Key: "moonshot", Key: "moonshot",
DisplayName: "Moonshot (Global)", DisplayName: "Moonshot (Global)",
Sort: 7, Sort: 80,
DefaultBaseURL: "https://api.moonshot.ai/v1", DefaultBaseURL: "https://api.moonshot.ai/v1",
EnvKey: "MOONSHOT_API_KEY", EnvKey: "MOONSHOT_API_KEY",
Enabled: true, Enabled: true,
@@ -112,7 +123,7 @@ var catalog = map[string]Meta{
"kimi": { "kimi": {
Key: "kimi", Key: "kimi",
DisplayName: "Kimi (CN)", DisplayName: "Kimi (CN)",
Sort: 8, Sort: 90,
DefaultBaseURL: "https://api.moonshot.cn/v1", DefaultBaseURL: "https://api.moonshot.cn/v1",
EnvKey: "KIMI_API_KEY", EnvKey: "KIMI_API_KEY",
Enabled: true, Enabled: true,
@@ -122,21 +133,69 @@ var catalog = map[string]Meta{
{ID: "kimi/kimi-k2-thinking", Name: "Kimi K2 Thinking"}, {ID: "kimi/kimi-k2-thinking", Name: "Kimi K2 Thinking"},
}, },
}, },
"zai": {
Key: "zai",
DisplayName: "Z.ai",
Sort: 95,
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"},
},
},
"kimi-coding": { "kimi-coding": {
Key: "kimi-coding", Key: "kimi-coding",
DisplayName: "Kimi Coding", DisplayName: "Kimi Coding",
Sort: 9, Sort: 100,
DefaultBaseURL: "https://api.moonshot.cn/anthropic/v1", DefaultBaseURL: "https://api.kimi.com/coding/",
EnvKey: "KIMI_API_KEY", EnvKey: "KIMI_API_KEY",
Enabled: true, Enabled: true,
Models: []Model{ Models: []Model{
{ID: "kimi-coding/k2p5", Name: "Kimi K2.5"}, {ID: "kimi-coding/k2p5", Name: "Kimi K2.5"},
}, },
}, },
"bailian-coding-plan": {
Key: "bailian-coding-plan",
DisplayName: "阿里云百炼 Coding Plan",
Sort: 11,
DefaultBaseURL: "https://coding.dashscope.aliyuncs.com/v1",
EnvKey: "QWEN_API_KEY",
Enabled: true,
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: 12,
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"},
},
},
"qwen": { "qwen": {
Key: "qwen", Key: "qwen",
DisplayName: "Qwen", DisplayName: "Qwen",
Sort: 10, Sort: 110,
DefaultBaseURL: "https://dashscope.aliyuncs.com/compatible-mode/v1", DefaultBaseURL: "https://dashscope.aliyuncs.com/compatible-mode/v1",
EnvKey: "QWEN_API_KEY", EnvKey: "QWEN_API_KEY",
Enabled: false, Enabled: false,
+1082 -125
View File
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -416,7 +416,7 @@ func (a AppService) Install(req request.AppInstallCreate, executeScript bool) (a
} }
} else { } else {
if appDetail.DockerCompose == "" { 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) _, composeRes, err = req_helper.HandleRequest(dockerComposeUrl, http.MethodGet, constant.TimeOut20s)
if err != nil { if err != nil {
return return
@@ -817,7 +817,7 @@ func (a AppService) GetAppUpdate() (*response.AppUpdateRes, error) {
return res, nil 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) _, versionRes, err := req_helper.HandleRequest(versionUrl, http.MethodGet, constant.TimeOut20s)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -889,7 +889,7 @@ func getAppFromRepo(downloadPath string) error {
func getAppList() (*dto.AppList, error) { func getAppList() (*dto.AppList, error) {
list := &dto.AppList{} 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 return nil, err
} }
listFile := filepath.Join(global.Dir.ResourceDir, "1panel.json") listFile := filepath.Join(global.Dir.ResourceDir, "1panel.json")
+14
View File
@@ -57,6 +57,7 @@ type IAppInstallService interface {
UpdateAppConfig(req request.AppConfigUpdate) error UpdateAppConfig(req request.AppConfigUpdate) error
GetInstallList() ([]dto.AppInstallInfo, error) GetInstallList() ([]dto.AppInstallInfo, error)
GetAppInstallInfo(appInstallID uint) (*response.AppInstallInfo, error) GetAppInstallInfo(appInstallID uint) (*response.AppInstallInfo, error)
UpdateSort(req request.AppInstallSort) error
} }
func NewIAppInstalledService() IAppInstallService { func NewIAppInstalledService() IAppInstallService {
@@ -83,6 +84,7 @@ func (a *AppInstallService) Page(req request.AppInstalledSearch) (int64, []respo
err error err error
) )
opts = append(opts, repo.WithOrderRuleBy("favorite", "descending")) opts = append(opts, repo.WithOrderRuleBy("favorite", "descending"))
opts = append(opts, repo.WithOrderRuleBy("sort_order", "ascending"))
if req.Name != "" { if req.Name != "" {
opts = append(opts, repo.WithByLikeName(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) return opNginx(install.ContainerName, constant.NginxReload)
case constant.Favorite: case constant.Favorite:
install.Favorite = req.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) return appInstallRepo.Save(context.Background(), &install)
default: default:
return errors.New("operate not support") return errors.New("operate not support")
@@ -318,6 +323,15 @@ func (a *AppInstallService) UpdateAppConfig(req request.AppConfigUpdate) error {
return appInstallRepo.Save(context.Background(), &installed) 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 { func (a *AppInstallService) Update(req request.AppInstalledUpdate) error {
installed, err := appInstallRepo.GetFirst(repo.WithByID(req.InstallId)) installed, err := appInstallRepo.GetFirst(repo.WithByID(req.InstallId))
if err != nil { if err != nil {
+175 -66
View File
@@ -7,6 +7,8 @@ import (
"net/http" "net/http"
"strconv" "strconv"
"strings" "strings"
"sync"
"sync/atomic"
"time" "time"
"github.com/1Panel-dev/1Panel/agent/app/dto" "github.com/1Panel-dev/1Panel/agent/app/dto"
@@ -81,7 +83,7 @@ func (a AppService) createSyncAppStoreTask(sharedCtx **appSyncContext) func(t *t
ctx := &appSyncContext{ ctx := &appSyncContext{
task: t, task: t,
httpClient: http.Client{Timeout: time.Duration(constant.TimeOut20s) * time.Second, Transport: xpack.LoadRequestTransport()}, 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, systemVersion: setting.SystemVersion,
settingService: settingService, settingService: settingService,
list: list, 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 { func (c *appSyncContext) syncAppIconsAndDetails() error {
total := len(c.list.Apps) total := len(c.list.Apps)
global.LOG.Infof("[AppStore] sync app detail start, total apps: %d", total) global.LOG.Infof("[AppStore] sync app detail start, total apps: %d", total)
var ( workItems := make([]appWorkItem, 0, total)
icon200Count = 0 for _, l := range c.list.Apps {
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)
}
app, ok := c.appsMap[l.AppProperty.Key] app, ok := c.appsMap[l.AppProperty.Key]
if !ok { if !ok {
continue continue
} }
iconUrl, hasPending := c.pendingIcons[l.AppProperty.Key] iconUrl, hasPending := c.pendingIcons[l.AppProperty.Key]
if hasPending { workItems = append(workItems, appWorkItem{
status, iconField := c.downloadAppIcon(iconUrl, l.AppProperty.Key, app.Icon) appDef: l,
switch status { 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: case http.StatusOK:
app.Icon = iconField
icon200Count++ icon200Count++
case http.StatusNotModified: case http.StatusNotModified:
icon304Count++ icon304Count++
default: default:
global.LOG.Warnf("[AppStore] download icon failed url=%s, appKey=%s", iconUrl, l.AppProperty.Key)
iconFailCount++ iconFailCount++
} }
} }
completed++
checkProgress()
}
app.TagsKey = l.AppProperty.Tags for result := range resultCh {
if l.AppProperty.Recommend > 0 { applyResult(result)
app.Recommend = l.AppProperty.Recommend }
} else {
app.Recommend = 9999 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", global.LOG.Infof("[AppStore] icon download completed - total: %d, success(200): %d, cached(304): %d, failed: %d",
+2 -1
View File
@@ -393,7 +393,7 @@ func deleteAppInstall(deleteReq request.AppInstallDelete) error {
return err return err
} }
appKey := install.App.Key appKey := install.App.Key
if appKey == constant.AppOpenclaw { if appKey == constant.AppOpenclaw || appKey == constant.AppCopaw {
_ = agentRepo.DeleteByAppInstallIDWithCtx(ctx, install.ID) _ = agentRepo.DeleteByAppInstallIDWithCtx(ctx, install.ID)
} }
@@ -1613,6 +1613,7 @@ func handleInstalled(appInstallList []model.AppInstall, updated, sync, checkUpda
Document: installed.App.Document, Document: installed.App.Document,
}, },
Favorite: installed.Favorite, Favorite: installed.Favorite,
SortOrder: installed.SortOrder,
Container: installed.ContainerName, Container: installed.ContainerName,
ServiceName: strings.ToLower(installed.ServiceName), ServiceName: strings.ToLower(installed.ServiceName),
} }
+153 -39
View File
@@ -11,6 +11,7 @@ import (
"time" "time"
"github.com/1Panel-dev/1Panel/agent/app/repo" "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/app/task"
"github.com/1Panel-dev/1Panel/agent/i18n" "github.com/1Panel-dev/1Panel/agent/i18n"
@@ -179,6 +180,9 @@ func handleAppRecover(install *model.AppInstall, parentTask *task.Task, recoverF
return err return err
} }
tmpPath := strings.ReplaceAll(recoverFile, ".tar.gz", "") tmpPath := strings.ReplaceAll(recoverFile, ".tar.gz", "")
if err := fileOp.TarGzExtractPro(tmpPath+"/app.tar.gz", tmpPath, ""); err != nil {
return err
}
defer func() { defer func() {
_, _ = compose.Up(install.GetComposePath()) _, _ = compose.Up(install.GetComposePath())
_ = os.RemoveAll(strings.ReplaceAll(recoverFile, ".tar.gz", "")) _ = 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") { if !fileOp.Stat(tmpPath+"/app.json") || !fileOp.Stat(tmpPath+"/app.tar.gz") {
return errors.New(i18n.GetMsgByKey("AppBackupFileIncomplete")) return errors.New(i18n.GetMsgByKey("AppBackupFileIncomplete"))
} }
var oldInstall model.AppInstall var backupInstall model.AppInstall
appJson, err := os.ReadFile(tmpPath + "/app.json") appJson, err := os.ReadFile(tmpPath + "/app.json")
if err != nil { if err != nil {
return err 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) 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")) return errors.New(i18n.GetMsgByKey("AppAttributesNotMatch"))
} }
backupEnvMap, err := getEnvMapByPath(path.Join(tmpPath, install.Name, ".env"))
newEnvFile := "" 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)) resources, _ := appInstallResourceRepo.GetBy(appInstallResourceRepo.WithAppInstallId(install.ID))
for _, resource := range resources { for _, resource := range resources {
var database model.Database var database model.Database
@@ -225,11 +236,20 @@ func handleAppRecover(install *model.AppInstall, parentTask *task.Task, recoverF
if err != nil { if err != nil {
return err 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) taskName := task.GetTaskName(db.Name, task.TaskRecover, task.TaskScopeDatabase)
t.LogStart(taskName) t.LogStart(taskName)
if err := handlePostgresqlRecover(dto.CommonRecover{ if err := handlePostgresqlRecover(dto.CommonRecover{
Name: database.Name, Name: newDB.PostgresqlName,
DetailName: db.Name, DetailName: newDB.Name,
File: fmt.Sprintf("%s/%s.sql.gz", tmpPath, install.Name), File: fmt.Sprintf("%s/%s.sql.gz", tmpPath, install.Name),
}, parentTask, true); err != nil { }, parentTask, true); err != nil {
t.LogFailedWithErr(taskName, err) t.LogFailedWithErr(taskName, err)
@@ -241,15 +261,11 @@ func handleAppRecover(install *model.AppInstall, parentTask *task.Task, recoverF
if err != nil { if err != nil {
return err return err
} }
newDB, envMap, err := reCreateDB(db.ID, database, oldInstall.Env) newDB, err := reCreateDB(db.ID, database, backupEnvMap)
if err != nil { if err != nil {
return err return err
} }
oldHost := fmt.Sprintf("\"PANEL_DB_HOST\":\"%v\"", envMap["PANEL_DB_HOST"].(string)) backupInstall.Env, mergedEnvContent, err = buildRecoverEnv(backupInstall.Env, backupEnvMap, installedEnvMap)
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)
if err != nil { if err != nil {
return err return err
} }
@@ -284,22 +300,22 @@ func handleAppRecover(install *model.AppInstall, parentTask *task.Task, recoverF
t.LogSuccess(deCompressName) t.LogSuccess(deCompressName)
_ = fileOp.DeleteDir(backPath) _ = fileOp.DeleteDir(backPath)
if len(newEnvFile) != 0 { if len(mergedEnvContent) != 0 {
envPath := fmt.Sprintf("%s/%s/.env", install.GetAppPath(), install.Name) envPath := fmt.Sprintf("%s/%s/.env", install.GetAppPath(), install.Name)
file, err := os.OpenFile(envPath, os.O_WRONLY|os.O_TRUNC, 0640) file, err := os.OpenFile(envPath, os.O_WRONLY|os.O_TRUNC, 0640)
if err != nil { if err != nil {
return err return err
} }
defer file.Close() defer file.Close()
_, _ = file.WriteString(newEnvFile) _, _ = file.WriteString(mergedEnvContent)
} }
oldInstall.ID = install.ID backupInstall.ID = install.ID
oldInstall.Status = constant.StatusRunning backupInstall.Status = constant.StatusRunning
oldInstall.AppId = install.AppId backupInstall.AppId = install.AppId
oldInstall.AppDetailId = install.AppDetailId backupInstall.AppDetailId = install.AppDetailId
oldInstall.App.ID = install.AppId backupInstall.App.ID = install.AppId
if err := appInstallRepo.Save(context.Background(), &oldInstall); err != nil { if err := appInstallRepo.Save(context.Background(), &backupInstall); err != nil {
global.LOG.Errorf("save db app install failed, err: %v", err) global.LOG.Errorf("save db app install failed, err: %v", err)
return err return err
} }
@@ -373,33 +389,131 @@ func doAppBackup(install *model.AppInstall, parentTask *task.Task, backupDir, fi
return nil 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() mysqlService := NewIMysqlService()
ctx := context.Background() ctx := context.Background()
_ = mysqlService.Delete(ctx, dto.MysqlDBDelete{ID: dbID, Database: database.Name, Type: database.Type, DeleteBackup: false, ForceDelete: true}) _ = mysqlService.Delete(ctx, dto.MysqlDBDelete{ID: dbID, Database: database.Name, Type: database.Type, DeleteBackup: false, ForceDelete: true})
envMap := make(map[string]interface{}) dbInfo := getDBCreateInfoFromEnv(envMap, "utf8mb4")
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)
createDB, err := mysqlService.Create(context.Background(), dto.MysqlDBCreate{ createDB, err := mysqlService.Create(context.Background(), dto.MysqlDBCreate{
Name: oldName, Name: dbInfo.Name,
From: database.From, From: database.From,
Database: database.Name, Database: database.Name,
Format: "utf8mb4", Format: dbInfo.Format,
Username: oldUser, Username: dbInfo.User,
Password: oldPassword, Password: dbInfo.Password,
Permission: "%", 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 { 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
} }
+19 -40
View File
@@ -43,7 +43,6 @@ import (
"github.com/docker/go-connections/nat" "github.com/docker/go-connections/nat"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
v1 "github.com/opencontainers/image-spec/specs-go/v1" v1 "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
"github.com/shirou/gopsutil/v4/cpu" "github.com/shirou/gopsutil/v4/cpu"
"github.com/shirou/gopsutil/v4/mem" "github.com/shirou/gopsutil/v4/mem"
) )
@@ -69,7 +68,6 @@ type IContainerService interface {
ComposeLogClean(req dto.ComposeLogClean) error ComposeLogClean(req dto.ComposeLogClean) error
ContainerCreate(req dto.ContainerOperate, inThread bool) error ContainerCreate(req dto.ContainerOperate, inThread bool) error
ContainerCreateByCommand(req dto.ContainerCreateByCommand) error
ContainerUpdate(req dto.ContainerOperate) error ContainerUpdate(req dto.ContainerOperate) error
ContainerUpgrade(req dto.ContainerUpgrade) error ContainerUpgrade(req dto.ContainerUpgrade) error
ContainerInfo(req dto.OperationWithName) (*dto.ContainerOperate, 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 { if err != nil {
return 0, nil, err return 0, nil, err
} }
defer client.Close() defer func() { _ = client.Close() }()
options := container.ListOptions{All: true} options := container.ListOptions{All: true}
if len(req.Filters) != 0 { if len(req.Filters) != 0 {
options.Filters = filters.NewArgs() options.Filters = filters.NewArgs()
@@ -302,42 +300,6 @@ func (u *ContainerService) ContainerListStats() ([]dto.ContainerListStats, error
return datas, nil 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) { func (u *ContainerService) Inspect(req dto.InspectReq) (string, error) {
client, err := docker.NewDockerClient() client, err := docker.NewDockerClient()
if err != nil { if err != nil {
@@ -621,6 +583,16 @@ func (u *ContainerService) ContainerInfo(req dto.OperationWithName) (*dto.Contai
data.ExposedPorts = loadContainerPortForInfo(exposePorts) data.ExposedPorts = loadContainerPortForInfo(exposePorts)
data.Hostname = oldContainer.Config.Hostname data.Hostname = oldContainer.Config.Hostname
data.DNS = oldContainer.HostConfig.DNS 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.DomainName = oldContainer.Config.Domainname
data.Cmd = oldContainer.Config.Cmd 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 { func (u *ContainerService) LoadUsers(req dto.OperationWithName) []string {
var users []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 { if err != nil {
return users return users
} }
@@ -1488,6 +1460,13 @@ func loadConfigInfo(isCreate bool, req dto.ContainerOperate, oldContainer *conta
hostConf.Binds = []string{} hostConf.Binds = []string{}
hostConf.Mounts = []mount.Mount{} hostConf.Mounts = []mount.Mount{}
hostConf.DNS = req.DNS 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{}) config.Volumes = make(map[string]struct{})
for _, volume := range req.Volumes { for _, volume := range req.Volumes {
item := mount.Mount{ item := mount.Mount{
+5
View File
@@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"os" "os"
"path" "path"
"path/filepath"
"strings" "strings"
"github.com/1Panel-dev/1Panel/agent/app/dto" "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) { func (u *DBCommonService) LoadDatabaseFile(req dto.OperationWithNameAndType) (string, error) {
filePath := "" filePath := ""
safeName := filepath.Base(req.Name)
if safeName != req.Name || strings.Contains(safeName, "..") {
return "", buserr.New("ErrInvalidParams")
}
switch req.Type { switch req.Type {
case "mysql-cluster-conf": case "mysql-cluster-conf":
filePath = path.Join(global.Dir.DataDir, fmt.Sprintf("apps/mysql-cluster/%s/conf/my.cnf", req.Name)) filePath = path.Join(global.Dir.DataDir, fmt.Sprintf("apps/mysql-cluster/%s/conf/my.cnf", req.Name))
+8 -8
View File
@@ -109,7 +109,7 @@ func (u *DeviceService) CheckDNS(key, value string) (bool, error) {
if err != nil { if err != nil {
return false, err return false, err
} }
defer conn.Close() defer func() { _ = conn.Close() }()
return true, nil return true, nil
} }
@@ -132,7 +132,7 @@ func (u *DeviceService) Update(key, value string) error {
if cmd.CheckIllegal(value) { if cmd.CheckIllegal(value) {
return buserr.New("ErrCmdIllegal") 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 return err
} }
_, _ = psutil.HOST.GetHostInfo(true) _, _ = psutil.HOST.GetHostInfo(true)
@@ -245,7 +245,7 @@ func (u *DeviceService) UpdateSwap(req dto.SwapHelper) error {
} }
cmdMgr := cmd.NewCommandMgr(cmd.WithTask(*taskItem)) cmdMgr := cmd.NewCommandMgr(cmd.WithTask(*taskItem))
if !req.IsNew { 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) 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) return operateSwapWithFile(true, req)
} }
taskItem.LogStart(i18n.GetMsgByKey("CreateSwap")) 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) return fmt.Errorf("handle dd %s failed, %v", req.Path, err)
} }
taskItem.Log("chmod 0600 " + req.Path) 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) return fmt.Errorf("handle chmod 0600 %s failed, %v", req.Path, err)
} }
taskItem.LogStart(i18n.GetMsgByKey("FormatSwap")) 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) return fmt.Errorf("handle mkswap -f %s failed, %v", req.Path, err)
} }
taskItem.LogStart(i18n.GetMsgByKey("EnableSwap")) taskItem.LogStart(i18n.GetMsgByKey("EnableSwap"))
if err := cmdMgr.RunBashCf("%s swapon %s", cmd.SudoHandleCmd(), req.Path); err != nil { if err := cmdMgr.Run("swapon", req.Path); err != nil {
_ = cmdMgr.RunBashCf("%s swapoff %s", cmd.SudoHandleCmd(), req.Path) _ = cmdMgr.Run("swapoff", req.Path)
return fmt.Errorf("handle swapoff %s failed, %v", req.Path, err) return fmt.Errorf("handle swapoff %s failed, %v", req.Path, err)
} }
return operateSwapWithFile(false, req) return operateSwapWithFile(false, req)
+10 -9
View File
@@ -2,13 +2,14 @@ package service
import ( import (
"fmt" "fmt"
"os"
"strings"
"time"
"github.com/1Panel-dev/1Panel/agent/app/dto" "github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/buserr" "github.com/1Panel-dev/1Panel/agent/buserr"
"github.com/1Panel-dev/1Panel/agent/global" "github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/utils/cmd" "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/request"
"github.com/1Panel-dev/1Panel/agent/app/dto/response" "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)) 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) 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) 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) 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) return "", buserr.WithErr("PartitionDiskErr", err)
} }
partition := req.Device + "1" partition := req.Device + "1"
@@ -133,7 +134,7 @@ func (s *DiskService) MountDisk(req request.DiskMountRequest) error {
} }
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(1 * time.Minute)) 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) return buserr.WithErr("MountDiskErr", err)
} }
if req.AutoMount { if req.AutoMount {
@@ -156,7 +157,7 @@ func (s *DiskService) UnmountDisk(req request.DiskUnmountRequest) error {
if !isPointMounted(req.MountPoint) { if !isPointMounted(req.MountPoint) {
return buserr.New("MountDiskErr") 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) return buserr.WithErr("MountDiskErr", err)
} }
if err := removeFromFstab(req.MountPoint); err != nil { if err := removeFromFstab(req.MountPoint); err != nil {
+10 -5
View File
@@ -263,7 +263,7 @@ func (f *FileService) Create(op request.FileCreate) error {
func (f *FileService) Delete(op request.FileDelete) error { func (f *FileService) Delete(op request.FileDelete) error {
if op.IsDir { if op.IsDir {
excludeDir := global.Dir.DataDir 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") 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) { func (f *FileService) ReadLogByLine(req request.FileReadByLineReq) (*response.FileLineContent, error) {
logFilePath := "" logFilePath := ""
taskStatus := "" 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 { switch req.Type {
case constant.TypeWebsite: case constant.TypeWebsite:
website, err := websiteRepo.GetFirst(repo.WithByID(req.ID)) website, err := websiteRepo.GetFirst(repo.WithByID(req.ID))
@@ -649,9 +655,9 @@ func (f *FileService) ReadLogByLine(req request.FileReadByLineReq) (*response.Fi
logFilePath = taskModel.LogFile logFilePath = taskModel.LogFile
taskStatus = taskModel.Status taskStatus = taskModel.Status
case "mysql-slow-logs": 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": 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": case "php-fpm-slow-logs":
php, err := runtimeRepo.GetFirst(context.Background(), repo.WithByID(req.ID)) php, err := runtimeRepo.GetFirst(context.Background(), repo.WithByID(req.ID))
if err != nil { if err != nil {
@@ -666,8 +672,7 @@ func (f *FileService) ReadLogByLine(req request.FileReadByLineReq) (*response.Fi
} }
logFilePath, _ = ini_conf.GetIniValue(configPath, "supervisord", "logfile") logFilePath, _ = ini_conf.GetIniValue(configPath, "supervisord", "logfile")
case constant.Supervisor: case constant.Supervisor:
logDir := path.Join(global.Dir.DataDir, "tools", "supervisord", "log") logFilePath = path.Join(global.Dir.DataDir, "tools", "supervisord", "log", req.Name)
logFilePath = path.Join(logDir, req.Name)
} }
file, err := os.Open(logFilePath) file, err := os.Open(logFilePath)
+4
View File
@@ -278,6 +278,10 @@ func (h *HostToolService) OperateSupervisorProcess(req request.SupervisorProcess
} }
func handleProcess(supervisordDir string, req request.SupervisorProcessConfig, containerName string) error { 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 ( var (
fileOp = files.NewFileOp() fileOp = files.NewFileOp()
logDir = path.Join(supervisordDir, "log") logDir = path.Join(supervisordDir, "log")
+16 -5
View File
@@ -4,6 +4,10 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"path"
"strconv"
"strings"
"github.com/1Panel-dev/1Panel/agent/app/dto" "github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/app/dto/request" "github.com/1Panel-dev/1Panel/agent/app/dto/request"
"github.com/1Panel-dev/1Panel/agent/app/dto/response" "github.com/1Panel-dev/1Panel/agent/app/dto/response"
@@ -23,9 +27,6 @@ import (
"github.com/1Panel-dev/1Panel/agent/utils/nginx/parser" "github.com/1Panel-dev/1Panel/agent/utils/nginx/parser"
"github.com/subosito/gotenv" "github.com/subosito/gotenv"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
"path"
"strconv"
"strings"
) )
type McpServerService struct{} type McpServerService struct{}
@@ -458,7 +459,12 @@ func addProxy(server *model.McpServer) {
} else { } else {
proxyPath = server.StreamableHttpPath proxyPath = server.StreamableHttpPath
} }
location.UpdateDirective("proxy_pass", []string{fmt.Sprintf("http://127.0.0.1:%d%s", server.Port, proxyPath)}) safePass, err := nginx.NginxSafeString(fmt.Sprintf("http://127.0.0.1:%d%s", server.Port, proxyPath), nginx.ModeURL)
if err != nil {
global.LOG.Errorf("mcp add proxy failed, err: %v", err)
return
}
location.UpdateDirective("proxy_pass", []string{safePass})
location.ChangePath("^~", proxyPath) location.ChangePath("^~", proxyPath)
if err = nginx.WriteConfig(config, nginx.IndentedStyle); err != nil { if err = nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
global.LOG.Errorf("write config failed, err: %v", buserr.WithErr("ErrUpdateBuWebsite", err)) global.LOG.Errorf("write config failed, err: %v", buserr.WithErr("ErrUpdateBuWebsite", err))
@@ -516,7 +522,12 @@ func addMCPProxy(websiteID uint) error {
} else { } else {
proxyPath = server.StreamableHttpPath proxyPath = server.StreamableHttpPath
} }
location.UpdateDirective("proxy_pass", []string{fmt.Sprintf("http://127.0.0.1:%d%s", server.Port, proxyPath)}) safePass, err := nginx.NginxSafeString(fmt.Sprintf("http://127.0.0.1:%d%s", server.Port, proxyPath), nginx.ModeURL)
if err != nil {
global.LOG.Errorf("mcp add proxy failed, err: %v", err)
return err
}
location.UpdateDirective("proxy_pass", []string{safePass})
location.ChangePath("^~", proxyPath) location.ChangePath("^~", proxyPath)
if err = nginx.WriteConfig(config, nginx.IndentedStyle); err != nil { if err = nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
return buserr.WithErr("ErrUpdateBuWebsite", err) return buserr.WithErr("ErrUpdateBuWebsite", err)
+3 -3
View File
@@ -677,7 +677,7 @@ func (r *RuntimeService) GetPHPExtensions(runtimeID uint) (response.PHPExtension
return res, err return res, err
} }
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(20 * time.Second)) 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 { if err != nil {
return res, err return res, err
} }
@@ -722,7 +722,7 @@ func (r *RuntimeService) InstallPHPExtension(req request.PHPExtensionInstallReq)
} }
installTask.AddSubTask("", func(t *task.Task) error { installTask.AddSubTask("", func(t *task.Task) error {
err = cmd.NewCommandMgr(cmd.WithTask(*installTask), cmd.WithTimeout(20*time.Minute)). 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 { if err != nil {
return err return err
} }
@@ -736,7 +736,7 @@ func (r *RuntimeService) InstallPHPExtension(req request.PHPExtensionInstallReq)
return err return err
} }
err = cmd.NewCommandMgr(cmd.WithTask(*installTask), cmd.WithTimeout(15*time.Minute)). 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 { if err != nil {
return err return err
} }
+85 -30
View File
@@ -133,7 +133,7 @@ func (u *SnapshotService) SnapshotRecover(req dto.SnapshotRecover) error {
var snapJson SnapshotJson var snapJson SnapshotJson
taskItem.AddSubTaskWithAliasAndOps( taskItem.AddSubTaskWithAliasAndOps(
"Readjson", "ReadJson",
func(t *task.Task) error { func(t *task.Task) error {
snapJson, err = readFromJson(path.Join(rootDir, snap.Name), &itemHelper) snapJson, err = readFromJson(path.Join(rootDir, snap.Name), &itemHelper)
return err return err
@@ -156,14 +156,6 @@ func (u *SnapshotService) SnapshotRecover(req dto.SnapshotRecover) error {
) )
req.IsNew = true 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" { if req.IsNew || snap.InterruptStep == "RecoverBackups" {
taskItem.AddSubTaskWithAliasAndOps( taskItem.AddSubTaskWithAliasAndOps(
"RecoverBackups", "RecoverBackups",
@@ -222,13 +214,24 @@ func (u *SnapshotService) SnapshotRecover(req dto.SnapshotRecover) error {
) )
req.IsNew = true req.IsNew = true
} }
taskItem.AddSubTaskWithAliasAndOps( if req.IsNew || snap.InterruptStep == "RecoverCompose" {
"RecoverDBData", taskItem.AddSubTaskWithAliasAndOps(
func(t *task.Task) error { "RecoverCompose",
return restartCompose(path.Join(snapJson.BaseDir, "1panel/docker/compose"), &itemHelper) func(t *task.Task) error {
}, return restartCompose(path.Join(snapJson.BaseDir, "1panel/docker/compose"), &itemHelper)
nil, 0, 90*time.Minute, },
) 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 { if err := taskItem.Execute(); err != nil {
_ = settingRepo.Update("SystemStatus", "Free") _ = settingRepo.Update("SystemStatus", "Free")
@@ -343,22 +346,22 @@ func backupBeforeRecover(name string, itemHelper *snapRecoverHelper) error {
func readFromJson(rootDir string, itemHelper *snapRecoverHelper) (SnapshotJson, error) { func readFromJson(rootDir string, itemHelper *snapRecoverHelper) (SnapshotJson, error) {
itemHelper.Task.Log("---------------------- 4 / 11 ----------------------") itemHelper.Task.Log("---------------------- 4 / 11 ----------------------")
itemHelper.Task.LogStart(i18n.GetMsgByKey("Readjson")) itemHelper.Task.LogStart(i18n.GetMsgByKey("ReadJson"))
snapJsonPath := path.Join(rootDir, "base/snapshot.json") snapJsonPath := path.Join(rootDir, "base/snapshot.json")
var snap SnapshotJson var snap SnapshotJson
_, err := os.Stat(snapJsonPath) _, err := os.Stat(snapJsonPath)
itemHelper.Task.LogWithStatus(i18n.GetMsgByKey("ReadjsonPath"), err) itemHelper.Task.LogWithStatus(i18n.GetMsgByKey("ReadJsonPath"), err)
if err != nil { if err != nil {
return snap, err return snap, err
} }
fileByte, err := os.ReadFile(snapJsonPath) fileByte, err := os.ReadFile(snapJsonPath)
itemHelper.Task.LogWithStatus(i18n.GetMsgByKey("ReadjsonContent"), err) itemHelper.Task.LogWithStatus(i18n.GetMsgByKey("ReadJsonContent"), err)
if err != nil { if err != nil {
return snap, err return snap, err
} }
err = json.Unmarshal(fileByte, &snap) err = json.Unmarshal(fileByte, &snap)
itemHelper.Task.LogWithStatus(i18n.GetMsgByKey("ReadjsonMarshal"), err) itemHelper.Task.LogWithStatus(i18n.GetMsgByKey("ReadJsonMarshal"), err)
if err != nil { if err != nil {
return snap, err return snap, err
} }
@@ -439,17 +442,8 @@ func recoverBaseData(src string, itemHelper *snapRecoverHelper) error {
return nil 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 { func restartCompose(composePath string, itemHelper *snapRecoverHelper) error {
itemHelper.Task.Log("---------------------- 11 / 11 ----------------------") itemHelper.Task.Log("---------------------- 7 / 11 ----------------------")
itemHelper.Task.LogStart(i18n.GetMsgByKey("RecoverCompose")) itemHelper.Task.LogStart(i18n.GetMsgByKey("RecoverCompose"))
composes, err := composeRepo.ListRecord() composes, err := composeRepo.ListRecord()
@@ -472,3 +466,64 @@ func restartCompose(composePath string, itemHelper *snapRecoverHelper) error {
} }
return nil 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
View File
@@ -269,16 +269,26 @@ func (u *SSHService) CreateRootCert(req dto.RootCertOperate) error {
publicPath := fmt.Sprintf("%s/.ssh/%s.pub", currentUser.HomeDir, req.Name) publicPath := fmt.Sprintf("%s/.ssh/%s.pub", currentUser.HomeDir, req.Name)
authFilePath := currentUser.HomeDir + "/.ssh/authorized_keys" authFilePath := currentUser.HomeDir + "/.ssh/authorized_keys"
authFileItem, _ := os.ReadFile(authFilePath) if info, err := os.Stat(authFilePath); err == nil && info.Size() > 0 {
authFile := string(authFileItem) f, err := os.Open(authFilePath)
if authFile != "" && !strings.HasSuffix(authFile, "\n") {
file, err := os.OpenFile(authFilePath, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644)
if err != nil { if err != nil {
return err return err
} }
defer file.Close() defer func() { _ = f.Close() }()
if _, err := file.WriteString("\n"); err != nil {
return err 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 return err
} }
} else { } else {
command := fmt.Sprintf("ssh-keygen -t %s -f %s/.ssh/%s -N ''", req.EncryptionMode, currentUser.HomeDir, req.Name) tmpPrivatePath := privatePath + ".tmp"
if len(req.PassPhrase) != 0 { tmpPublicPath := privatePath + ".tmp.pub"
command = fmt.Sprintf("ssh-keygen -t %s -P %s -f %s/.ssh/%s | echo y", req.EncryptionMode, req.PassPhrase, currentUser.HomeDir, req.Name) 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) 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 { publicKeyBytes, err := os.ReadFile(publicPath)
return fmt.Errorf("generate failed, %v", err) 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 cert.PrivateKeyPath = privatePath
+28 -8
View File
@@ -110,6 +110,7 @@ type IWebsiteService interface {
GetProxyCache(id uint) (res response.NginxProxyCache, err error) GetProxyCache(id uint) (res response.NginxProxyCache, err error)
ClearProxyCache(req request.NginxCommonReq) error ClearProxyCache(req request.NginxCommonReq) error
DeleteProxy(req request.WebsiteProxyDel) (err error) DeleteProxy(req request.WebsiteProxyDel) (err error)
UpdateProxyStatus(req request.WebsiteProxyStatusUpdate) (err error)
CreateWebsiteDomain(create request.WebsiteDomainCreate) ([]model.WebsiteDomain, error) CreateWebsiteDomain(create request.WebsiteDomainCreate) ([]model.WebsiteDomain, error)
GetWebsiteDomain(websiteId uint) ([]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 { switch web.Type {
case constant.Deployment: case constant.Deployment:
appInstall, err := appInstallRepo.GetFirst(repo.WithByID(web.AppInstallID)) appInstall, err := appInstallRepo.GetFirst(repo.WithByID(web.AppInstallID))
if err != nil { if err == nil {
return 0, nil, err appName = appInstall.Name
appInstallID = appInstall.ID
} }
appName = appInstall.Name
appInstallID = appInstall.ID
case constant.Runtime: case constant.Runtime:
runtime, _ := runtimeRepo.GetFirst(context.Background(), repo.WithByID(web.RuntimeID)) runtime, _ := runtimeRepo.GetFirst(context.Background(), repo.WithByID(web.RuntimeID))
if runtime != nil { if runtime != nil {
@@ -1325,7 +1325,7 @@ func (w WebsiteService) UpdateSitePermission(req request.WebsiteUpdateDirPermiss
} }
absoluteIndexPath := GetSitePath(website, SiteIndexDir) absoluteIndexPath := GetSitePath(website, SiteIndexDir)
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(10 * time.Second)) 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 return err
} }
website.User = req.User website.User = req.User
@@ -1906,6 +1906,10 @@ func (w WebsiteService) UpdateRedirectFile(req request.NginxRedirectUpdate) (err
if err != nil { if err != nil {
return err 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") absolutePath := path.Join(GetSitePath(website, SiteRedirectDir), req.Name+".conf")
fileOp := files.NewFileOp() fileOp := files.NewFileOp()
oldRewriteContent, err = fileOp.GetContent(absolutePath) oldRewriteContent, err = fileOp.GetContent(absolutePath)
@@ -2333,9 +2337,25 @@ func (w WebsiteService) ExecComposer(req request.ExecComposerReq) error {
siteDir, _ := settingRepo.Get(settingRepo.WithByKey("WEBSITE_DIR")) siteDir, _ := settingRepo.Get(settingRepo.WithByKey("WEBSITE_DIR"))
execDir := strings.ReplaceAll(req.Dir, siteDir.Value, "/www") execDir := strings.ReplaceAll(req.Dir, siteDir.Value, "/www")
composerTask.AddSubTask("", func(t *task.Task) error { 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) if err := cmdMgr.Run("docker", "exec",
err = cmdMgr.RunBashC(cmdStr) "-u", req.User,
if err != nil { 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 err
} }
return nil return nil
+16 -5
View File
@@ -3,6 +3,10 @@ package service
import ( import (
"bufio" "bufio"
"fmt" "fmt"
"os"
"path"
"strings"
"github.com/1Panel-dev/1Panel/agent/app/dto" "github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/app/dto/request" "github.com/1Panel-dev/1Panel/agent/app/dto/request"
"github.com/1Panel-dev/1Panel/agent/app/dto/response" "github.com/1Panel-dev/1Panel/agent/app/dto/response"
@@ -11,14 +15,12 @@ import (
"github.com/1Panel-dev/1Panel/agent/buserr" "github.com/1Panel-dev/1Panel/agent/buserr"
"github.com/1Panel-dev/1Panel/agent/cmd/server/nginx_conf" "github.com/1Panel-dev/1Panel/agent/cmd/server/nginx_conf"
"github.com/1Panel-dev/1Panel/agent/constant" "github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/utils/files" "github.com/1Panel-dev/1Panel/agent/utils/files"
"github.com/1Panel-dev/1Panel/agent/utils/nginx" "github.com/1Panel-dev/1Panel/agent/utils/nginx"
"github.com/1Panel-dev/1Panel/agent/utils/nginx/components" "github.com/1Panel-dev/1Panel/agent/utils/nginx/components"
"github.com/1Panel-dev/1Panel/agent/utils/nginx/parser" "github.com/1Panel-dev/1Panel/agent/utils/nginx/parser"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
"os"
"path"
"strings"
) )
func (w WebsiteService) GetAuthBasics(req request.NginxAuthReq) (res response.NginxAuthRes, err error) { func (w WebsiteService) GetAuthBasics(req request.NginxAuthReq) (res response.NginxAuthRes, err error) {
@@ -260,6 +262,10 @@ func (w WebsiteService) UpdatePathAuthBasic(req request.NginxPathAuthUpdate) err
if !fileOp.Stat(passDir) { if !fileOp.Stat(passDir) {
_ = fileOp.CreateDir(passDir, constant.DirPerm) _ = 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)) confPath := path.Join(authDir, fmt.Sprintf("%s.conf", req.Name))
passPath := path.Join(passDir, fmt.Sprintf("%s.pass", req.Name)) passPath := path.Join(passDir, fmt.Sprintf("%s.pass", req.Name))
var config *components.Config var config *components.Config
@@ -289,7 +295,12 @@ func (w WebsiteService) UpdatePathAuthBasic(req request.NginxPathAuthUpdate) err
config.FilePath = confPath config.FilePath = confPath
directives := config.Directives directives := config.Directives
location, _ := directives[0].(*components.Location) location, _ := directives[0].(*components.Location)
location.UpdateDirective("auth_basic_user_file", []string{fmt.Sprintf("/www/sites/%s/path_auth/pass/%s", website.Alias, fmt.Sprintf("%s.pass", req.Name))}) safePass, err := nginx.NginxSafeString(fmt.Sprintf("/www/sites/%s/path_auth/pass/%s", website.Alias, fmt.Sprintf("%s.pass", req.Name)), nginx.ModePath)
if err != nil {
global.LOG.Errorf("invalid auth_basic_user_file path, err: %v", err)
return err
}
location.UpdateDirective("auth_basic_user_file", []string{safePass})
location.ChangePath("~*", fmt.Sprintf("^%s", req.Path)) location.ChangePath("~*", fmt.Sprintf("^%s", req.Path))
var passwdHash []byte var passwdHash []byte
passwdHash, err = bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost) passwdHash, err = bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
@@ -306,7 +317,7 @@ func (w WebsiteService) UpdatePathAuthBasic(req request.NginxPathAuthUpdate) err
} }
nginxInclude := fmt.Sprintf("/www/sites/%s/path_auth/*.conf", website.Alias) 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 { if err = updateNginxConfig(constant.NginxScopeServer, []dto.NginxParam{{Name: "include", Params: []string{nginxInclude}}}, &website); err != nil {
return nil return err
} }
return nil return nil
} }
+20 -3
View File
@@ -3,6 +3,10 @@ package service
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"os"
"path"
"strings"
"github.com/1Panel-dev/1Panel/agent/app/dto" "github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/app/dto/request" "github.com/1Panel-dev/1Panel/agent/app/dto/request"
"github.com/1Panel-dev/1Panel/agent/app/repo" "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"
"github.com/1Panel-dev/1Panel/agent/utils/nginx/components" "github.com/1Panel-dev/1Panel/agent/utils/nginx/components"
"github.com/1Panel-dev/1Panel/agent/utils/nginx/parser" "github.com/1Panel-dev/1Panel/agent/utils/nginx/parser"
"os"
"path"
"strings"
) )
func (w WebsiteService) GetLoadBalances(id uint) ([]dto.NginxUpstream, error) { 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) { if !fileOp.Stat(includeDir) {
_ = fileOp.CreateDir(includeDir, constant.DirPerm) _ = 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)) filePath := path.Join(includeDir, fmt.Sprintf("%s.conf", req.Name))
if fileOp.Stat(filePath) { if fileOp.Stat(filePath) {
return buserr.New("ErrNameIsExist") return buserr.New("ErrNameIsExist")
@@ -133,6 +138,10 @@ func (w WebsiteService) UpdateLoadBalance(req request.WebsiteLBUpdate) error {
} }
includeDir := GetSitePath(website, SiteUpstreamDir) includeDir := GetSitePath(website, SiteUpstreamDir)
fileOp := files.NewFileOp() 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)) filePath := path.Join(includeDir, fmt.Sprintf("%s.conf", req.Name))
if !fileOp.Stat(filePath) { if !fileOp.Stat(filePath) {
return nil return nil
@@ -191,6 +200,10 @@ func (w WebsiteService) DeleteLoadBalance(req request.WebsiteLBDelete) error {
includeDir := GetSitePath(website, SiteUpstreamDir) includeDir := GetSitePath(website, SiteUpstreamDir)
fileOp := files.NewFileOp() 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)) filePath := path.Join(includeDir, fmt.Sprintf("%s.conf", req.Name))
if !fileOp.Stat(filePath) { if !fileOp.Stat(filePath) {
return nil return nil
@@ -211,6 +224,10 @@ func (w WebsiteService) UpdateLoadBalanceFile(req request.WebsiteLBUpdateFile) e
return err return err
} }
includeDir := GetSitePath(website, SiteUpstreamDir) 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)) filePath := path.Join(includeDir, fmt.Sprintf("%s.conf", req.Name))
fileOp := files.NewFileOp() fileOp := files.NewFileOp()
oldContent, err := fileOp.GetContent(filePath) oldContent, err := fileOp.GetContent(filePath)
+72 -22
View File
@@ -24,6 +24,21 @@ import (
) )
func (w WebsiteService) OperateProxy(req request.WebsiteProxyConfig) (err error) { 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 ( var (
website model.Website website model.Website
par *parser.Parser par *parser.Parser
@@ -81,16 +96,8 @@ func (w WebsiteService) OperateProxy(req request.WebsiteProxyConfig) (err error)
if err != nil { if err != nil {
return return
} }
case "delete": default:
_ = fileOp.DeleteFile(includePath) return errors.New("unknown operate")
_ = 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)
} }
config.FilePath = includePath config.FilePath = includePath
@@ -107,8 +114,16 @@ func (w WebsiteService) OperateProxy(req request.WebsiteProxyConfig) (err error)
err = errors.New("invalid proxy config, no location found") err = errors.New("invalid proxy config, no location found")
return return
} }
location.UpdateDirective("proxy_pass", []string{req.ProxyPass}) safePass, err := nginx.NginxSafeString(req.ProxyPass, nginx.ModeURL)
location.UpdateDirective("proxy_set_header", []string{"Host", req.ProxyHost}) if err != nil {
return err
}
safeHeader, err := nginx.NginxSafeString(req.ProxyHost, nginx.ModeHost)
if err != nil {
return err
}
location.UpdateDirective("proxy_pass", []string{safePass})
location.UpdateDirective("proxy_set_header", []string{"Host", safeHeader})
location.ChangePath(req.Modifier, req.Match) location.ChangePath(req.Modifier, req.Match)
// Server Cache Settings // Server Cache Settings
if req.Cache { if req.Cache {
@@ -147,14 +162,26 @@ func (w WebsiteService) OperateProxy(req request.WebsiteProxyConfig) (err error)
} }
// CORS Settings // CORS Settings
if req.Cors { if req.Cors {
location.UpdateDirective("add_header", []string{"Access-Control-Allow-Origin", req.AllowOrigins, "always"}) safeAllowOrigins, err := nginx.NginxSafeString(req.AllowOrigins, nginx.ModeGeneric)
if err != nil {
return err
}
location.UpdateDirective("add_header", []string{"Access-Control-Allow-Origin", safeAllowOrigins, "always"})
if req.AllowMethods != "" { if req.AllowMethods != "" {
location.UpdateDirective("add_header", []string{"Access-Control-Allow-Methods", req.AllowMethods, "always"}) safeAllowMethods, err := nginx.NginxSafeString(req.AllowMethods, nginx.ModeAllowMethods)
if err != nil {
return err
}
location.UpdateDirective("add_header", []string{"Access-Control-Allow-Methods", safeAllowMethods, "always"})
} else { } else {
location.RemoveDirective("add_header", []string{"Access-Control-Allow-Methods"}) location.RemoveDirective("add_header", []string{"Access-Control-Allow-Methods"})
} }
if req.AllowHeaders != "" { if req.AllowHeaders != "" {
location.UpdateDirective("add_header", []string{"Access-Control-Allow-Headers", req.AllowHeaders, "always"}) safeAllowHeaders, err := nginx.NginxSafeString(req.AllowHeaders, nginx.ModeGeneric)
if err != nil {
return err
}
location.UpdateDirective("add_header", []string{"Access-Control-Allow-Headers", safeAllowHeaders, "always"})
} else { } else {
location.RemoveDirective("add_header", []string{"Access-Control-Allow-Headers"}) location.RemoveDirective("add_header", []string{"Access-Control-Allow-Headers"})
} }
@@ -391,24 +418,47 @@ func (w WebsiteService) ClearProxyCache(req request.NginxCommonReq) error {
} }
func (w WebsiteService) DeleteProxy(req request.WebsiteProxyDel) (err error) { func (w WebsiteService) DeleteProxy(req request.WebsiteProxyDel) (err error) {
fileOp := files.NewFileOp()
website, err := websiteRepo.GetFirst(repo.WithByID(req.ID)) website, err := websiteRepo.GetFirst(repo.WithByID(req.ID))
if err != nil { if err != nil {
return return
} }
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty) includeDir := GetSitePath(website, SiteProxyDir)
if err != nil { fileOp := files.NewFileOp()
return
}
includeDir := path.Join(nginxInstall.GetPath(), "www", "sites", website.Alias, "proxy")
if !fileOp.Stat(includeDir) { if !fileOp.Stat(includeDir) {
_ = fileOp.CreateDir(includeDir, 0755) return
} }
fileName := fmt.Sprintf("%s.conf", req.Name) fileName := fmt.Sprintf("%s.conf", req.Name)
includePath := path.Join(includeDir, fileName) includePath := path.Join(includeDir, fileName)
backName := fmt.Sprintf("%s.bak", req.Name) backName := fmt.Sprintf("%s.bak", req.Name)
backPath := path.Join(includeDir, backName) backPath := path.Join(includeDir, backName)
_ = fileOp.DeleteFile(includePath) _ = fileOp.DeleteFile(includePath)
_ = fileOp.DeleteFile(backPath) _ = fileOp.DeleteFile(backPath)
return updateNginxConfig(constant.NginxScopeServer, nil, &website) 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")
}
+12 -3
View File
@@ -4,6 +4,10 @@ import (
"bytes" "bytes"
"context" "context"
"fmt" "fmt"
"os"
"path"
"strings"
"github.com/1Panel-dev/1Panel/agent/app/dto" "github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/app/dto/request" "github.com/1Panel-dev/1Panel/agent/app/dto/request"
"github.com/1Panel-dev/1Panel/agent/app/dto/response" "github.com/1Panel-dev/1Panel/agent/app/dto/response"
@@ -12,9 +16,6 @@ import (
"github.com/1Panel-dev/1Panel/agent/cmd/server/nginx_conf" "github.com/1Panel-dev/1Panel/agent/cmd/server/nginx_conf"
"github.com/1Panel-dev/1Panel/agent/constant" "github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/utils/files" "github.com/1Panel-dev/1Panel/agent/utils/files"
"os"
"path"
"strings"
) )
func (w WebsiteService) UpdateRewriteConfig(req request.NginxRewriteUpdate) error { 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) contentByte, _ = nginx_conf.Rewrites.ReadFile(rewriteFile)
if contentByte == nil { if contentByte == nil {
customRewriteDir := GetOpenrestyDir(DefaultRewriteDir) 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))) customRewriteFile := path.Join(customRewriteDir, fmt.Sprintf("%s.conf", strings.ToLower(req.Name)))
contentByte, err = files.NewFileOp().GetContent(customRewriteFile) contentByte, err = files.NewFileOp().GetContent(customRewriteFile)
} }
@@ -90,6 +95,10 @@ func (w WebsiteService) OperateCustomRewrite(req request.CustomRewriteOperate) e
return err 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)) rewriteFile := path.Join(rewriteDir, fmt.Sprintf("%s.conf", req.Name))
switch req.Operate { switch req.Operate {
case "create": case "create":
+25
View File
@@ -1048,6 +1048,31 @@ func opWebsite(website *model.Website, operate string) error {
proxy := fmt.Sprintf("http://%s", website.Proxy) proxy := fmt.Sprintf("http://%s", website.Proxy)
server.UpdateRootProxy([]string{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 website.Status = constant.WebRunning
now := time.Now() now := time.Now()
-5
View File
@@ -4,11 +4,6 @@ base:
is_demo: false is_demo: false
is_offline: 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: log:
level: debug level: debug
time_zone: Asia/Shanghai time_zone: Asia/Shanghai
+1
View File
@@ -8,6 +8,7 @@ const (
AppOpenresty = "openresty" AppOpenresty = "openresty"
AppOpenclaw = "openclaw" AppOpenclaw = "openclaw"
AppCopaw = "copaw"
AppMysql = "mysql" AppMysql = "mysql"
AppMariaDB = "mariadb" AppMariaDB = "mariadb"
AppPostgresql = "postgresql" AppPostgresql = "postgresql"
+13 -2
View File
@@ -1,8 +1,9 @@
package cron package cron
import ( import (
"crypto/rand"
"fmt" "fmt"
mathRand "math/rand" "math/big"
"time" "time"
"github.com/1Panel-dev/1Panel/agent/app/model" "github.com/1Panel-dev/1Panel/agent/app/model"
@@ -43,7 +44,17 @@ func Run() {
if _, err := global.Cron.AddJob("@daily", job.NewSSLJob()); err != nil { if _, err := global.Cron.AddJob("@daily", job.NewSSLJob()); err != nil {
global.LOG.Errorf("can not add ssl corn job: %s", err.Error()) 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()) global.LOG.Errorf("can not add appstore corn job: %s", err.Error())
} }
if _, err := global.Cron.AddJob("0 3 */31 * *", job.NewBackupJob()); err != nil { if _, err := global.Cron.AddJob("0 3 */31 * *", job.NewBackupJob()); err != nil {
+1 -7
View File
@@ -2,13 +2,13 @@ package global
type ServerConfig struct { type ServerConfig struct {
Base Base `mapstructure:"base"` Base Base `mapstructure:"base"`
RemoteURL RemoteURL `mapstructure:"remote_url"`
Log LogConfig `mapstructure:"log"` Log LogConfig `mapstructure:"log"`
DockerConfig DockerConfig DockerConfig DockerConfig
} }
type Base struct { type Base struct {
Port string `mapstructure:"port"` Port string `mapstructure:"port"`
Edition string `mapstructure:"edition"` // [ cn / intl]
Version string `mapstructure:"version"` Version string `mapstructure:"version"`
EncryptKey string `mapstructure:"encrypt_key"` EncryptKey string `mapstructure:"encrypt_key"`
Mode string `mapstructure:"mode"` // xpack [ Enable / Disable ] Mode string `mapstructure:"mode"` // xpack [ Enable / Disable ]
@@ -17,12 +17,6 @@ type Base struct {
IsOffLine bool `mapstructure:"is_offline"` 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 { type SystemDir struct {
BaseDir string BaseDir string
DbDir string DbDir string
+19
View File
@@ -40,3 +40,22 @@ var (
TaskCtxMap = make(map[string]context.CancelFunc) 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
View File
@@ -50,7 +50,7 @@ require (
golang.org/x/crypto v0.46.0 golang.org/x/crypto v0.46.0
golang.org/x/net v0.48.0 golang.org/x/net v0.48.0
golang.org/x/oauth2 v0.34.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 golang.org/x/text v0.32.0
google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38
gopkg.in/ini.v1 v1.67.0 gopkg.in/ini.v1 v1.67.0
@@ -59,7 +59,7 @@ require (
) )
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/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
github.com/BurntSushi/toml v1.5.0 // indirect github.com/BurntSushi/toml v1.5.0 // indirect
github.com/Microsoft/go-winio v0.6.2 // 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/bytedance/sonic/loader v0.1.1 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cenkalti/backoff/v5 v5.0.3 // 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 v1.8.4 // indirect
github.com/clbanning/mxj/v2 v2.7.0 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect
github.com/cloudwego/base64x v0.1.4 // 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/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/httptrace/otelhttptrace v0.60.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.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/otlpmetric/otlpmetricgrpc v1.35.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace 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/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 // indirect
go.opentelemetry.io/otel/metric v1.38.0 // indirect go.opentelemetry.io/otel/metric v1.40.0 // indirect
go.opentelemetry.io/otel/sdk v1.38.0 // indirect go.opentelemetry.io/otel/sdk v1.40.0 // indirect
go.opentelemetry.io/otel/sdk/metric v1.38.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.40.0 // indirect
go.opentelemetry.io/otel/trace v1.38.0 // indirect go.opentelemetry.io/otel/trace v1.40.0 // indirect
go.opentelemetry.io/proto/otlp v1.5.0 // indirect go.opentelemetry.io/proto/otlp v1.5.0 // indirect
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect
+14 -15
View File
@@ -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.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= 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= 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.1 h1:YpjwWWlNmGIDyXOn8zLzqiD+9TyIlPhGFG96P39uBpw=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= 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 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= 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= 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 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= 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/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 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.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2/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/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 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= 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.40.0 h1:oA5YeOcpRTXq6NN7frwmwFR0Cn3RhTVZvXsP4duvCms=
go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM= 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 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/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= 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/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 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/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.40.0 h1:rcZe317KPftE2rstWIBitCdVp89A2HqjkxR3c11+p9g=
go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI= go.opentelemetry.io/otel/metric v1.40.0/go.mod h1:ib/crwQH7N3r5kfiBZQbwrTge743UDc7DTFVZrrXnqc=
go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E= go.opentelemetry.io/otel/sdk v1.40.0 h1:KHW/jUzgo6wsPh9At46+h4upjtccTmuZCFAc9OJ71f8=
go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg= go.opentelemetry.io/otel/sdk v1.40.0/go.mod h1:Ph7EFdYvxq72Y8Li9q8KebuYUr2KoeyHx0DRMKrYBUE=
go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM= go.opentelemetry.io/otel/sdk/metric v1.40.0 h1:mtmdVqgQkeRxHgRv4qhyJduP3fYJRMX4AtAlbuWdCYw=
go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA= go.opentelemetry.io/otel/sdk/metric v1.40.0/go.mod h1:4Z2bGMf0KSK3uRjlczMOeMhKU2rhUqdWNoKcYrtcBPg=
go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE= go.opentelemetry.io/otel/trace v1.40.0 h1:WA4etStDttCSYuhwvEa8OP8I5EWu24lkOzp+ZYblVjw=
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs= 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 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 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4=
go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= 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.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.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.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= 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/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-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+285 -295
View File
@@ -1,115 +1,115 @@
ErrInvalidParams: 'Request parameter error: {{ .detail }}' ErrInvalidParams: 'Bad request: {{ .detail }}'
ErrTokenParse: 'Token generation error: {{ .detail }}' ErrTokenParse: 'Token error: {{ .detail }}'
ErrInitialPassword: 'Original password is incorrect' ErrInitialPassword: 'Original password is incorrect'
ErrInternalServer: 'Internal server error: {{ .detail }}' ErrInternalServer: 'Internal server error: {{ .detail }}'
ErrRecordExist: 'Record already exists' ErrRecordExist: 'Record already exists'
ErrRecordNotFound: 'Record not found' ErrRecordNotFound: 'Record not found'
ErrStructTransform: 'Type conversion failed: {{ .err }}' ErrStructTransform: 'Type conversion failed: {{ .err }}'
ErrNotLogin: 'User not logged in: {{ .detail }}' ErrNotLogin: 'Not logged in: {{ .detail }}'
ErrPasswordExpired: 'The current password has expired: {{ .detail }}' ErrPasswordExpired: 'Password expired: {{ .detail }}'
ErrNotSupportType: 'The system does not support the current type: {{ .name }}' ErrNotSupportType: 'Unsupported type: {{ .name }}'
ErrProxy: 'Request error, please check the node status: {{ .detail }}' ErrProxy: 'Request failed: {{ .detail }}'
ErrApiConfigStatusInvalid: 'Access to the API interface is prohibited: {{ .detail }}' ErrApiConfigStatusInvalid: 'API access disabled: {{ .detail }}'
ErrApiConfigKeyInvalid: 'API interface key error: {{ .detail }}' ErrApiConfigKeyInvalid: 'Invalid API key: {{ .detail }}'
ErrApiConfigIPInvalid: 'The IP used to call the API interface is not in the whitelist: {{ .detail }}' ErrApiConfigIPInvalid: 'IP not in API allowlist: {{ .detail }}'
ErrApiConfigDisable: 'This interface prohibits the use of API interface calls: {{ .detail }}' ErrApiConfigDisable: 'Endpoint not allowed via API: {{ .detail }}'
ErrApiConfigKeyTimeInvalid: 'API interface timestamp error: {{ .detail }}' ErrApiConfigKeyTimeInvalid: 'Invalid API timestamp: {{ .detail }}'
ErrShutDown: "Command manually terminated!" ErrShutDown: 'Command stopped manually'
ErrMinQuickJump: "Please set at least one quick jump entry!" ErrMinQuickJump: 'Set at least one quick jump entry'
ErrMaxQuickJump: "You can set up to four quick jump entries!" ErrMaxQuickJump: 'At most 4 quick jump entries'
#common #common
ErrUsernameIsExist: 'Username already exists' ErrUsernameIsExist: 'Username already exists'
ErrNameIsExist: 'Name already exists' ErrNameIsExist: 'Name already exists'
ErrDemoEnvironment: 'Demo server, this operation is forbidden!' ErrDemoEnvironment: 'Disabled in demo environment'
ErrCmdTimeout: 'Command execution timed out!' ErrCmdTimeout: 'Command timed out'
ErrCmdIllegal: 'There are illegal characters in the execution command, please modify it and try again!' ErrCmdIllegal: 'Command has invalid characters'
ErrPortExist: '{{ .port }} port is already occupied by {{ .type }} [{{ .name }}]' ErrPortExist: '{{ .port }} port is already occupied by {{ .type }} [{{ .name }}]'
TYPE_APP: 'Application' TYPE_APP: 'Application'
TYPE_RUNTIME: 'Runtime environment' TYPE_RUNTIME: 'Runtime'
TYPE_DOMAIN: 'Domain Name' TYPE_DOMAIN: 'Domain'
ErrTypePort: 'Port {{ .name }} format is incorrect' ErrTypePort: 'Invalid port format: {{ .name }}'
ErrTypePortRange: 'The port range needs to be between 1-65535' ErrTypePortRange: 'Port range must be 1-65535'
Success: 'Success' Success: 'Success'
Failed: 'Failed' Failed: 'Failed'
SystemRestart: 'Task interrupted due to system restart' SystemRestart: 'Task interrupted by system restart'
ErrGroupIsDefault: 'Default group, cannot be deleted' 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" Decrypt: "Decrypt"
#agent #agent
ErrAgentAccountBound: 'This account is bound to an agent and cannot be deleted. Please check and try again!' ErrAgentAccountBound: 'Account is bound to an agent and cannot be deleted'
ErrAgentAccountUnavailable: 'The account connection information is unavailable. Error: {{ .err }}. Please check and try again!' ErrAgentAccountUnavailable: 'Account connection unavailable: {{ .err }}'
ErrAgentProviderNotSupported: 'This agent provider is not supported. Please check and try again!' ErrAgentProviderNotSupported: 'Unsupported agent provider'
ErrAgentAccountRequired: 'Please select an agent account and try again.' ErrAgentAccountRequired: 'Select an agent account first'
ErrAgentAccountNotVerified: 'The account has not been verified. Please check and try again!' ErrAgentAccountNotVerified: 'Agent account not verified'
ErrAgentProviderMismatch: 'The account provider does not match. Please check and try again!' ErrAgentProviderMismatch: 'Agent provider mismatch'
ErrAgentBaseURLRequired: 'Base URL cannot be empty. Please check and try again!' ErrAgentBaseURLRequired: 'Base URL is required'
ErrAgentApiKeyRequired: 'API Key cannot be empty. Please check and try again!' ErrAgentApiKeyRequired: 'API key is required'
ErrAgentComposeRequired: 'Custom compose content cannot be empty. Please check and try again!' ErrAgentComposeRequired: 'Compose content is required'
ErrAgentIDRequired: 'Agent ID cannot be empty. Please check and try again!' ErrAgentIDRequired: 'Agent ID is required'
ErrAgentAccountIDRequired: 'Account ID cannot be empty. Please check and try again!' ErrAgentAccountIDRequired: 'Account ID is required'
#backup #backup
Localhost: 'Local Machine' Localhost: 'Local'
ErrBackupInUsed: 'The backup account has been used in the scheduled task and cannot be deleted.' ErrBackupInUsed: 'Backup account is in use by a scheduled task'
ErrBackupCheck: 'Backup account test connection failed {{ .err }}' ErrBackupCheck: 'Backup account connectivity test failed: {{ .err }}'
ErrBackupLocalDelete: 'Deleting the local server backup account is not supported yet' ErrBackupLocalDelete: 'Local backup accounts cannot be deleted'
ErrBackupLocalCreate: 'Creating local server backup accounts is not supported yet' ErrBackupLocalCreate: 'Local backup accounts cannot be created'
#app #app
ErrPortInUsed: '{{ .detail }} port is already occupied!' 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' ErrNotInstall: 'Application not installed'
ErrPortInOtherApp: '{{ .port }} port is already occupied by application {{ .apps }}!' ErrPortInOtherApp: '{{ .port }} port is already occupied by application {{ .apps }}!'
ErrDbUserNotValid: 'Existing database, username and password do not match!' ErrDbUserNotValid: 'Database username/password mismatch'
ErrUpdateBuWebsite: 'The application was updated successfully, but the website configuration file modification failed. Please check the configuration! ' ErrUpdateBuWebsite: 'App updated, but website config update failed'
Err1PanelNetworkFailed: 'Default container network creation failed! {{ .detail }}' Err1PanelNetworkFailed: 'Default container network creation failed! {{ .detail }}'
ErrFileParse: 'Application docker-compose file parsing failed!' ErrFileParse: 'Failed to parse app docker-compose file'
ErrInstallDirNotFound: 'The installation directory does not exist. If you need to uninstall, please select Force Uninstall' ErrInstallDirNotFound: 'Install directory not found; use Force Uninstall'
AppStoreIsUpToDate: 'The app store is already the latest version' 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' LocalAppVersionNull: 'App {{ .name }} has no synced version'
LocalAppVersionErr: '{{ .name }} sync version {{ .version }} failed! {{ .err }}' LocalAppVersionErr: 'Failed to sync {{ .name }} version {{ .version }}: {{ .err }}'
ErrFileNotFound: '{{ .name }} file does not exist' 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' 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' ErrContainerName: 'Container name already exists'
ErrCreateHttpClient: 'Failed to create request {{ .err }}' ErrCreateHttpClient: 'Failed to create HTTP request: {{ .err }}'
ErrHttpReqTimeOut: 'Request timed out {{ .err }}' ErrHttpReqTimeOut: 'HTTP request timed out: {{ .err }}'
ErrHttpReqFailed: 'Request failed {{ .err }}' ErrHttpReqFailed: 'HTTP request failed: {{ .err }}'
ErrNoSuchHost: 'Unable to find the requested server {{ .err }}' ErrNoSuchHost: 'Host resolve failed: {{ .err }}'
ErrHttpReqNotFound: 'The requested resource {{ .err }} could not be found' ErrHttpReqNotFound: 'Requested resource not found: {{ .err }}'
ErrContainerNotFound: '{{ .name }} container does not exist' ErrContainerNotFound: '{{ .name }} container does not exist'
ErrContainerMsg: '{{ .name }} container is abnormal. Please check the log on the container page for details' ErrContainerMsg: 'Container {{ .name }} is abnormal; check logs'
ErrAppBackup: '{{ .name }} application backup failed {{ .err }}' ErrAppBackup: 'App backup failed: {{ .name }} {{ .err }}'
ErrVersionTooLow: 'The current 1Panel version is too low to update the App Store. Please upgrade the version before operating.' ErrVersionTooLow: '1Panel version too low to update App Store'
ErrAppNameExist: 'The application name already exists' ErrAppNameExist: 'The application name already exists'
AppStoreIsSyncing: 'The App Store is syncing, please try again later' AppStoreIsSyncing: 'App Store is syncing; try again later'
ErrGetCompose: 'Failed to obtain the docker-compose.yml file! {{ .detail }}' ErrGetCompose: 'Failed to read docker-compose.yml: {{ .detail }}'
ErrAppWarn: 'Abnormal status, please check the log' ErrAppWarn: 'App status abnormal; check logs'
ErrAppParamKey: 'Parameter {{ .name }} field is abnormal' ErrAppParamKey: 'Invalid app parameter: {{ .name }}'
ErrAppUpgrade: 'Application {{ .name }} upgrade failed {{ .err }}' ErrAppUpgrade: 'App upgrade failed: {{ .name }} {{ .err }}'
AppRecover: 'Rollback application {{ .name }}' AppRecover: 'Rollback application {{ .name }}'
PullImageStart: 'Start pulling image [{{ .name }}]' PullImageStart: 'Pull image [{{ .name }}]'
PullImageSuccess: 'Image pull successful' PullImageSuccess: 'Image pulled'
AppStoreIsLastVersion: 'The App Store is already the latest version' AppStoreSyncSuccess: 'App Store synced'
AppStoreSyncSuccess: 'App Store synchronization successful' SyncAppDetail: 'Sync app config'
SyncAppDetail: 'Synchronize application configuration' AppVersionNotMatch: 'Skip {{ .name }}: requires newer 1Panel'
AppVersionNotMatch: '{{ .name }} application requires a higher 1Panel version, skipping synchronization' MoveSiteDir: 'Website dir changed; migrate OpenResty dir to {{ .name }}'
MoveSiteDir: "Detected website directory change. Need to migrate OpenResty website directory to {{ .name }}" MoveSiteDirSuccess: 'Website dir migrated'
MoveSiteDirSuccess: 'Successful migration of website directory'
DeleteRuntimePHP: 'Delete PHP runtime' DeleteRuntimePHP: 'Delete PHP runtime'
CustomAppStoreFileValid: 'App store packages need to be in .tar.gz format' CustomAppStoreFileValid: 'App Store package must be .tar.gz'
PullImageTimeout: 'Pull image timeout, please try to increase the image acceleration or change to another image acceleration' PullImageTimeout: 'Image pull timed out; try another mirror'
ErrAppIsDown: '{{ .name }} application status is abnormal, please check' ErrAppIsDown: 'App {{ .name }} is abnormal'
ErrCustomApps: 'There is an installed application, please uninstall it first' ErrCustomApps: 'Installed apps detected; uninstall first'
ErrCustomRuntimes: 'There is an installed runtime environment, please delete it first' ErrCustomRuntimes: 'Installed runtimes detected; delete first'
ErrAppVersionDeprecated: "The {{ .name }} application is not compatible with the current 1Panel version, skipped" 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" ErrDockerFailed: 'Docker is abnormal; check service status'
ErrDockerComposeCmdNotFound: "The Docker Compose command does not exist, please install this command on the host machine first" ErrDockerComposeCmdNotFound: 'Docker Compose not found on host'
UseExistImage: 'Failed to pull image, using existing image' UseExistImage: 'Image exists; using existing image'
ErrDatabaseNotFound: 'Database not found: {{ .name }}'
#ssh #ssh
ExportIP: "Login IP" ExportIP: "Login IP"
@@ -121,42 +121,42 @@ ExportStatus: "Login Status"
ExportDate: "Time" ExportDate: "Time"
#file #file
ErrFileCanNotRead: 'This file does not support preview' ErrFileCanNotRead: 'File preview is not supported'
ErrFileToLarge: 'The file is larger than 10M and cannot be opened' ErrFileToLarge: 'File is larger than 10 MB'
ErrPathNotFound: 'Directory does not exist' 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!' ErrLinkPathNotFound: 'The target path does not exist!'
ErrFileIsExist: 'The file or folder already exists!' ErrFileIsExist: 'The file or folder already exists!'
ErrFileUpload: '{{ .name }} failed to upload file {{ .detail }}' ErrFileUpload: 'Upload failed: {{ .name }} {{ .detail }}'
ErrFileDownloadDir: 'Download folder is not supported' ErrFileDownloadDir: 'Directory download is not supported'
ErrCmdNotFound: '{{ .name}} command does not exist, please install this command on the host first' ErrCmdNotFound: 'Command not found: {{ .name }}'
ErrSourcePathNotFound: 'Source directory does not exist' ErrSourcePathNotFound: 'Source directory does not exist'
ErrFavoriteExist: 'This path has already been favorited' ErrFavoriteExist: 'Path already in favorites'
ErrInvalidChar: 'Illegal characters are not allowed' ErrInvalidChar: 'Illegal characters are not allowed'
ErrPathNotDelete: 'The selected directory cannot be deleted' ErrPathNotDelete: 'The selected directory cannot be deleted'
ErrLogFileToLarge: "The log file exceeds 500MB and cannot be opened" ErrLogFileToLarge: 'Log file exceeds 500 MB'
FileDropFailed: "Failed to clean up file {{ .name }}: {{ .err }}" FileDropFailed: 'File cleanup failed: {{ .name }} {{ .err }}'
FileDropSuccess: "Successfully cleaned up file {{ .name }}, cleaned {{ .count }} files, freed {{ .size }} disk space" FileDropSuccess: 'Cleaned {{ .name }}; files: {{ .count }}, freed: {{ .size }}'
FileDropSum: "File cleanup completed successfully, total {{ .count }} files cleaned, total {{ .size }} disk space freed" FileDropSum: 'Cleanup done; files: {{ .count }}, freed: {{ .size }}'
ErrBadDecrypt: "Compressed package decryption password error, decompression failed, please check and try again!" ErrBadDecrypt: 'Wrong archive password; extract failed'
#website #website
ErrAliasIsExist: 'Alias already exists' ErrAliasIsExist: 'Alias already exists'
ErrBackupMatch: 'The backup file does not match some of the current website data {{ .detail }}' ErrBackupMatch: 'Backup data mismatch: {{ .detail }}'
ErrBackupExist: 'The corresponding part of the source data in the backup file does not exist {{ .detail }}' ErrBackupExist: 'Backup source data missing: {{ .detail }}'
ErrPHPResource: 'The local operating environment does not support switching! ' ErrPHPResource: 'Switching local runtime is not supported'
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' ErrPathPermission: 'Non-1000:1000 folder in index dir may cause Access denied'
ErrDomainIsUsed: 'The domain name is already used by the website [{{ .name }}]' ErrDomainIsUsed: 'The domain name is already used by the website [{{ .name }}]'
ErrDomainFormat: '{{ .name }} domain name format is incorrect' ErrDomainFormat: 'Invalid domain format: {{ .name }}'
ErrDefaultAlias: 'default is a reserved code, please use another code' ErrDefaultAlias: 'default is reserved; use another alias'
ErrParentWebsite: 'You need to delete the subsite {{ .name }} first' ErrParentWebsite: 'Delete subsite {{ .name }} first'
ErrBuildDirNotFound: 'The build directory does not exist' ErrBuildDirNotFound: 'The build directory does not exist'
ErrImageNotExist: 'The operating environment {{ .name }} image does not exist, please re-edit the operating environment' ErrImageNotExist: 'Runtime image not found: {{ .name }}'
ErrProxyIsUsed: "Load balancing has been used by reverse proxy, cannot be deleted" ErrProxyIsUsed: 'Load balancer is used by reverse proxy'
ErrSSLValid: 'Certificate file is abnormal, please check the certificate status!' ErrSSLValid: 'Certificate file is invalid'
ErrWebsiteDir: "Please select a directory within the website directory." ErrWebsiteDir: 'Select a subdirectory under the website directory'
ErrComposerFileNotFound: "composer.json file does not exist" 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' Status: 'Status'
start: 'Start' start: 'Start'
stop: 'Stop' stop: 'Stop'
@@ -166,157 +166,157 @@ pause: 'Pause'
unpause: 'Resume' unpause: 'Resume'
remove: 'Delete' remove: 'Delete'
delete: 'Delete' delete: 'Delete'
ErrDefaultWebsite: 'Default website has been set, please cancel it before setting!' ErrDefaultWebsite: 'Default website already set; unset it first'
SSL: 'Certificate' SSL: 'Certificate'
Set: 'Settings' Set: 'Settings'
#ssl #ssl
ErrSSLCannotDelete: 'The {{ .name }} certificate is being used by a website and cannot be deleted' ErrSSLCannotDelete: 'Certificate {{ .name }} is in use by a website'
ErrAccountCannotDelete: 'The account is associated with a certificate and cannot be deleted' ErrAccountCannotDelete: 'Account is linked to a certificate and cannot be deleted'
ErrSSLApply: 'Certificate renewal successful, openresty reload failed, please check the configuration!' ErrSSLApply: 'Certificate renewed; OpenResty reload failed'
ErrEmailIsExist: 'The mailbox already exists' ErrEmailIsExist: 'Email already exists'
ErrSSLKeyNotFound: 'The private key file does not exist' ErrSSLKeyNotFound: 'The private key file does not exist'
ErrSSLCertificateNotFound: 'The certificate file does not exist' ErrSSLCertificateNotFound: 'The certificate file does not exist'
ErrSSLKeyFormat: 'Private key file verification failed' 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' ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid or EabHmacKey cannot be blank'
ErrOpenrestyNotFound: 'Http mode requires Openresty to be installed first' ErrOpenrestyNotFound: 'HTTP mode requires OpenResty'
ApplySSLStart: 'Start applying for a certificate, domain name [{{ .domain }}] application method [{{ .type }}] ' ApplySSLStart: 'Starting certificate request. Domain: [{{ .domain }}], method: [{{ .type }}]'
dnsAccount: 'DNS Auto' dnsAccount: 'DNS Auto'
dnsManual: 'DNS Manual' dnsManual: 'DNS Manual'
http: 'HTTP' http: 'HTTP'
ApplySSLFailed: 'Application for [{{ .domain }}] certificate failed, {{ .detail }} ' ApplySSLFailed: 'Failed to request certificate for [{{ .domain }}]: {{ .detail }}'
ApplySSLSuccess: 'Apply for [{{ .domain }}] certificate successfully! !' ApplySSLSuccess: 'Certificate issued for [{{ .domain }}]'
DNSAccountName: 'DNS account [{{ .name }}] vendor [{{ .type }}]' DNSAccountName: 'DNS account [{{ .name }}], provider [{{ .type }}]'
PushDirLog: 'Certificate pushed to directory [{{ .path }}] {{ .status }}' PushDirLog: 'Certificate pushed to directory [{{ .path }}] {{ .status }}'
ErrDeleteCAWithSSL: 'The current organization has a certificate that has been issued and cannot be deleted.' ErrDeleteCAWithSSL: 'CA has issued certificates; cannot delete'
ErrDeleteWithPanelSSL: 'Panel SSL configuration uses this certificate and cannot be deleted' ErrDeleteWithPanelSSL: 'Certificate is in use by Panel SSL settings'
ErrDefaultCA: 'The default authority cannot be deleted' 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 }}' ErrUpdateWebsiteSSL: '{{ .name }} website certificate update failed: {{ .err }}'
ApplyWebSiteSSLSuccess: 'Update website certificate successfully' ApplyWebSiteSSLSuccess: 'Website certificate updated'
ErrExecShell: 'Failed to execute script {{ .err }}' ErrExecShell: 'Failed to execute script {{ .err }}'
ExecShellStart: 'Start executing the script' ExecShellStart: 'Run script'
ExecShellSuccess: 'Script execution successful' ExecShellSuccess: 'Script succeeded'
StartUpdateSystemSSL: 'Start updating system certificate' StartUpdateSystemSSL: 'Update system certificate'
UpdateSystemSSLSuccess: 'Update system certificate successfully' UpdateSystemSSLSuccess: 'System certificate updated'
ErrWildcardDomain: 'Unable to apply for wildcard domain name certificate in HTTP mode' ErrWildcardDomain: 'Wildcard certificates are not supported in HTTP mode'
ErrApplySSLCanNotDelete: "The certificate {{.name}} being applied for cannot be deleted, please try again later." ErrApplySSLCanNotDelete: 'Certificate {{ .name }} is being issued and cannot be deleted yet'
StartPushSSLToNode: "Starting to push certificate to node" StartPushSSLToNode: 'Push certificate to node'
PushSSLToNodeFailed: "Failed to push certificate to node: {{ .err }}" PushSSLToNodeFailed: "Failed to push certificate to node: {{ .err }}"
PushSSLToNodeSuccess: "Successfully pushed certificate to node" PushSSLToNodeSuccess: 'Certificate pushed to node'
#mysql #mysql
ErrUserIsExist: 'The current user already exists, please re-enter' ErrUserIsExist: 'User already exists'
ErrDatabaseIsExist: 'The current database already exists, please re-enter' ErrDatabaseIsExist: 'Database already exists'
ErrExecTimeOut: 'SQL execution timed out, please check the database' ErrExecTimeOut: 'SQL execution timed out'
ErrRemoteExist: 'The remote database already exists with this name, please modify it and try again' ErrRemoteExist: 'Remote database name already exists'
ErrLocalExist: 'The name already exists in the local database, please modify it and try again' ErrLocalExist: 'Local database name already exists'
RemoteBackup: "To back up the remote database, the local container database service needs to be started first using the image {{ .name }}, please wait..." RemoteBackup: 'Start local DB container with image {{ .name }} before backing up remote DB'
RemoteRecover: "To restore the remote database, the local container database service needs to be started first using the image {{ .name }}, please wait..." RemoteRecover: 'Start local DB container with image {{ .name }} before restoring remote DB'
Arg: "Argument" Arg: "Argument"
#redis #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 #container
ErrInUsed: "{{ .detail }} is in use and cannot be deleted!" ErrInUsed: "{{ .detail }} is in use and cannot be deleted!"
ErrObjectInUsed: "This object is in use and cannot be deleted!" ErrObjectInUsed: "This object is in use and cannot be deleted!"
ErrObjectBeDependent: "This image is depended on by other images and cannot be deleted!" ErrObjectBeDependent: "This image is referenced by other images and cannot be deleted!"
ErrPortRules: 'Port number does not match, please re-enter!' ErrPortRules: 'Port count does not match'
ErrPgImagePull: 'Image pull timed out, please configure image acceleration or manually pull the {{ .name }} image and try again' ErrPgImagePull: 'Image pull timed out; configure acceleration or pull {{ .name }} manually'
PruneHelper: "This cleanup {{ .name }} freed disk space {{ .size }}" PruneHelper: "Cleanup {{ .name }} released {{ .size }} disk space"
ImageRemoveHelper: "Deleted image {{ .name }}, freeing {{ .size }} disk space" ImageRemoveHelper: "Removed image {{ .name }}, released {{ .size }} disk space"
BuildCache: "Build cache" BuildCache: 'Build Cache'
Volume: "Storage volume" Volume: 'Volume'
Network: "Network" Network: "Network"
PruneStart: "Cleaning in progress, please wait..." PruneStart: 'Cleaning in progress'
#runtime #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' ErrImageBuildErr: 'Image build failed'
ErrImageExist: "Image already exists! Please modify the image name." ErrImageExist: "Image already exists. Use a different image name."
ErrDelWithWebsite: 'The operating environment is already associated with a website and cannot be deleted' ErrDelWithWebsite: 'Runtime is linked to a website and cannot be deleted'
ErrRuntimeStart: 'Startup failed' ErrRuntimeStart: 'Startup failed'
ErrPackageJsonNotFound: 'package.json file does not exist' ErrPackageJsonNotFound: 'package.json file does not exist'
ErrScriptsNotFound: 'The scripts configuration item was not found in package.json' ErrScriptsNotFound: 'No scripts section found in package.json'
ErrContainerNameNotFound: 'Unable to get container name, please check .env file' ErrContainerNameNotFound: 'Container name not found; check .env'
ErrNodeModulesNotFound: 'The node_modules folder does not exist! Please edit the runtime environment or wait for the runtime environment to start successfully' ErrNodeModulesNotFound: 'node_modules not found; edit runtime or wait for startup'
ErrContainerNameIsNull: 'Container name does not exist' ErrContainerNameIsNull: 'Container name is empty'
ErrPHPPortIsDefault: "Port 9000 is the default port, please modify and try again" ErrPHPPortIsDefault: 'Port 9000 is reserved as default; use another port'
ErrPHPRuntimePortFailed: "The port {{ .name }} is already used by the current runtime environment, please modify and try again" ErrPHPRuntimePortFailed: 'Port {{ .name }} is already used by this runtime'
#tool #tool
ErrConfigNotFound: 'Configuration file does not exist' ErrConfigNotFound: 'Configuration file does not exist'
ErrConfigParse: 'The configuration file format is incorrect' ErrConfigParse: 'Invalid configuration file format'
ErrConfigIsNull: 'Configuration file cannot be empty' ErrConfigIsNull: 'Configuration file cannot be empty'
ErrConfigDirNotFound: 'The running directory does not exist' ErrConfigDirNotFound: 'Run directory not found'
ErrConfigAlreadyExist: 'A configuration file with the same name already exists' ErrConfigAlreadyExist: 'Configuration file with the same name already exists'
ErrUserFindErr: 'User {{ .name }} search failed {{ .err }}' ErrUserFindErr: 'Failed to find user {{ .name }}: {{ .err }}'
#cronjob #cronjob
CutWebsiteLogSuccess: '{{ .name }} website log cut successfully, backup path {{ .path }}' CutWebsiteLogSuccess: 'Website log rotated: {{ .name }} (backup: {{ .path }})'
HandleShell: 'Execute script {{ .name }}' HandleShell: 'Run script {{ .name }}'
HandleCurl: "Access URL {{ .name }}" HandleCurl: 'Request URL {{ .name }}'
HandleNtpSync: 'System time synchronization' HandleNtpSync: 'Sync system time'
HandleSystemClean: 'System cache cleanup' HandleSystemClean: 'Clean system cache'
SystemLog: 'System Log' SystemLog: 'System Log'
CutWebsiteLog: 'Rotate Website Log' CutWebsiteLog: 'Rotate Website Log'
FileOrDir: 'Directory / File' FileOrDir: 'Directory / File'
UploadFile: 'Uploading backup file {{ .file }} to {{ .backup }}' UploadFile: 'Upload backup {{ .file }} to {{ .backup }}'
Upload: "Upload" Upload: "Upload"
IgnoreBackupErr: "Backup failed, error: {{ .detail }}, ignoring this error..." IgnoreBackupErr: 'Backup failed: {{ .detail }} (ignored)'
IgnoreUploadErr: "Upload failed, error: {{ .detail }}, ignoring this error..." IgnoreUploadErr: 'Upload failed: {{ .detail }} (ignored)'
LoadBackupFailed: "Failed to get backup account connection, error: {{ .detail }}" LoadBackupFailed: 'Failed to get backup account connection info: {{ .detail }}'
InExecuting: "The current task is being executed, please do not repeat the execution!" InExecuting: 'Task is already running'
NoSuchResource: "No backup content found in the database, skipping..." NoSuchResource: 'No backup records found; skipped'
CleanLog: "Clean Log" CleanLog: 'Clean logs'
CleanLogByName: "Clean {{.name}} Log" CleanLogByName: 'Clean {{ .name }} logs'
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." WafIpGroupNotFound: "WAF IP group not found. Go to [Advanced Features -> WAF -> Black/White List -> IP Group] and add one using Remote Download."
#toolbox #toolbox
ErrNotExistUser: 'The current user does not exist, please modify and try again!' ErrNotExistUser: 'User does not exist'
ErrBanAction: 'Setting failed. The current {{ .name }} service is unavailable. Please check and try again!' ErrBanAction: 'Config failed: service {{ .name }} unavailable'
ErrClamdscanNotFound: 'The clamdscan command was not detected, please refer to the documentation to install it!' ErrClamdscanNotFound: 'clamdscan command not found'
TaskSwapSet: "Set Swap" TaskSwapSet: 'Set swap'
SetSwap: "Set Swap {{ .path }} - {{ .size }}" SetSwap: "Set Swap {{ .path }} - {{ .size }}"
CreateSwap: "Create Swap File" CreateSwap: 'Create swap file'
FormatSwap: "Format Swap File" FormatSwap: 'Format swap file'
EnableSwap: "Enable Swap" EnableSwap: 'Enable swap'
#tamper #tamper
CleanTamperSetting: "Clean up historical protection settings" CleanTamperSetting: 'Clean historical protection settings'
SetTamperWithRules: "Start directory protection according to rules" SetTamperWithRules: 'Enable directory protection by rules'
ProtectDir: "Protect directory {{ .name }}" ProtectDir: "Protect directory {{ .name }}"
IgnoreFile: "Protect file {{ .name }}" IgnoreFile: "Protect file {{ .name }}"
TamperSetSuccessful: "Protection settings completed, start monitoring the following directories:" TamperSetSuccessful: 'Protection set. Monitoring these directories:'
#waf #waf
ErrScope: 'Modifying this configuration is not supported' ErrScope: 'This config cannot be changed'
ErrStateChange: 'State change failed' ErrStateChange: 'Failed to change state'
ErrRuleExist: 'Rule already exists' ErrRuleExist: 'Rule already exists'
ErrRuleNotExist: 'Rule does not exist' ErrRuleNotExist: 'Rule does not exist'
ErrParseIP: 'Wrong IP format' ErrParseIP: 'Invalid IP format'
ErrDefaultIP: 'default is a reserved name, please change it to another name' ErrDefaultIP: 'default is reserved; use another name'
ErrGroupInUse: 'IP group is used by blacklist/whitelist and cannot be deleted' ErrGroupInUse: 'IP group is used by blacklist/whitelist rules'
ErrIPGroupAclUse: "IP group is used by custom rules of website {{ .name }}, cannot be deleted" ErrIPGroupAclUse: 'IP group is used by website {{ .name }} custom rules'
ErrGroupExist: 'IP group name already exists' ErrGroupExist: 'IP group name already exists'
ErrIPRange: 'Wrong IP range' ErrIPRange: 'Invalid IP range'
ErrIPExist: 'IP already exists' ErrIPExist: 'IP already exists'
urlDefense: 'URL rules' urlDefense: 'URL rules'
urlHelper: 'Prohibited URL' urlHelper: 'Blocked URL'
dirFilter: 'Directory filter' dirFilter: 'Directory filter'
xss: 'XSS' xss: 'XSS'
phpExec: 'PHP script execution' phpExec: 'PHP script execution'
oneWordTrojan: 'One Word Trojan' oneWordTrojan: 'One Word Trojan'
appFilter: 'Apply dangerous directory filtering' appFilter: 'App dangerous directory filtering'
webshell: 'Webshell' webShell: 'WebShell'
args: 'Parameter rules' args: 'Parameter rules'
protocolFilter: 'Protocol filtering' protocolFilter: 'Protocol filtering'
javaFileter: 'Java dangerous file filter' javaFilter: 'Java dangerous file filtering'
scannerFilter: 'Scanner filter' scannerFilter: 'Scanner filter'
escapeFilter: 'escape filter' escapeFilter: 'Escape filtering'
customRule: 'Custom rule' customRule: 'Custom rules'
httpMethod: 'HTTP method filtering' httpMethod: 'HTTP method filtering'
fileExt: 'File upload restrictions' fileExt: 'File upload restrictions'
defaultIpBlack: 'Malicious IP group' defaultIpBlack: 'Malicious IP group'
@@ -331,8 +331,8 @@ notFoundCount: '404 Rate Limit'
headerDefense: 'Header rules' headerDefense: 'Header rules'
defaultUaBlack: 'User-Agent rules' defaultUaBlack: 'User-Agent rules'
methodWhite: 'HTTP rules' methodWhite: 'HTTP rules'
captcha: 'human-machine verification' captcha: 'Human verification'
fiveSeconds: '5 seconds verification' fiveSeconds: '5-second verification'
vulnCheck: 'Supplementary rules' vulnCheck: 'Supplementary rules'
acl: 'Custom rules' acl: 'Custom rules'
sql: 'SQL injection' sql: 'SQL injection'
@@ -340,19 +340,20 @@ cc: 'Access frequency limit'
defaultUrlBlack: 'URL rules' defaultUrlBlack: 'URL rules'
sqlInject: 'SQL injection' sqlInject: 'SQL injection'
ErrDBNotExist: 'Database does not exist' ErrDBNotExist: 'Database does not exist'
allow: 'allow' allow: 'Allow'
deny: 'deny' deny: 'Deny'
OpenrestyNotFound: 'Openresty is not installed' OpenrestyNotFound: 'OpenResty is not installed'
remoteIpIsNull: "IP list is empty" 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 #task
TaskStart: '{{ .name }} task starts [START]' TaskStart: '{{ .name }} [START]'
TaskEnd: '{{ .name }} Task completed [COMPLETED]' TaskEnd: '{{ .name }} [DONE]'
TaskFailed: '{{ .name }} task failed' TaskFailed: '{{ .name }} task failed'
TaskTimeout: '{{ .name }} timed out' TaskTimeout: '{{ .name }} timed out'
TaskSuccess: '{{ .name }} Task succeeded' TaskSuccess: '{{ .name }} succeeded'
TaskRetry: 'Start {{ .name }}th retry' TaskRetry: 'Retry #{{ .name }}'
SubTaskSuccess: '{{ .name }} succeeded' SubTaskSuccess: '{{ .name }} succeeded'
SubTaskFailed: '{{ .name }} failed: {{ .err }}' SubTaskFailed: '{{ .name }} failed: {{ .err }}'
TaskInstall: 'Install' TaskInstall: 'Install'
@@ -376,34 +377,34 @@ TaskImport: "Import"
TaskExport: "Export" TaskExport: "Export"
Website: 'Website' Website: 'Website'
App: 'Application' App: 'Application'
Runtime: 'Runtime environment' Runtime: 'Runtime'
Database: 'Database' Database: 'Database'
ConfigFTP: 'Create FTP user {{ .name }}' ConfigFTP: 'Create FTP user {{ .name }}'
ConfigOpenresty: 'Create Openresty configuration file' ConfigOpenresty: 'Create OpenResty config file'
InstallAppSuccess: 'Application {{ .name }} installed successfully' InstallAppSuccess: 'App {{ .name }} installed'
ConfigRuntime: 'Configure the runtime environment' ConfigRuntime: 'Configure runtime'
ConfigApp: 'Configuration Application' ConfigApp: 'Configure app'
SuccessStatus: '{{ .name }} succeeded' SuccessStatus: '{{ .name }} succeeded'
FailedStatus: '{{ .name }} failed {{ .err }}' FailedStatus: '{{ .name }} failed: {{ .err }}'
HandleLink: 'Handle application association' HandleLink: 'Process app links'
HandleDatabaseApp: 'Handling application parameters' HandleDatabaseApp: 'Process app parameters'
ExecShell: 'Execute {{ .name }} script' ExecShell: 'Run script {{ .name }}'
PullImage: 'Pull image' PullImage: 'Pull image'
Start: 'Start' Start: 'Start'
Run: 'Start' Run: 'Start'
Stop: 'Stop' Stop: 'Stop'
Image: 'Mirror' Image: 'Image'
Compose: 'Orchestration' Compose: 'Compose'
Container: 'Container' Container: 'Container'
AppLink: 'Linked Application' AppLink: 'Linked Application'
EnableSSL: 'Enable HTTPS' EnableSSL: 'Enable HTTPS'
AppStore: 'App Store' AppStore: 'App Store'
TaskSync: 'Synchronize' TaskSync: 'Sync'
LocalApp: 'Local Application' LocalApp: 'Local Application'
SubTask: 'Subtask' SubTask: 'Subtask'
RuntimeExtension: 'Runtime Environment Extension' RuntimeExtension: 'Runtime extension'
TaskIsExecuting: 'Task is running' TaskIsExecuting: 'Task is running'
CustomAppstore: 'Custom application warehouse' CustomAppstore: 'Custom application repository'
TaskExec: 'Execute' TaskExec: 'Execute'
TaskBatch: "Batch Operation" TaskBatch: "Batch Operation"
FileConvert: 'File Conversion' FileConvert: 'File Conversion'
@@ -414,130 +415,119 @@ TaskScan: "Scan"
# task - ai # task - ai
OllamaModelPull: 'Pull Ollama model {{ .name }}' OllamaModelPull: 'Pull Ollama model {{ .name }}'
OllamaModelSize: 'Get the size of Ollama model {{ .name }}' OllamaModelSize: 'Get Ollama model size: {{ .name }}'
# task-snapshot # task-snapshot
Snapshot: 'Snapshot' Snapshot: 'Snapshot'
SnapDBInfo: 'Write 1Panel database information' SnapDBInfo: 'Write 1Panel DB info'
SnapCopy: 'Copy files & directories {{ .name }}' SnapCopy: 'Copy files/directories {{ .name }}'
SnapNewDB: 'Initialize database {{ .name }} connection' SnapNewDB: 'Init DB connection {{ .name }}'
SnapDeleteOperationLog: 'Delete operation log' SnapDeleteOperationLog: 'Delete operation logs'
SnapDeleteLoginLog: 'Delete access log' SnapDeleteLoginLog: 'Delete access logs'
SnapDeleteMonitor: 'Delete monitoring data' SnapDeleteMonitor: 'Delete monitoring data'
SnapRemoveSystemIP: 'Remove system IP' SnapRemoveSystemIP: 'Remove system IP'
SnapBaseInfo: 'Write 1Panel basic information' SnapBaseInfo: 'Write 1Panel base info'
SnapInstallAppImageEmpty: 'No application images selected, skipping...' SnapInstallAppImageEmpty: 'No app images selected; skipped'
SnapInstallApp: 'Backup 1Panel installed applications' SnapInstallApp: 'Backup installed apps'
SnapDockerSave: 'Compress installed applications' SnapDockerSave: 'Compress installed applications'
SnapLocalBackup: 'Backup 1Panel local backup directory' SnapLocalBackup: 'Backup local backup directory'
SnapCompressBackup: 'Compress local backup directory' SnapCompressBackup: 'Compress local backup directory'
SnapPanelData: 'Backup 1Panel data directory' SnapPanelData: 'Backup 1Panel data directory'
SnapCompressPanel: 'Compressed Data Directory' SnapCompressPanel: 'Compress data directory'
SnapWebsite: 'Backup 1Panel website directory' SnapWebsite: 'Backup website directory'
SnapCloseDBConn: 'Close the database connection' SnapCloseDBConn: 'Close DB connection'
SnapCompress: 'Make snapshot files' SnapCompress: 'Create snapshot file'
SnapCompressFile: 'Compress snapshot file' SnapCompressFile: 'Compress snapshot file'
SnapCheckCompress: 'Check snapshot compression file' SnapCheckCompress: 'Check snapshot archive'
SnapCompressSize: 'Snapshot file size {{ .name }}' SnapCompressSize: 'Snapshot size {{ .name }}'
SnapUpload: 'Upload snapshot file' SnapUpload: 'Upload snapshot file'
SnapUploadTo: 'Upload snapshot file to {{ .name }}' SnapUploadTo: 'Upload snapshot to {{ .name }}'
SnapUploadRes: 'Upload snapshot file to {{ .name }}' SnapUploadRes: 'Upload snapshot to {{ .name }}'
SnapshotRecover: 'Snapshot Restore' SnapshotRecover: 'Recover snapshot'
RecoverDownload: 'Download snapshot file' RecoverDownload: 'Download snapshot file'
Download: 'Download' Download: 'Download'
RecoverDownloadAccount: 'Get snapshot download backup account {{ .name }}' RecoverDownloadAccount: 'Get snapshot download account {{ .name }}'
RecoverDecompress: 'Decompress snapshot compressed files' RecoverDecompress: 'Decompress snapshot archive'
Decompress: 'Decompression' Decompress: 'Decompression'
BackupBeforeRecover: 'Backup system-related data before snapshot' BackupBeforeRecover: 'Backup system data before recovery'
Readjson: 'Read the Json file in the snapshot' ReadJson: 'Read snapshot JSON file'
ReadjsonPath: 'Get the Json file path in the snapshot' ReadJsonPath: 'Get snapshot JSON path'
ReadjsonContent: 'Read Json file' ReadJsonContent: 'Read JSON content'
ReadjsonMarshal: 'Json escape processing' ReadJsonMarshal: 'Json escape processing'
RecoverApp: 'Restore installed apps' RecoverApp: 'Restore installed apps'
RecoverWebsite: 'Recover website directory' RecoverWebsite: 'Restore website directory'
RecoverAppImage: 'Restore snapshot image backup' RecoverAppImage: 'Restore snapshot image backup'
RecoverCompose: 'Restore other composer content' RecoverCompose: 'Restore other compose projects'
RecoverComposeList: 'Get all composers to be restored' RecoverComposeList: 'Get all compose projects to restore'
RecoverComposeItem: 'Recover compose {{ .name }}' RecoverComposeItem: 'Recover compose {{ .name }}'
RecoverAppEmpty: 'No application image backup was found in the snapshot file' RecoverAppEmpty: 'No app image backup found in snapshot'
RecoverBaseData: 'Recover base data and files' RecoverBaseData: 'Restore base data and files'
RecoverDaemonJsonEmpty: 'Both the snapshot file and the current machine do not have the container configuration daemon.json file' RecoverDaemonJsonEmpty: 'daemon.json not found in snapshot or current host'
RecoverDaemonJson: 'Restore container configuration daemon.json file' RecoverDaemonJson: 'Restore daemon.json'
RecoverDBData: 'Recover database data' RecoverDBData: 'Recover database data'
RecoverBackups: 'Restore local backup directory' RecoverBackups: 'Restore local backup directory'
RecoverPanelData: 'Recovery data directory' RecoverPanelData: 'Restore data directory'
# task - container # task - container
ContainerNewCliet: 'Initialize Docker Client'
ContainerImagePull: 'Pull container image {{ .name }}' ContainerImagePull: 'Pull container image {{ .name }}'
ContainerRemoveOld: 'Remove the original container {{ .name }}' ContainerRemoveOld: 'Remove the original container {{ .name }}'
ContainerImageCheck: 'Check if the image is pulled normally' ContainerImageCheck: 'Check image pull result'
ContainerLoadInfo: 'Get basic container information' ContainerLoadInfo: 'Load container info'
ContainerRecreate: 'Container update failed, now starting to restore the original container' ContainerRecreate: 'Container update failed; restoring original container'
ContainerCreate: 'Create a new container {{ .name }}' ContainerCreate: 'Create a new container {{ .name }}'
ContainerCreateFailed: 'Container creation failed, delete the failed container' ContainerCreateFailed: 'Container create failed; deleting failed container'
ContainerStartCheck: 'Check if the container has been started' ContainerStartCheck: 'Check container started'
# task - image # task - image
ImageBuild: 'Image Build' ImageBuild: 'Build image'
ImageBuildStdoutCheck: 'Parse image output content'
ImageBuildRes: 'Image build output: {{ .name }}'
ImagePull: 'Pull image' ImagePull: 'Pull image'
ImageRepoAuthFromDB: 'Get repository authentication information from the database' ImageRepoAuthFromDB: 'Load registry auth from DB'
ImaegPullRes: 'Image pull output: {{ .name }}'
ImagePush: 'Push image' ImagePush: 'Push image'
ImageRenameTag: 'Modify image tag' ImageRenameTag: 'Update image tag'
ImageNewTag: 'New image tag {{ .name }}' ImageNewTag: 'New image tag {{ .name }}'
ImaegPushRes: 'Image push output: {{ .name }}' ComposeCreate: 'Create compose project'
ComposeCreate: 'Create a composition'
ComposeCreateRes: 'Compose create output: {{ .name }}'
# task - website # task - website
BackupNginxConfig: 'Backup website OpenResty configuration file' BackupNginxConfig: 'Backup website OpenResty config'
CompressFileSuccess: 'Compress directory successfully, compressed to {{ .name }}' CompressFileSuccess: 'Directory compressed to {{ .name }}'
CompressDir: 'Compression directory' CompressDir: 'Compress directory'
DeCompressFile: 'Decompress file {{ .name }}' DeCompressFile: 'Decompress file {{ .name }}'
ErrCheckValid: 'Backup file verification failed, {{ .name }}' ErrCheckValid: 'Backup file validation failed: {{ .name }}'
Rollback: 'Rollback' Rollback: 'Rollback'
websiteDir: 'Website Directory' websiteDir: 'Website directory'
RecoverFailedStartRollBack: 'Recovery failed, start rollback' RecoverFailedStartRollBack: 'Recovery failed; starting rollback'
AppBackupFileIncomplete: 'The backup file is incomplete and lacks app.json or app.tar.gz files' AppBackupFileIncomplete: 'Backup is incomplete: missing app.json or app.tar.gz'
AppAttributesNotMatch: 'Application type or name does not match' AppAttributesNotMatch: 'Application type or name does not match'
#alert #alert
ErrAlert: 'The format of the warning message is incorrect, please check and try again!' ErrAlertSync: 'Failed to sync alert message'
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!'
#task - runtime #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 # alert mail template
PanelAlertTitle: "Panel Alert Notification" PanelAlertTitle: "Panel Alert Notification"
TestAlertTitle: "Test Email - Verify Email Connectivity" TestAlertTitle: "Test Email - Verify Email Connectivity"
TestAlert: "This is a test email to verify that your email sending configuration is correct." 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." LicenseExpirationAlert: "Panel {{ .node }}{{ .ip }}: license expires in {{ .day }} days. Log in to view details."
CronJobFailedAlert: "Your {{ .node }}{{ .ip }} Panel, scheduled task - {{ .name }} execution failed. Please log in to the panel for details." CronJobFailedAlert: "Panel {{ .node }}{{ .ip }}: scheduled task {{ .name }} failed. Log in to view details."
ClamAlert: "Your {{ .node }}{{ .ip }} Panel, the virus scan task detected {{ .num }} infected files. Please log in to the panel for details." ClamAlert: "Panel {{ .node }}{{ .ip }}: virus scan found {{ .num }} infected files. Log in to view details."
WebSiteAlert: "Your {{ .node }}{{ .ip }} Panel, {{ .num }} websites will expire in {{ .day }} days. Please log in to the panel for details." WebSiteAlert: "Panel {{ .node }}{{ .ip }}: {{ .num }} websites expire in {{ .day }} days. Log in to view details."
SSLAlert: "Your {{ .node }}{{ .ip }} Panel, {{ .num }} SSL certificates will expire in {{ .day }} days. Please log in to the panel for details." SSLAlert: "Panel {{ .node }}{{ .ip }}: {{ .num }} SSL certificates expire in {{ .day }} days. Log in to view details."
DiskUsedAlert: "Your {{ .node }}{{ .ip }} Panel, disk {{ .name }} usage has reached {{ .used }}. Please log in to the panel for details." DiskUsedAlert: "Panel {{ .node }}{{ .ip }}: disk {{ .name }} usage reached {{ .used }}. Log in to view details."
ResourceAlert: "Your {{ .node }}{{ .ip }} Panel, the average {{ .name }} usage rate in {{ .time }} minutes is {{ .used }}. Please log in to the panel for details." ResourceAlert: "Panel {{ .node }}{{ .ip }}: average {{ .name }} usage in {{ .time }} minutes is {{ .used }}. Log in to view details."
PanelVersionAlert: "Your {{ .node }}{{ .ip }} Panel, the latest panel version is available for upgrade. Please log in to the panel for details." PanelVersionAlert: "Panel {{ .node }}{{ .ip }}: a new panel version is available. Log in to view details."
PanelPwdExpirationAlert: "Your {{ .node }}{{ .ip }} Panel, the panel password will expire in {{ .day }} days. Please log in to the panel for details." PanelPwdExpirationAlert: "Panel {{ .node }}{{ .ip }}: panel password expires in {{ .day }} days. Log in to view details."
CommonAlert: "Your {{ .node }}{{ .ip }} Panel, {{ .msg }}. Please log in to the panel for details." CommonAlert: "Panel {{ .node }}{{ .ip }}: {{ .msg }}. Log in to view details."
NodeExceptionAlert: "Your {{ .node }}{{ .ip }} Panel, {{ .num }} nodes are abnormal. Please log in to the panel for details." NodeExceptionAlert: "Panel {{ .node }}{{ .ip }}: {{ .num }} nodes are abnormal. Log in to view details."
LicenseExceptionAlert: "Your {{ .node }}{{ .ip }} Panel, {{ .num }} licenses are abnormal. Please log in to the panel for details." LicenseExceptionAlert: "Panel {{ .node }}{{ .ip }}: {{ .num }} licenses are abnormal. Log in to view details."
SSHAndPanelLoginAlert: "Your {{ .node }}{{ .ip }} Panel, {{ .name }} login from {{ .loginIp }} is abnormal. Please log in to the panel for details." SSHAndPanelLoginAlert: "Panel {{ .node }}{{ .ip }}: abnormal {{ .name }} login from {{ .loginIp }}. Log in to view details."
#disk #disk
DeviceNotFound: "Device {{ .name }} not found" DeviceNotFound: "Device {{ .name }} not found"
DeviceIsMounted: "Device {{ .name }} is mounted, please unmount first" DeviceIsMounted: 'Device {{ .name }} is mounted; unmount first'
PartitionDiskErr: "Failed to partition, {{ .err }}" PartitionDiskErr: 'Partition failed: {{ .err }}'
FormatDiskErr: "Failed to format disk, {{ .err }}" FormatDiskErr: 'Format failed: {{ .err }}'
MountDiskErr: "Failed to mount disk, {{ .err }}" MountDiskErr: 'Mount failed: {{ .err }}'
UnMountDiskErr: "Failed to unmount disk, {{ .err }}" XfsNotFound: 'xfs not found; install xfsprogs first'
XfsNotFound: "xfs filesystem not detected, please install xfsprogs first"
+165 -231
View File
@@ -1,30 +1,27 @@
ErrInvalidParams: 'Error en los parámetros de la solicitud: {{ .detail }}' ErrInvalidParams: 'Solicitud inválida: {{ .detail }}'
ErrTokenParse: 'Error al generar el token: {{ .detail }}' ErrTokenParse: 'Token inválido: {{ .detail }}'
ErrInitialPassword: 'La contraseña original es incorrecta' ErrInitialPassword: 'Contraseña original incorrecta'
ErrInternalServer: 'Error interno del servidor: {{ .detail }}' ErrInternalServer: 'Error interno: {{ .detail }}'
ErrRecordExist: 'El registro ya existe' ErrRecordExist: 'Registro ya existe'
ErrRecordNotFound: 'Registro no encontrado' ErrRecordNotFound: 'Registro no encontrado'
ErrStructTransform: 'Error de conversión de tipo: {{ .err }}' ErrStructTransform: 'Error de conversión: {{ .err }}'
ErrNotLogin: 'Usuario no ha iniciado sesión: {{ .detail }}' ErrNotLogin: 'No has iniciado sesión: {{ .detail }}'
ErrPasswordExpired: 'La contraseña actual ha expirado: {{ .detail }}' ErrPasswordExpired: 'Contraseña expirada: {{ .detail }}'
ErrNotSupportType: 'El sistema no admite el tipo actual: {{ .name }}' ErrNotSupportType: 'Tipo no soportado: {{ .name }}'
ErrProxy: 'Error en la solicitud, por favor revise el estado del nodo: {{ .detail }}' ErrProxy: 'Solicitud fallida: {{ .detail }}'
ErrApiConfigStatusInvalid: 'Se prohíbe el acceso a la interfaz API: {{ .detail }}' ErrApiConfigStatusInvalid: 'API desactivada: {{ .detail }}'
ErrApiConfigKeyInvalid: 'Error en la clave de la interfaz API: {{ .detail }}' ErrApiConfigKeyInvalid: 'Clave API inválida: {{ .detail }}'
ErrApiConfigIPInvalid: 'La IP usada para llamar a la API no está en la lista blanca: {{ .detail }}' ErrApiConfigIPInvalid: 'IP no permitida: {{ .detail }}'
ErrApiConfigDisable: 'Esta interfaz prohíbe el uso de llamadas a la API: {{ .detail }}' ErrApiConfigDisable: 'API no permitida: {{ .detail }}'
ErrApiConfigKeyTimeInvalid: 'Error en la marca de tiempo de la interfaz API: {{ .detail }}' ErrApiConfigKeyTimeInvalid: 'Timestamp inválido: {{ .detail }}'
ErrShutDown: "¡Comando terminado manualmente!" ErrShutDown: 'Comando detenido manualmente'
ErrMinQuickJump: 'Agrega al menos una entrada rápida'
ErrMinQuickJump: "¡Por favor configure al menos una entrada de acceso rápido!" ErrMaxQuickJump: 'Máximo 4 entradas rápidas'
ErrMaxQuickJump: "¡Puede configurar hasta cuatro entradas de acceso rápido!" ErrUsernameIsExist: 'Usuario ya existe'
ErrNameIsExist: 'Nombre ya existe'
#común ErrDemoEnvironment: 'No disponible en demo'
ErrUsernameIsExist: 'El nombre de usuario ya existe' ErrCmdTimeout: 'Comando agotó tiempo'
ErrNameIsExist: 'El nombre ya existe' ErrCmdIllegal: 'Comando contiene caracteres inválidos'
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!'
ErrPortExist: 'El puerto {{ .port }} ya está ocupado por {{ .type }} [{{ .name }}]' ErrPortExist: 'El puerto {{ .port }} ya está ocupado por {{ .type }} [{{ .name }}]'
TYPE_APP: 'Aplicación' TYPE_APP: 'Aplicación'
TYPE_RUNTIME: 'Entorno de ejecución' TYPE_RUNTIME: 'Entorno de ejecución'
@@ -36,45 +33,39 @@ Failed: 'Error'
SystemRestart: 'La tarea fue interrumpida debido a un reinicio del sistema' SystemRestart: 'La tarea fue interrumpida debido a un reinicio del sistema'
ErrGroupIsDefault: 'Grupo predeterminado, no se puede eliminar' ErrGroupIsDefault: 'Grupo predeterminado, no se puede eliminar'
ErrGroupIsInWebsiteUse: 'El grupo está siendo usado por otro sitio web y no se puede eliminar.' ErrGroupIsInWebsiteUse: 'El grupo está siendo usado por otro sitio web y no se puede eliminar.'
Decrypt: "Descifrar" Decrypt: 'Descifrar'
ErrAgentAccountBound: 'Cuenta vinculada a agente'
#agent ErrAgentAccountUnavailable: 'Conexión de cuenta no disponible: {{ .err }}'
ErrAgentAccountBound: 'Esta cuenta está vinculada a un agente y no se puede eliminar. Verifique e inténtelo de nuevo!' ErrAgentProviderNotSupported: 'Proveedor de agente no soportado'
ErrAgentAccountUnavailable: 'La información de conexión de la cuenta no está disponible. Error: {{ .err }}. Verifique e inténtelo de nuevo!' ErrAgentAccountRequired: 'Elige una cuenta de agente primero'
ErrAgentProviderNotSupported: 'Este proveedor de agente no es compatible. Verifique e inténtelo de nuevo!' ErrAgentAccountNotVerified: 'Cuenta de agente no verificada'
ErrAgentAccountRequired: 'Seleccione una cuenta de agente y vuelva a intentarlo.' ErrAgentProviderMismatch: 'Proveedor de agente no coincide'
ErrAgentAccountNotVerified: 'La cuenta no está verificada. Verifique e inténtelo de nuevo!' ErrAgentBaseURLRequired: 'URL base requerida'
ErrAgentProviderMismatch: 'El proveedor de la cuenta no coincide. Verifique e inténtelo de nuevo!' ErrAgentApiKeyRequired: 'Clave API requerida'
ErrAgentBaseURLRequired: 'Base URL no puede estar vacío. Verifique e inténtelo de nuevo!' ErrAgentComposeRequired: 'Contenido compose requerido'
ErrAgentApiKeyRequired: 'API Key no puede estar vacío. Verifique e inténtelo de nuevo!' ErrAgentIDRequired: 'ID de agente requerido'
ErrAgentComposeRequired: 'El contenido personalizado de compose no puede estar vacío. Verifique e inténtelo de nuevo!' ErrAgentAccountIDRequired: 'ID de cuenta requerido'
ErrAgentIDRequired: 'El ID del agente no puede estar vacío. Verifique e inténtelo de nuevo!' Localhost: 'Máquina local'
ErrAgentAccountIDRequired: 'El ID de la cuenta no puede estar vacío. Verifique e inténtelo de nuevo!' ErrBackupInUsed: 'Cuenta de respaldo en uso por tarea programada'
ErrBackupCheck: 'Conexión de respaldo falló: {{ .err }}'
#backup ErrBackupLocalDelete: 'No se puede eliminar cuentas de respaldo locales'
ErrBackupInUsed: 'La cuenta de respaldo está siendo utilizada en una tarea programada y no se puede eliminar.' ErrBackupLocalCreate: 'No se pueden crear cuentas de respaldo locales'
ErrBackupCheck: 'Error al probar la conexión de la cuenta de respaldo {{ .err }}' ErrPortInUsed: 'El puerto {{ .detail }} ya está ocupado'
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!'
ErrAppLimit: 'El número de aplicaciones instaladas ha superado el límite' ErrAppLimit: 'El número de aplicaciones instaladas ha superado el límite'
ErrNotInstall: 'Aplicación no instalada' ErrNotInstall: 'Aplicación no instalada'
ErrPortInOtherApp: '¡El puerto {{ .port }} ya está ocupado por la aplicación {{ .apps }}!' ErrPortInOtherApp: 'El puerto {{ .port }} ya está ocupado por la aplicación {{ .apps }}'
ErrDbUserNotValid: '¡Base de datos existente, usuario y contraseña no coinciden!' 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!' 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 }}' 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!' 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' 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' 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' 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 }}' LocalAppVersionErr: 'La sincronización de la versión {{ .version }} de {{ .name }} falló {{ .err }}'
ErrFileNotFound: 'El archivo {{ .name }} no existe' 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' ErrAppDirNull: 'La carpeta de la versión no existe'
LocalAppErr: '¡La sincronización de la aplicación {{ .name }} falló! {{ .err }}' LocalAppErr: 'La sincronización de la aplicación {{ .name }} falló {{ .err }}'
ErrContainerName: 'El nombre del contenedor ya existe' ErrContainerName: 'El nombre del contenedor ya existe'
ErrCreateHttpClient: 'Fallo al crear la solicitud {{ .err }}' ErrCreateHttpClient: 'Fallo al crear la solicitud {{ .err }}'
ErrHttpReqTimeOut: 'La solicitud superó el tiempo de espera {{ .err }}' ErrHttpReqTimeOut: 'La solicitud superó el tiempo de espera {{ .err }}'
@@ -87,46 +78,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.' ErrVersionTooLow: 'La versión actual de 1Panel es demasiado baja para actualizar la tienda de aplicaciones. Actualice primero.'
ErrAppNameExist: 'El nombre de la aplicación ya existe' ErrAppNameExist: 'El nombre de la aplicación ya existe'
AppStoreIsSyncing: 'La tienda de aplicaciones está sincronizando, inténtelo más tarde' AppStoreIsSyncing: 'La tienda de aplicaciones está sincronizando, inténtelo más tarde'
ErrGetCompose: '¡Fallo al obtener el archivo docker-compose.yml! {{ .detail }}' ErrGetCompose: 'Fallo al obtener el archivo docker-compose.yml {{ .detail }}'
ErrAppWarn: 'Estado anómalo, revise el log' ErrAppWarn: 'Estado anómalo, revise el log'
ErrAppParamKey: 'El campo de parámetro {{ .name }} es anómalo' ErrAppParamKey: 'El campo de parámetro {{ .name }} es anómalo'
ErrAppUpgrade: 'La actualización de la aplicación {{ .name }} falló {{ .err }}' ErrAppUpgrade: 'La actualización de la aplicación {{ .name }} falló {{ .err }}'
AppRecover: 'Revertir la aplicación {{ .name }}' AppRecover: 'Revertir la aplicación {{ .name }}'
PullImageStart: 'Iniciar descarga de la imagen [{{ .name }}]' PullImageStart: 'Iniciar descarga de la imagen [{{ .name }}]'
PullImageSuccess: 'Descarga de imagen exitosa' 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' AppStoreSyncSuccess: 'Sincronización de la tienda de aplicaciones exitosa'
SyncAppDetail: 'Sincronizar configuración de la aplicación' 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' 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' MoveSiteDir: 'La actualización actual requiere migrar el directorio del sitio web OpenResty'
MoveSiteDirSuccess: 'Migración del directorio del sitio exitosa' MoveSiteDirSuccess: 'Migración del directorio del sitio exitosa'
DeleteRuntimePHP: 'Eliminar entorno de ejecución PHP' 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' 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' ErrAppIsDown: 'El estado de la aplicación {{ .name }} es anómalo, revise'
ErrCustomApps: 'Hay una aplicación instalada, desinstálela primero' ErrCustomApps: 'Hay una aplicación instalada, desinstálela primero'
ErrCustomRuntimes: 'Hay un entorno de ejecución instalado, elimínelo 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" 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" 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" ErrDockerComposeCmdNotFound: 'El comando Docker Compose no existe instálelo primero en el host'
UseExistImage: 'Error al extraer la imagen, usando imagen existente' UseExistImage: 'La imagen ya existe, usando imagen existente'
ErrDatabaseNotFound: 'La base de datos {{ .name }} no existe'
#ssh ExportIP: 'IP de inicio de sesión'
ExportIP: "IP de inicio de sesión" ExportArea: 'Ubicación'
ExportArea: "Ubicación" ExportPort: 'Puerto'
ExportPort: "Puerto" ExportAuthMode: 'Método de inicio de sesión'
ExportAuthMode: "Método de inicio de sesión" ExportUser: 'Usuario'
ExportUser: "Usuario" ExportStatus: 'Estado de inicio de sesión'
ExportStatus: "Estado de inicio de sesión" ExportDate: 'Fecha y hora'
ExportDate: "Fecha y hora"
#file
ErrFileCanNotRead: 'Este archivo no soporta vista previa' ErrFileCanNotRead: 'Este archivo no soporta vista previa'
ErrFileToLarge: 'El archivo es mayor a 10M y no puede abrirse' ErrFileToLarge: 'El archivo es mayor a 10M y no puede abrirse'
ErrPathNotFound: 'El directorio no existe' ErrPathNotFound: 'El directorio no existe'
ErrMovePathFailed: '¡La ruta de destino no puede contener la ruta original!' ErrMovePathFailed: 'La ruta de destino no puede contener la ruta original'
ErrLinkPathNotFound: '¡La ruta de destino no existe!' ErrLinkPathNotFound: 'La ruta de destino no existe'
ErrFileIsExist: '¡El archivo o carpeta ya existe!' ErrFileIsExist: 'El archivo o carpeta ya existe'
ErrFileUpload: '{{ .name }} falló al subir archivo {{ .detail }}' ErrFileUpload: '{{ .name }} falló al subir archivo {{ .detail }}'
ErrFileDownloadDir: 'No se admite la descarga de carpetas' ErrFileDownloadDir: 'No se admite la descarga de carpetas'
ErrCmdNotFound: 'El comando {{ .name }} no existe, instálelo primero en el host' ErrCmdNotFound: 'El comando {{ .name }} no existe, instálelo primero en el host'
@@ -134,16 +121,15 @@ ErrSourcePathNotFound: 'El directorio fuente no existe'
ErrFavoriteExist: 'Esta ruta ya ha sido marcada como favorita' ErrFavoriteExist: 'Esta ruta ya ha sido marcada como favorita'
ErrInvalidChar: 'No se permiten caracteres ilegales' ErrInvalidChar: 'No se permiten caracteres ilegales'
ErrPathNotDelete: 'No se puede eliminar el directorio seleccionado' ErrPathNotDelete: 'No se puede eliminar el directorio seleccionado'
FileDropFailed: "Error al limpiar el archivo {{ .name }}: {{ .err }}" ErrLogFileToLarge: 'Log file exceeds 500 MB'
FileDropSuccess: "Archivo {{ .name }} limpiado correctamente, {{ .count }} archivos eliminados, {{ .size }} de espacio liberado" FileDropFailed: 'Error al limpiar el archivo {{ .name }}: {{ .err }}'
FileDropSum: "Limpieza de archivos completada, total {{ .count }} archivos eliminados, {{ .size }} de espacio liberado" FileDropSuccess: 'Archivo {{ .name }} limpiado correctamente, {{ .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!" 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
ErrAliasIsExist: 'El alias ya existe' ErrAliasIsExist: 'El alias ya existe'
ErrBackupMatch: 'El archivo de respaldo no coincide con parte de los datos actuales del sitio web {{ .detail }}' ErrBackupMatch: 'El archivo de respaldo no coincide con parte de los datos actuales del sitio web {{ .detail }}'
ErrBackupExist: 'Parte de los datos fuente del respaldo no existe {{ .detail }}' ErrBackupExist: 'Parte de los datos fuente del respaldo no existe {{ .detail }}'
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' 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 }}]' ErrDomainIsUsed: 'El dominio ya está en uso por el sitio web [{{ .name }}]'
ErrDomainFormat: 'El formato del dominio {{ .name }} es incorrecto' ErrDomainFormat: 'El formato del dominio {{ .name }} es incorrecto'
@@ -151,11 +137,11 @@ ErrDefaultAlias: 'default es un código reservado, use otro'
ErrParentWebsite: 'Primero debe eliminar el sub-sitio {{ .name }}' ErrParentWebsite: 'Primero debe eliminar el sub-sitio {{ .name }}'
ErrBuildDirNotFound: 'El directorio de compilación no existe' ErrBuildDirNotFound: 'El directorio de compilación no existe'
ErrImageNotExist: 'La imagen del entorno {{ .name }} no existe, edítela de nuevo' 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" 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!' ErrSSLValid: 'Archivo de certificado anómalo, revise el estado del certificado'
ErrWebsiteDir: "Por favor seleccione un directorio dentro del directorio del sitio web" ErrWebsiteDir: 'seleccione un directorio dentro del directorio del sitio web'
ErrComposerFileNotFound: "El archivo composer.json no existe" ErrComposerFileNotFound: 'El archivo composer.json no existe'
ErrRuntimeNoPort: "El entorno de ejecución no tiene configurado un puerto, edítelo primero" ErrRuntimeNoPort: 'El entorno de ejecución no tiene configurado un puerto, edítelo primero'
Status: 'Estado' Status: 'Estado'
start: 'Iniciar' start: 'Iniciar'
stop: 'Detener' stop: 'Detener'
@@ -165,14 +151,12 @@ pause: 'Pausar'
unpause: 'Reanudar' unpause: 'Reanudar'
remove: 'Eliminar' remove: 'Eliminar'
delete: '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' SSL: 'Certificado'
Set: 'Configuración' Set: 'Configuración'
#ssl
ErrSSLCannotDelete: 'El certificado {{ .name }} está siendo utilizado por un sitio web y no puede eliminarse' ErrSSLCannotDelete: 'El certificado {{ .name }} está siendo utilizado por un sitio web y no puede eliminarse'
ErrAccountCannotDelete: 'La cuenta está asociada a un certificado y no puede eliminarse' ErrAccountCannotDelete: 'La cuenta está asociada a un certificado y no puede eliminarse'
ErrSSLApply: 'Renovación del certificado exitosa, recarga de openresty fallida, ¡revise la configuración!' ErrSSLApply: 'Renovación del certificado exitosa, recarga de openresty fallida, revise la configuración'
ErrEmailIsExist: 'El correo ya existe' ErrEmailIsExist: 'El correo ya existe'
ErrSSLKeyNotFound: 'El archivo de clave privada no existe' ErrSSLKeyNotFound: 'El archivo de clave privada no existe'
ErrSSLCertificateNotFound: 'El archivo de certificado no existe' ErrSSLCertificateNotFound: 'El archivo de certificado no existe'
@@ -185,9 +169,10 @@ dnsAccount: 'DNS Automático'
dnsManual: 'DNS Manual' dnsManual: 'DNS Manual'
http: 'HTTP' http: 'HTTP'
ApplySSLFailed: 'Solicitud de certificado para [{{ .domain }}] fallida, {{ .detail }}' 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 }}]' DNSAccountName: 'Cuenta DNS [{{ .name }}] proveedor [{{ .type }}]'
PushDirLog: 'Certificado empujado al directorio [{{ .path }}] {{ .status }}' 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' ErrDeleteWithPanelSSL: 'La configuración SSL del panel utiliza este certificado y no puede eliminarse'
ErrDefaultCA: 'La autoridad por defecto no puede eliminarse' ErrDefaultCA: 'La autoridad por defecto no puede eliminarse'
ApplyWebSiteSSLLog: 'Iniciando renovación del certificado del sitio web {{ .name }}' ApplyWebSiteSSLLog: 'Iniciando renovación del certificado del sitio web {{ .name }}'
@@ -199,98 +184,79 @@ ExecShellSuccess: 'Ejecución de script exitosa'
StartUpdateSystemSSL: 'Iniciando actualización del certificado del sistema' StartUpdateSystemSSL: 'Iniciando actualización del certificado del sistema'
UpdateSystemSSLSuccess: 'Certificado del sistema actualizado correctamente' UpdateSystemSSLSuccess: 'Certificado del sistema actualizado correctamente'
ErrWildcardDomain: 'No se puede solicitar certificado de dominio wildcard en modo HTTP' 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'
ErrApplySSLCanNotDelete: "El certificado {{ .name }} en proceso de solicitud no puede eliminarse, inténtelo más tarde" StartPushSSLToNode: 'Iniciando envío de certificado al nodo'
StartPushSSLToNode: "Iniciando envío de certificado al nodo" PushSSLToNodeFailed: 'Error al enviar el certificado al nodo: {{ .err }}'
PushSSLToNodeFailed: "Error al enviar el certificado al nodo: {{ .err }}" PushSSLToNodeSuccess: 'Certificado enviado correctamente al nodo'
PushSSLToNodeSuccess: "Certificado enviado correctamente al nodo"
#mysql
ErrUserIsExist: 'El usuario actual ya existe, intente con otro' ErrUserIsExist: 'El usuario actual ya existe, intente con otro'
ErrDatabaseIsExist: 'La base de datos actual ya existe, intente con otro nombre' ErrDatabaseIsExist: 'La base de datos actual ya existe, intente con otro nombre'
ErrExecTimeOut: 'Tiempo de espera en la ejecución SQL, revise la base de datos' ErrExecTimeOut: 'Tiempo de espera en la ejecución SQL, revise la base de datos'
ErrRemoteExist: 'La base de datos remota ya existe con ese nombre, modifíquelo e intente de nuevo' 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' 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..." 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 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...'
Arg: "Argumento" Arg: 'Argumento'
#redis
ErrTypeOfRedis: 'El tipo de archivo de recuperación no coincide con el método de persistencia actual, modifíquelo e intente' ErrTypeOfRedis: 'El tipo de archivo de recuperación no coincide con el método de persistencia actual, modifíquelo e intente'
ErrInUsed: '{{ .detail }} está en uso y no se puede eliminar'
#container ErrObjectInUsed: 'Este objeto está en uso y no se puede eliminar'
ErrInUsed: "{{ .detail }} está en uso y no se puede eliminar!" ErrObjectBeDependent: 'Esta imagen es dependida por otras imágenes 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' 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' 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 }}" PruneHelper: 'Esta limpieza {{ .name }} liberó espacio en disco {{ .size }}'
ImageRemoveHelper: "Imagen {{ .name }} eliminada, liberando {{ .size }} de espacio en disco" ImageRemoveHelper: 'Imagen {{ .name }} eliminada, liberando {{ .size }} de espacio en disco'
BuildCache: "Caché de compilación" BuildCache: 'Caché de compilación'
Volume: "Volumen de almacenamiento" Volume: 'Volumen de almacenamiento'
Network: "Red" Network: 'Red'
PruneStart: "Limpiando en progreso, por favor espere..." PruneStart: 'Limpiando en progreso espere...'
ErrFileNotExist: 'El archivo {{ .detail }} no existe, verifique la integridad'
#runtime
ErrFileNotExist: 'El archivo {{ .detail }} no existe, ¡verifique la integridad!'
ErrImageBuildErr: 'Fallo al construir la imagen' ErrImageBuildErr: 'Fallo al construir la imagen'
ErrImageExist: "¡La imagen ya existe! Modifique el nombre de la imagen." ErrImageExist: 'La imagen ya existe Modifique el nombre de la imagen.'
ErrDelWithWebsite: 'El entorno de ejecución ya está asociado a un sitio web y no puede eliminarse' ErrDelWithWebsite: 'El entorno de ejecución ya está asociado a un sitio web y no puede eliminarse'
ErrRuntimeStart: 'Fallo al iniciar' ErrRuntimeStart: 'Fallo al iniciar'
ErrPackageJsonNotFound: 'El archivo package.json no existe' ErrPackageJsonNotFound: 'El archivo package.json no existe'
ErrScriptsNotFound: 'No se encontró la configuración de scripts en package.json' 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' ErrNodeModulesNotFound: 'La carpeta node_modules no existe, edite o espere a que inicie'
ErrContainerNameIsNull: 'El nombre del contenedor no existe' ErrContainerNameIsNull: 'El nombre del contenedor no existe'
ErrPHPPortIsDefault: "El puerto 9000 es el predeterminado, modifique e intente de nuevo" ErrPHPPortIsDefault: 'El puerto 9000 es el predeterminado, modifique e intente de nuevo'
ErrPHPRuntimePortFailed: "El puerto {{ .name }} ya está en uso por el entorno actual, modifique e intente" ErrPHPRuntimePortFailed: 'El puerto {{ .name }} ya está en uso por el entorno actual, modifique e intente'
#tool
ErrConfigNotFound: 'El archivo de configuración no existe' ErrConfigNotFound: 'El archivo de configuración no existe'
ErrConfigParse: 'El formato del archivo de configuración es incorrecto' ErrConfigParse: 'El formato del archivo de configuración es incorrecto'
ErrConfigIsNull: 'El archivo de configuración no puede estar vacío' ErrConfigIsNull: 'El archivo de configuración no puede estar vacío'
ErrConfigDirNotFound: 'El directorio de ejecución no existe' ErrConfigDirNotFound: 'El directorio de ejecución no existe'
ErrConfigAlreadyExist: 'Ya existe un archivo de configuración con ese nombre' ErrConfigAlreadyExist: 'Ya existe un archivo de configuración con ese nombre'
ErrUserFindErr: 'Búsqueda del usuario {{ .name }} fallida {{ .err }}' ErrUserFindErr: 'Búsqueda del usuario {{ .name }} fallida {{ .err }}'
#cronjob
CutWebsiteLogSuccess: 'Log del sitio web {{ .name }} cortado con éxito, ruta de respaldo {{ .path }}' CutWebsiteLogSuccess: 'Log del sitio web {{ .name }} cortado con éxito, ruta de respaldo {{ .path }}'
HandleShell: 'Ejecutar script {{ .name }}' HandleShell: 'Ejecutar script {{ .name }}'
HandleCurl: "URL {{ .name }} にアクセス" HandleCurl: 'URL {{ .name }} にアクセス'
HandleNtpSync: 'Sincronizar hora del sistema' HandleNtpSync: 'Sincronizar hora del sistema'
HandleSystemClean: 'Limpiar caché del sistema' HandleSystemClean: 'Limpiar caché del sistema'
SystemLog: 'Log del sistema' SystemLog: 'Log del sistema'
CutWebsiteLog: 'Rotar log del sitio web' CutWebsiteLog: 'Rotar log del sitio web'
FileOrDir: 'Directorio / Archivo' FileOrDir: 'Directorio / Archivo'
UploadFile: 'Subiendo archivo de respaldo {{ .file }} a {{ .backup }}' UploadFile: 'Subiendo archivo de respaldo {{ .file }} a {{ .backup }}'
Upload: 'Subir'
IgnoreBackupErr: 'Fallo en el respaldo, error: {{ .detail }}, se ignora este error...' IgnoreBackupErr: 'Fallo en el respaldo, error: {{ .detail }}, se ignora este error...'
IgnoreUploadErr: 'Fallo en la subida, 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 }}'
LoadBackupFailed: "Error al obtener la conexión de la cuenta de respaldo, error: {{ .detail }}" InExecuting: 'La tarea actual se está ejecutando no la repita'
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...'
NoSuchResource: "No se encontraron contenidos de respaldo en la base de datos, omitiendo..." CleanLog: 'Limpiar registro'
CleanLog: "Limpiar registro" CleanLogByName: 'Limpiar registro de {{ .name }}'
CleanLogByName: "Limpiar registro de {{.name}}" WafIpGroupNotFound: 'Grupo de IP de WAF no encontrado., vaya a [Funciones Avanzadas - WAF - Lista Blanca/Negra - Grupo de IP] para agregar un grupo de IP mediante el método de descarga remota.'
WafIpGroupNotFound: "Grupo de IP de WAF no encontrado. 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
ErrNotExistUser: 'El usuario actual no existe, modifíquelo e intente de nuevo' ErrNotExistUser: 'El usuario actual no existe, modifíquelo e intente de nuevo'
ErrBanAction: 'Fallo al configurar. El servicio {{ .name }} no está disponible, revise e intente de nuevo' ErrBanAction: 'Fallo al configurar. El servicio {{ .name }} no está disponible, revise e intente de nuevo'
ErrClamdscanNotFound: 'El comando clamdscan no fue detectado, siga la documentación para instalarlo' ErrClamdscanNotFound: 'El comando clamdscan no fue detectado, siga la documentación para instalarlo'
TaskSwapSet: "Configurar Swap" TaskSwapSet: 'Configurar Swap'
SetSwap: "Configurar Swap {{ .path }} - {{ .size }}" SetSwap: 'Configurar Swap {{ .path }} - {{ .size }}'
CreateSwap: "Crear Archivo Swap" CreateSwap: 'Crear Archivo Swap'
FormatSwap: "Formatear Archivo Swap" FormatSwap: 'Formatear Archivo Swap'
EnableSwap: "Habilitar Swap" EnableSwap: 'Habilitar Swap'
CleanTamperSetting: 'Limpiar configuraciones de protección históricas'
#tamper SetTamperWithRules: 'Iniciar protección de directorio según reglas'
CleanTamperSetting: "Limpiar configuraciones de protección históricas" ProtectDir: 'Proteger directorio {{ .name }}'
SetTamperWithRules: "Iniciar protección de directorio según reglas" IgnoreFile: 'Proteger archivo {{ .name }}'
ProtectDir: "Proteger directorio {{ .name }}" TamperSetSuccessful: 'Configuración de protección completada, comenzando monitoreo de los siguientes directorios:'
IgnoreFile: "Proteger archivo {{ .name }}"
TamperSetSuccessful: "Configuración de protección completada, comenzando monitoreo de los siguientes directorios:"
#waf
ErrScope: 'No se admite la modificación de esta configuración' ErrScope: 'No se admite la modificación de esta configuración'
ErrStateChange: 'Fallo al cambiar de estado' ErrStateChange: 'Fallo al cambiar de estado'
ErrRuleExist: 'La regla ya existe' ErrRuleExist: 'La regla ya existe'
@@ -298,7 +264,7 @@ ErrRuleNotExist: 'La regla no existe'
ErrParseIP: 'Formato de IP incorrecto' ErrParseIP: 'Formato de IP incorrecto'
ErrDefaultIP: 'default es un nombre reservado, cámbielo' ErrDefaultIP: 'default es un nombre reservado, cámbielo'
ErrGroupInUse: 'El grupo IP está en uso por listas negras/blancas y no se puede eliminar' 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' ErrGroupExist: 'El nombre del grupo IP ya existe'
ErrIPRange: 'Rango de IP incorrecto' ErrIPRange: 'Rango de IP incorrecto'
ErrIPExist: 'La IP ya existe' ErrIPExist: 'La IP ya existe'
@@ -309,10 +275,10 @@ xss: 'XSS'
phpExec: 'Ejecución de scripts PHP' phpExec: 'Ejecución de scripts PHP'
oneWordTrojan: 'Troyano de una sola palabra' oneWordTrojan: 'Troyano de una sola palabra'
appFilter: 'Filtrar directorios peligrosos' appFilter: 'Filtrar directorios peligrosos'
webshell: 'Webshell' webShell: 'Webshell'
args: 'Reglas de parámetros' args: 'Reglas de parámetros'
protocolFilter: 'Filtrado de protocolos' protocolFilter: 'Filtrado de protocolos'
javaFileter: 'Filtrado de archivos Java peligrosos' javaFilter: 'Filtrado de archivos Java peligrosos'
scannerFilter: 'Filtrado de escáneres' scannerFilter: 'Filtrado de escáneres'
escapeFilter: 'Filtro de escape' escapeFilter: 'Filtro de escape'
customRule: 'Regla personalizada' customRule: 'Regla personalizada'
@@ -342,10 +308,9 @@ ErrDBNotExist: 'La base de datos no existe'
allow: 'permitir' allow: 'permitir'
deny: 'denegar' deny: 'denegar'
OpenrestyNotFound: 'Openresty no está instalado' OpenrestyNotFound: 'Openresty no está instalado'
remoteIpIsNull: "La lista de IP está vacía" remoteIpIsNull: 'La lista de IP está vacía'
OpenrestyVersionErr: "La versión de Openresty es demasiado baja, actualice a 1.27.1.2-2-2-focal" 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'
#task
TaskStart: 'La tarea {{ .name }} inicia [INICIO]' TaskStart: 'La tarea {{ .name }} inicia [INICIO]'
TaskEnd: 'La tarea {{ .name }} completada [COMPLETADA]' TaskEnd: 'La tarea {{ .name }} completada [COMPLETADA]'
TaskFailed: 'La tarea {{ .name }} falló' TaskFailed: 'La tarea {{ .name }} falló'
@@ -357,11 +322,11 @@ SubTaskFailed: '{{ .name }} falló: {{ .err }}'
TaskInstall: 'Instalar' TaskInstall: 'Instalar'
TaskUninstall: 'Desinstalar' TaskUninstall: 'Desinstalar'
TaskCreate: 'Crear' TaskCreate: 'Crear'
TaskProtect: "Proteger"
TaskDelete: 'Eliminar' TaskDelete: 'Eliminar'
TaskUpgrade: 'Actualizar' TaskUpgrade: 'Actualizar'
TaskUpdate: 'Actualizar' TaskUpdate: 'Actualizar'
TaskRestart: 'Reiniciar' TaskRestart: 'Reiniciar'
TaskProtect: 'Proteger'
TaskBackup: 'Respaldar' TaskBackup: 'Respaldar'
TaskRecover: 'Recuperar' TaskRecover: 'Recuperar'
TaskRollback: 'Revertir' TaskRollback: 'Revertir'
@@ -369,9 +334,10 @@ TaskPull: 'Descargar'
TaskCommit: 'Commit' TaskCommit: 'Commit'
TaskBuild: 'Construir' TaskBuild: 'Construir'
TaskPush: 'Subir' TaskPush: 'Subir'
TaskClean: 'Limpieza'
TaskHandle: 'Ejecutar' TaskHandle: 'Ejecutar'
TaskImport: "Importar" TaskImport: 'Importar'
TaskExport: "Exportar" TaskExport: 'Exportar'
Website: 'Sitio web' Website: 'Sitio web'
App: 'Aplicación' App: 'Aplicación'
Runtime: 'Entorno de ejecución' Runtime: 'Entorno de ejecución'
@@ -402,20 +368,13 @@ SubTask: 'Subtarea'
RuntimeExtension: 'Extensión del entorno de ejecución' RuntimeExtension: 'Extensión del entorno de ejecución'
TaskIsExecuting: 'Tarea en ejecución' TaskIsExecuting: 'Tarea en ejecución'
CustomAppstore: 'Almacén de aplicaciones personalizado' CustomAppstore: 'Almacén de aplicaciones personalizado'
TaskClean: "Limpieza" TaskExec: 'Ejecutar'
TaskExec: "Ejecutar" TaskBatch: 'Operación por Lotes'
TaskBatch: "Operación por Lotes"
FileConvert: 'Conversión de Formato de Archivo' FileConvert: 'Conversión de Formato de Archivo'
Clamscan: 'Escanear {{ .name }}'
# task - ai TaskScan: 'Escaneo'
OllamaModelPull: 'Descargar modelo Ollama {{ .name }}' OllamaModelPull: 'Descargar modelo Ollama {{ .name }}'
OllamaModelSize: 'Obtener tamaño del modelo Ollama {{ .name }}' OllamaModelSize: 'Obtener tamaño del modelo Ollama {{ .name }}'
# task - clam
Clamscan: "Escanear {{ .name }}"
TaskScan: "Escaneo"
# task-snapshot
Snapshot: 'Instantánea' Snapshot: 'Instantánea'
SnapDBInfo: 'Escribir información de base de datos de 1Panel' SnapDBInfo: 'Escribir información de base de datos de 1Panel'
SnapCopy: 'Copiar archivos y directorios {{ .name }}' SnapCopy: 'Copiar archivos y directorios {{ .name }}'
@@ -440,7 +399,7 @@ SnapCheckCompress: 'Verificar archivo de compresión de instantánea'
SnapCompressSize: 'Tamaño del archivo de instantánea {{ .name }}' SnapCompressSize: 'Tamaño del archivo de instantánea {{ .name }}'
SnapUpload: 'Subir archivo de instantánea' SnapUpload: 'Subir archivo de instantánea'
SnapUploadTo: 'Subir archivo de instantánea a {{ .name }}' SnapUploadTo: 'Subir archivo de instantánea a {{ .name }}'
SnapUploadRes: 'Subir archivo de instantánea a {{ .name }}'
SnapshotRecover: 'Restaurar instantánea' SnapshotRecover: 'Restaurar instantánea'
RecoverDownload: 'Descargar archivo de instantánea' RecoverDownload: 'Descargar archivo de instantánea'
Download: 'Descargar' Download: 'Descargar'
@@ -448,10 +407,10 @@ RecoverDownloadAccount: 'Obtener cuenta de respaldo para descargar instantánea
RecoverDecompress: 'Descomprimir archivos de instantánea' RecoverDecompress: 'Descomprimir archivos de instantánea'
Decompress: 'Descompresión' Decompress: 'Descompresión'
BackupBeforeRecover: 'Respaldar datos del sistema antes de restaurar instantánea' BackupBeforeRecover: 'Respaldar datos del sistema antes de restaurar instantánea'
Readjson: 'Leer archivo Json de la instantánea' ReadJson: 'Leer archivo Json de la instantánea'
ReadjsonPath: 'Obtener ruta del archivo Json en la instantánea' ReadJsonPath: 'Obtener ruta del archivo Json en la instantánea'
ReadjsonContent: 'Leer archivo Json' ReadJsonContent: 'Leer archivo Json'
ReadjsonMarshal: 'Procesar escape de Json' ReadJsonMarshal: 'Procesar escape de Json'
RecoverApp: 'Restaurar aplicaciones instaladas' RecoverApp: 'Restaurar aplicaciones instaladas'
RecoverWebsite: 'Recuperar directorio del sitio web' RecoverWebsite: 'Recuperar directorio del sitio web'
RecoverAppImage: 'Restaurar imagen de la instantánea' RecoverAppImage: 'Restaurar imagen de la instantánea'
@@ -465,9 +424,6 @@ RecoverDaemonJson: 'Restaurar archivo daemon.json de configuración de contenedo
RecoverDBData: 'Restaurar datos de base de datos' RecoverDBData: 'Restaurar datos de base de datos'
RecoverBackups: 'Restaurar directorio local de respaldo' RecoverBackups: 'Restaurar directorio local de respaldo'
RecoverPanelData: 'Recuperar directorio de datos' RecoverPanelData: 'Recuperar directorio de datos'
# task - container
ContainerNewCliet: 'Inicializar cliente Docker'
ContainerImagePull: 'Descargar imagen de contenedor {{ .name }}' ContainerImagePull: 'Descargar imagen de contenedor {{ .name }}'
ContainerRemoveOld: 'Eliminar el contenedor original {{ .name }}' ContainerRemoveOld: 'Eliminar el contenedor original {{ .name }}'
ContainerImageCheck: 'Comprobar si la imagen se descargó correctamente' ContainerImageCheck: 'Comprobar si la imagen se descargó correctamente'
@@ -476,22 +432,13 @@ ContainerRecreate: 'Actualización del contenedor fallida, restaurando el conten
ContainerCreate: 'Crear nuevo contenedor {{ .name }}' ContainerCreate: 'Crear nuevo contenedor {{ .name }}'
ContainerCreateFailed: 'Falló la creación del contenedor, eliminando el contenedor fallido' ContainerCreateFailed: 'Falló la creación del contenedor, eliminando el contenedor fallido'
ContainerStartCheck: 'Verificar si el contenedor ha iniciado' ContainerStartCheck: 'Verificar si el contenedor ha iniciado'
# task - image
ImageBuild: 'Construcción de imagen' ImageBuild: 'Construcción de imagen'
ImageBuildStdoutCheck: 'Analizar salida de la imagen'
ImageBuildRes: 'Salida de construcción de imagen: {{ .name }}'
ImagePull: 'Descargar imagen' ImagePull: 'Descargar imagen'
ImageRepoAuthFromDB: 'Obtener información de autenticación del repositorio desde la base de datos'
ImagePush: 'Subir imagen' ImagePush: 'Subir imagen'
ImageRenameTag: 'Modificar etiqueta de imagen' ImageRenameTag: 'Modificar etiqueta de imagen'
ImageNewTag: 'Nueva etiqueta de imagen {{ .name }}' ImageNewTag: 'Nueva etiqueta de imagen {{ .name }}'
ComposeCreate: 'Crear orquestación' ComposeCreate: 'Crear orquestación'
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' BackupNginxConfig: 'Respaldar archivo de configuración OpenResty'
CompressFileSuccess: 'Directorio comprimido con éxito, guardado en {{ .name }}' CompressFileSuccess: 'Directorio comprimido con éxito, guardado en {{ .name }}'
CompressDir: 'Directorio comprimido' CompressDir: 'Directorio comprimido'
@@ -502,40 +449,27 @@ websiteDir: 'Directorio del sitio web'
RecoverFailedStartRollBack: 'Restauración fallida, iniciando reversión' RecoverFailedStartRollBack: 'Restauración fallida, iniciando reversión'
AppBackupFileIncomplete: 'El archivo de respaldo está incompleto, falta app.json o app.tar.gz' AppBackupFileIncomplete: 'El archivo de respaldo está incompleto, falta app.json o app.tar.gz'
AppAttributesNotMatch: 'El tipo o nombre de la aplicación no coincide' AppAttributesNotMatch: 'El tipo o nombre de la aplicación no coincide'
ErrAlertSync: 'Error en la sincronización de la alerta, revise e intente de nuevo'
#alert ErrInstallExtension: 'Ya hay una tarea de instalación en curso, espere a que termine'
ErrAlert: 'El formato del mensaje de alerta es incorrecto, ¡revise e intente de nuevo!' PanelAlertTitle: 'Notificación de alerta del panel'
ErrAlertPush: 'Error al enviar la alerta, ¡revise e intente de nuevo!' TestAlertTitle: 'Correo de prueba - Verificar conectividad de correo'
ErrAlertSave: 'Error al guardar la alerta, ¡revise e intente de nuevo!' TestAlert: 'Este es un correo de prueba para verificar que la configuración de envío de correos es correcta.'
ErrAlertSync: 'Error en la sincronización de la alerta, ¡revise e intente de nuevo!' LicenseExpirationAlert: 'Su Panel {{ .node }}{{ .ip }}, la licencia expirará en {{ .day }} días. Inicie sesión en el panel para ver los detalles.'
ErrAlertRemote: 'Error remoto de alerta, ¡revise e intente de nuevo!' 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.'
#task - runtime WebSiteAlert: 'Su Panel {{ .node }}{{ .ip }}, {{ .num }} sitios web expirarán en {{ .day }} días. Inicie sesión en el panel para ver los detalles.'
ErrInstallExtension: "Ya hay una tarea de instalación en curso, espere a que termine" 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.'
# alert mail template 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.'
PanelAlertTitle: "Notificación de alerta del panel" 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.'
TestAlertTitle: "Correo de prueba - Verificar conectividad de correo" 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.'
TestAlert: "Este es un correo de prueba para verificar que la configuración de envío de correos es correcta." CommonAlert: 'Su Panel {{ .node }}{{ .ip }}, {{ .msg }}. Inicie sesión en el panel para ver los detalles.'
LicenseExpirationAlert: "Su Panel {{ .node }}{{ .ip }}, la licencia expirará en {{ .day }} días. 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.'
CronJobFailedAlert: "Su Panel {{ .node }}{{ .ip }}, la ejecución de la tarea programada {{ .name }} falló. 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.'
ClamAlert: "Su Panel {{ .node }}{{ .ip }}, la tarea de escaneo antivirus detectó {{ .num }} archivos infectados. 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.'
WebSiteAlert: "Su Panel {{ .node }}{{ .ip }}, {{ .num }} sitios web expirarán en {{ .day }} días. Inicie sesión en el panel para ver los detalles." DeviceNotFound: 'Dispositivo {{ .name }} no encontrado'
SSLAlert: "Su Panel {{ .node }}{{ .ip }}, {{ .num }} certificados SSL expirarán en {{ .day }} días. Inicie sesión en el panel para ver los detalles." DeviceIsMounted: 'El dispositivo {{ .name }} está montado, desmóntelo primero'
DiskUsedAlert: "Su Panel {{ .node }}{{ .ip }}, el uso del disco {{ .name }} ha alcanzado {{ .used }}. Inicie sesión en el panel para ver los detalles." PartitionDiskErr: 'Error al particionar, {{ .err }}'
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." FormatDiskErr: 'Error al formatear disco, {{ .err }}'
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." MountDiskErr: 'Error al montar disco, {{ .err }}'
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." XfsNotFound: 'No se detectó el sistema de archivos xfs instale xfsprogs primero'
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"
+160 -227
View File
@@ -1,30 +1,28 @@
ErrInvalidParams: 'リクエストパラメータエラー: {{ .detail }}' ErrInvalidParams: '不正なリクエスト: {{ .detail }}'
ErrTokenParse: 'トークン生成エラー: {{ .detail }}' ErrTokenParse: 'トークンエラー: {{ .detail }}'
ErrInitialPassword: '元のパスワードが正しくありません' ErrInitialPassword: '元のパスワードが違います'
ErrInternalServer: '内部サーバーエラー: {{ .detail }}' ErrInternalServer: '内部エラー: {{ .detail }}'
ErrRecordExist: 'レコードがすでに存在します' ErrRecordExist: 'レコードが既に存在します'
ErrRecordNotFound: 'レコードが見つかりません' ErrRecordNotFound: 'レコードが見つかりません'
ErrStructTransform: '型変換に失敗しました: {{ .err }}' ErrStructTransform: '型変換エラー: {{ .err }}'
ErrNotLogin: 'ユーザーがログインしていません: {{ .detail }}' ErrNotLogin: 'ログインしていません: {{ .detail }}'
ErrPasswordExpired: '現在のパスワードの有効期限が切れています: {{ .detail }}' ErrPasswordExpired: 'パスワード期限切れ: {{ .detail }}'
ErrNotSupportType: 'システムは現在のタイプ: {{ .name }} をサポートしていません' ErrNotSupportType: '未対応のタイプ: {{ .name }}'
ErrProxy: 'リクエスト エラーです。ノードのステータスを確認してください: {{ .detail }}' ErrProxy: 'リクエストに失敗しました: {{ .detail }}'
ErrApiConfigStatusInvalid: 'API インターフェースへのアクセスは禁止されています: {{ .detail }}' ErrApiConfigStatusInvalid: 'API利用不可: {{ .detail }}'
ErrApiConfigKeyInvalid: 'API インターフェース キー エラー: {{ .detail }}' ErrApiConfigKeyInvalid: 'APIキーが無効です: {{ .detail }}'
ErrApiConfigIPInvalid: 'API インターフェースの呼び出しに使用された IP がホワイトリストにありません: {{ .detail }}' ErrApiConfigIPInvalid: 'IPが許可されていません: {{ .detail }}'
ErrApiConfigDisable: 'このインターフェースは、API インターフェース呼び出しの使用を禁止しています: {{ .detail }}' ErrApiConfigDisable: 'APIは無効です: {{ .detail }}'
ErrApiConfigKeyTimeInvalid: 'API インターフェースのタイムスタンプ エラー: {{ .detail }}' ErrApiConfigKeyTimeInvalid: 'タイムスタンプが無効です: {{ .detail }}'
ErrShutDown: 'コマンドは手動で停止されました'
ErrMinQuickJump: "少なくとも1つのクイックジャンプエントリを設定してください!" ErrMinQuickJump: 'クイックアクセスを1件以上追加'
ErrMaxQuickJump: "最大4つのクイックジャンプエントリを設定できます!" ErrMaxQuickJump: '最大4件のクイックアクセス'
ErrUsernameIsExist: 'ユーザー名はすでに使われています'
#common ErrNameIsExist: '名称はすでに使われています'
ErrUsernameIsExist: 'ユーザー名は既に存在します' ErrDemoEnvironment: 'デモ環境では利用できません'
ErrNameIsExist: '名前は既に存在します' ErrCmdTimeout: 'コマンドがタイムアウトしました'
ErrDemoEnvironment: 'デモ サーバー、この操作は禁止されています!' ErrCmdIllegal: 'コマンドに無効な文字が含まれています'
ErrCmdTimeout: 'コマンドの実行がタイムアウトしました!' ErrPortExist: 'ポート {{ .port }} は {{ .type }} [{{ .name }}] が使用中です'
ErrCmdIllegal: '実行コマンドに不正な文字が含まれています。修正してもう一度お試しください。'
ErrPortExist: '{{ .port }} ポートは、{{ .type }} [{{ .name }}] によって既に使用されています'
TYPE_APP: 'アプリケーション' TYPE_APP: 'アプリケーション'
TYPE_RUNTIME: 'ランタイム環境' TYPE_RUNTIME: 'ランタイム環境'
TYPE_DOMAIN: 'ドメイン名' TYPE_DOMAIN: 'ドメイン名'
@@ -35,45 +33,39 @@ Failed: '失敗'
SystemRestart: 'システムの再起動によりタスクが中断されました' SystemRestart: 'システムの再起動によりタスクが中断されました'
ErrGroupIsDefault: 'デフォルト グループ、削除できません' ErrGroupIsDefault: 'デフォルト グループ、削除できません'
ErrGroupIsInWebsiteUse: 'グループは別の Web サイトで使用されているため、削除できません。' ErrGroupIsInWebsiteUse: 'グループは別の Web サイトで使用されているため、削除できません。'
Decrypt: "復号化" Decrypt: '復号化'
ErrAgentAccountBound: 'アカウントはエージェントに紐づいています'
#agent ErrAgentAccountUnavailable: 'アカウント接続不可: {{ .err }}'
ErrAgentAccountBound: 'このアカウントはエージェントに紐付いているため削除できません。確認して再試行してください!' ErrAgentProviderNotSupported: 'エージェントプロバイダ非対応'
ErrAgentAccountUnavailable: 'アカウント接続情報を利用できません。エラー: {{ .err }}。確認して再試行してください!' ErrAgentAccountRequired: 'まずエージェントアカウントを選択'
ErrAgentProviderNotSupported: 'このエージェント提供元はサポートされていません。確認して再試行してください!' ErrAgentAccountNotVerified: 'アカウント未検証です'
ErrAgentAccountRequired: 'エージェントアカウントを選択して再試行してください。' ErrAgentProviderMismatch: 'エージェントプロバイダが一致しません'
ErrAgentAccountNotVerified: 'アカウントの検証が完了していません。確認して再試行してください!' ErrAgentBaseURLRequired: 'ベースURLが必要です'
ErrAgentProviderMismatch: 'アカウントの提供元が一致しません。確認して再試行してください!' ErrAgentApiKeyRequired: 'APIキーが必要です'
ErrAgentBaseURLRequired: 'Base URL を空にできません。確認して再試行してください!' ErrAgentComposeRequired: 'Composeが必要です'
ErrAgentApiKeyRequired: 'API Key を空にできません。確認して再試行してください!' ErrAgentIDRequired: 'エージェントIDが必要です'
ErrAgentComposeRequired: 'カスタム compose 内容を空にできません。確認して再試行してください!' ErrAgentAccountIDRequired: 'アカウントIDが必要です'
ErrAgentIDRequired: 'エージェント ID を空にできません。確認して再試行してください!'
ErrAgentAccountIDRequired: 'アカウント ID を空にできません。確認して再試行してください!'
#backup
Localhost: 'ローカルマシン' Localhost: 'ローカルマシン'
ErrBackupInUsed: 'バックアップ アカウントはスケジュールされたタスクで使用されているため、削除できません。' ErrBackupInUsed: 'バックアップアカウントがスケジュールで使用中'
ErrBackupCheck: 'バックアップ アカウントのテスト接続に失敗しました {{ .err }}' ErrBackupCheck: '接続テストに失敗しました: {{ .err }}'
ErrBackupLocalDelete: 'ローカル サーバーのバックアップ アカウントの削除はまだサポートされていません' ErrBackupLocalDelete: 'ローカルバックアップは削除できません'
ErrBackupLocalCreate: 'ローカル サーバーのバックアップ アカウントの作成はまだサポートされていません' ErrBackupLocalCreate: 'ローカルバックアップは作成できません'
ErrPortInUsed: '{{ .detail }} ポートはすでに使用されています'
#app
ErrPortInUsed: '{{ .detail }} ポートはすでに使用されています!'
ErrAppLimit: 'インストールされているアプリケーションの数が制限を超えました' ErrAppLimit: 'インストールされているアプリケーションの数が制限を超えました'
ErrNotInstall: 'アプリケーションがインストールされていません' ErrNotInstall: 'アプリケーションがインストールされていません'
ErrPortInOtherApp: '{{ .port }} ポートは既にアプリケーション {{ .apps }} によって使用されています!' ErrPortInOtherApp: '{{ .port }} ポートは既にアプリケーション {{ .apps }} によって使用されています'
ErrDbUserNotValid: '既存のデータベース、ユーザー名、およびパスワードが一致しません!' ErrDbUserNotValid: '既存のデータベース、ユーザー名、およびパスワードが一致しません'
ErrUpdateBuWebsite: 'アプリケーションは正常に更新されましたが、Web サイト構成ファイルの変更に失敗しました。設定を確認してください! ' ErrUpdateBuWebsite: 'アプリケーションは正常に更新されましたが、Web サイト構成ファイルの変更に失敗しました。設定を確認してください'
Err1PanelNetworkFailed: 'デフォルトのコンテナ ネットワークの作成に失敗しました。 {{ .detail }}' Err1PanelNetworkFailed: 'デフォルトのコンテナ ネットワークの作成に失敗しました。 {{ .detail }}'
ErrFileParse: 'アプリケーションの docker-compose ファイルの解析に失敗しました!' ErrFileParse: 'アプリケーションの docker-compose ファイルの解析に失敗しました'
ErrInstallDirNotFound: 'インストール ディレクトリが存在しません。アンインストールする必要がある場合は、強制アンインストールを選択してください。' ErrInstallDirNotFound: 'インストール ディレクトリが存在しません。アンインストールする必要がある場合は、強制アンインストールを選択してください。'
AppStoreIsUpToDate: 'アプリストアはすでに最新バージョンです' AppStoreIsUpToDate: 'アプリストアはすでに最新バージョンです'
LocalAppVersionNull: '{{ .name }} アプリケーションはバージョンに同期されていません。アプリリストに追加できません' LocalAppVersionNull: '{{ .name }} アプリケーションはバージョンに同期されていません。アプリリストに追加できません'
LocalAppVersionErr: '{{ .name }} バージョン {{ .version }} の同期に失敗しました! {{ .err }}' LocalAppVersionErr: '{{ .name }} バージョン {{ .version }} の同期に失敗しました {{ .err }}'
ErrFileNotFound: '{{ .name }} ファイルが存在しません' ErrFileNotFound: '{{ .name }} ファイルが存在しません'
ErrFileParseApp: '{{ .name }} ファイルの解析に失敗しました {{ .err }}' ErrFileParseApp: '{{ .name }} ファイルの解析に失敗しました {{ .err }}'
ErrAppDirNull: 'バージョン フォルダーが存在しません' ErrAppDirNull: 'バージョン フォルダーが存在しません'
LocalAppErr: 'アプリケーション {{ .name }} の同期に失敗しました! {{ .err }}' LocalAppErr: 'アプリケーション {{ .name }} の同期に失敗しました {{ .err }}'
ErrContainerName: 'コンテナ名が既に存在します' ErrContainerName: 'コンテナ名が既に存在します'
ErrCreateHttpClient: 'リクエスト {{ .err }} の作成に失敗しました' ErrCreateHttpClient: 'リクエスト {{ .err }} の作成に失敗しました'
ErrHttpReqTimeOut: 'リクエストがタイムアウトしました {{ .err }}' ErrHttpReqTimeOut: 'リクエストがタイムアウトしました {{ .err }}'
@@ -86,64 +78,58 @@ ErrAppBackup: '{{ .name }} アプリケーションのバックアップに失
ErrVersionTooLow: '現在の 1Panel のバージョンが低すぎるため、App Store を更新できません。操作する前にバージョンをアップグレードしてください。' ErrVersionTooLow: '現在の 1Panel のバージョンが低すぎるため、App Store を更新できません。操作する前にバージョンをアップグレードしてください。'
ErrAppNameExist: 'アプリケーション名がすでに存在します' ErrAppNameExist: 'アプリケーション名がすでに存在します'
AppStoreIsSyncing: 'App Store が同期中です。しばらくしてからもう一度お試しください' AppStoreIsSyncing: 'App Store が同期中です。しばらくしてからもう一度お試しください'
ErrGetCompose: 'docker-compose.yml ファイルの取得に失敗しました! {{ .detail }}' ErrGetCompose: 'docker-compose.yml ファイルの取得に失敗しました {{ .detail }}'
ErrAppWarn: '異常な状態です。ログを確認してください' ErrAppWarn: '異常な状態です。ログを確認してください'
ErrAppParamKey: 'パラメータ {{ .name }} フィールドが異常です' ErrAppParamKey: 'パラメータ {{ .name }} フィールドが異常です'
ErrAppUpgrade: 'アプリケーション {{ .name }} のアップグレードに失敗しました {{ .err }}' ErrAppUpgrade: 'アプリケーション {{ .name }} のアップグレードに失敗しました {{ .err }}'
AppRecover: 'アプリケーション {{ .name }} をロールバックします' AppRecover: 'アプリケーション {{ .name }} をロールバックします'
PullImageStart: "イメージ [{{ .name }}] のプルを開始します" PullImageStart: 'イメージ [{{ .name }}] のプルを開始します'
PullImageSuccess: 'イメージのプルが成功しました' PullImageSuccess: 'イメージのプルが成功しました'
AppStoreIsLastVersion: 'App Store はすでに最新バージョンです'
AppStoreSyncSuccess: 'App Store の同期が成功しました' AppStoreSyncSuccess: 'App Store の同期が成功しました'
SyncAppDetail: 'アプリケーション構成を同期する' SyncAppDetail: 'アプリケーション構成を同期する'
AppVersionNotMatch: '{{ .name }} アプリケーションには、より高い 1Panel バージョンが必要なため、同期をスキップします' AppVersionNotMatch: '{{ .name }} アプリケーションには、より高い 1Panel バージョンが必要なため、同期をスキップします'
MoveSiteDir: "ウェブサイトディレクトリの変更を検出しました。OpenResty ウェブサイトディレクトリを {{ .name }} に移行する必要があります" MoveSiteDir: 'ウェブサイトディレクトリの変更を検出しました。OpenResty ウェブサイトディレクトリを {{ .name }} に移行する必要があります'
MoveSiteDirSuccess: 'Web サイト ディレクトリの移行に成功しました' MoveSiteDirSuccess: 'Web サイト ディレクトリの移行に成功しました'
DeleteRuntimePHP: 'PHP ランタイムを削除する' DeleteRuntimePHP: 'PHP ランタイムを削除する'
CustomAppStoreFileValid: 'App Store パッケージは .tar.gz 形式である必要があります' CustomAppStoreFileValid: 'App Store パッケージは.tar.gz 形式である必要があります'
PullImageTimeout: 'プル イメージのタイムアウトです。イメージのアクセラレーションを増やすか、別のイメージのアクセラレーションに変更してください' PullImageTimeout: 'プル イメージのタイムアウトです。イメージのアクセラレーションを増やすか、別のイメージのアクセラレーションに変更してください'
ErrAppIsDown: '{{ .name }} アプリケーションの状態が異常です。確認してください' ErrAppIsDown: '{{ .name }} アプリケーションの状態が異常です。確認してください'
ErrCustomApps: 'インストールされているアプリケーションがあります。まずアンインストールしてください' ErrCustomApps: 'インストールされているアプリケーションがあります。まずアンインストールしてください'
ErrCustomRuntimes: 'ランタイム環境がインストールされています。まずそれを削除してください' ErrCustomRuntimes: 'ランタイム環境がインストールされています。まずそれを削除してください'
ErrAppVersionDeprecated: "{{ .name }} アプリケーションは現在の 1Panel バージョンと互換性がありません、スキップしました" ErrAppVersionDeprecated: '{{ .name }} アプリケーションは現在の 1Panel バージョンと互換性がありません、スキップしました'
ErrDockerFailed: "Docker の状態が異常です。サービス状態を確認してください" ErrDockerFailed: 'Docker の状態が異常です。サービス状態を確認してください'
ErrDockerComposeCmdNotFound: "Docker Compose コマンドは存在しません。ホストマシンにこのコマンドを先にインストールしてください" ErrDockerComposeCmdNotFound: 'Docker Compose コマンドは存在しません。ホストマシンにこのコマンドを先にインストールしてください'
UseExistImage: 'イメージのプルに失敗しました、既存のイメージを使用します' UseExistImage: 'イメージは既に存在します。既存のイメージを使用します'
ErrDatabaseNotFound: 'データベース {{ .name }} は存在しません'
#ssh ExportIP: 'ログインIP'
ExportIP: "ログインIP" ExportArea: '地域'
ExportArea: "地域" ExportPort: 'ポート'
ExportPort: "ポート" ExportAuthMode: 'ログイン方式'
ExportAuthMode: "ログイン方式" ExportUser: 'ユーザー'
ExportUser: "ユーザー" ExportStatus: 'ログイン状態'
ExportStatus: "ログイン状態" ExportDate: '時間'
ExportDate: "時間"
#file
ErrFileCanNotRead: 'このファイルはプレビューをサポートしていません' ErrFileCanNotRead: 'このファイルはプレビューをサポートしていません'
ErrFileToLarge: 'ファイルは 10M より大きいため開けません' ErrFileToLarge: 'ファイルは 10M より大きいため開けません'
ErrPathNotFound: 'ディレクトリが存在しません' ErrPathNotFound: 'ディレクトリが存在しません'
ErrMovePathFailed: 'ターゲット パスに元のパスを含めることはできません!' ErrMovePathFailed: 'ターゲット パスに元のパスを含めることはできません'
ErrLinkPathNotFound: 'ターゲット パスが存在しません!' ErrLinkPathNotFound: 'ターゲット パスが存在しません'
ErrFileIsExist: 'ファイルまたはフォルダーは既に存在します!' ErrFileIsExist: 'ファイルまたはフォルダーは既に存在します'
ErrFileUpload: '{{ .name }} はファイル {{ .detail }} のアップロードに失敗しました' ErrFileUpload: '{{ .name }} はファイル {{ .detail }} のアップロードに失敗しました'
ErrFileDownloadDir: 'ダウンロード フォルダーはサポートされていません' ErrFileDownloadDir: 'ダウンロード フォルダーはサポートされていません'
ErrCmdNotFound: '{{ .name}} コマンドが存在しません。まずこのコマンドをホストにインストールしてください' ErrCmdNotFound: '{{ .name }} コマンドが存在しません。まずこのコマンドをホストにインストールしてください'
ErrSourcePathNotFound: 'ソース ディレクトリが存在しません' ErrSourcePathNotFound: 'ソース ディレクトリが存在しません'
ErrFavoriteExist: 'このパスはすでにお気に入りに登録されています' ErrFavoriteExist: 'このパスはすでにお気に入りに登録されています'
ErrInvalidChar: '不正な文字は許可されません' ErrInvalidChar: '不正な文字は許可されません'
ErrPathNotDelete: '選択されたディレクトリは削除できません' ErrPathNotDelete: '選択されたディレクトリは削除できません'
ErrLogFileToLarge: "ログファイルが500MBを超えており、開くことができません" ErrLogFileToLarge: 'ログファイルが500MBを超えており、開くことができません'
FileDropFailed: "ファイル {{ .name }} のクリーンアップに失敗しました: {{ .err }}" FileDropFailed: 'ファイル {{ .name }} のクリーンアップに失敗しました: {{ .err }}'
FileDropSuccess: "ファイル {{ .name }} のクリーンアップに成功しました、{{ .count }} ファイルを削除、{{ .size }} のディスク領域を解放" FileDropSuccess: 'ファイル {{ .name }} のクリーンアップに成功しました、{{ .count }} ファイルを削除、{{ .size }} のディスク領域を解放'
FileDropSum: "ファイルのクリーンアップが完了しました、合計 {{ .count }} ファイルを削除、合計 {{ .size }} のディスク領域を解放" FileDropSum: 'ファイルのクリーンアップが完了しました、合計 {{ .count }} ファイルを削除、合計 {{ .size }} のディスク領域を解放'
ErrBadDecrypt: "圧縮パッケージの解凍パスワードが間違っています。解凍に失敗しました。確認して再試行してください!" ErrBadDecrypt: '圧縮パッケージの解凍パスワードが間違っています。解凍に失敗しました。確認後再試行!'
#website
ErrAliasIsExist: 'エイリアスがすでに存在します' ErrAliasIsExist: 'エイリアスがすでに存在します'
ErrBackupMatch: 'バックアップ ファイルは、現在の Web サイト データ {{ .detail }} の一部と一致しません' ErrBackupMatch: 'バックアップ ファイルは、現在の Web サイト データ {{ .detail }} の一部と一致しません'
ErrBackupExist: 'バックアップ ファイル内のソース データの対応する部分が存在しません {{ .detail }}' ErrBackupExist: 'バックアップ ファイル内のソース データの対応する部分が存在しません {{ .detail }}'
ErrPHPResource: 'ローカルオペレーティング環境は切り替えをサポートしていません! ' ErrPHPResource: 'ローカルオペレーティング環境は切り替えをサポートしていません'
ErrPathPermission: 'インデックス ディレクトリに 1000:1000 以外の権限を持つフォルダーが検出されました。これにより、Web サイトでアクセス拒否エラーが発生する可能性があります。上記の保存ボタンをクリックしてください。' ErrPathPermission: 'インデックス ディレクトリに 1000:1000 以外の権限を持つフォルダーが検出されました。これにより、Web サイトでアクセス拒否エラーが発生する可能性があります。上記の保存ボタンをクリックしてください。'
ErrDomainIsUsed: 'ドメイン名はウェブサイト [{{ .name }}] で既に使用されています' ErrDomainIsUsed: 'ドメイン名はウェブサイト [{{ .name }}] で既に使用されています'
ErrDomainFormat: '{{ .name }} ドメイン名の形式が正しくありません' ErrDomainFormat: '{{ .name }} ドメイン名の形式が正しくありません'
@@ -151,11 +137,11 @@ ErrDefaultAlias: 'デフォルトは予約済みのコードです。別のコ
ErrParentWebsite: 'まずサブサイト {{ .name }} を削除する必要があります' ErrParentWebsite: 'まずサブサイト {{ .name }} を削除する必要があります'
ErrBuildDirNotFound: 'ビルド ディレクトリが存在しません' ErrBuildDirNotFound: 'ビルド ディレクトリが存在しません'
ErrImageNotExist: 'オペレーティング環境 {{ .name }} イメージが存在しません。オペレーティング環境を再編集してください' ErrImageNotExist: 'オペレーティング環境 {{ .name }} イメージが存在しません。オペレーティング環境を再編集してください'
ErrProxyIsUsed: "ロードバランシングはリバースプロキシによって使用されているため、削除できません" ErrProxyIsUsed: 'ロードバランシングはリバースプロキシによって使用されているため、削除できません'
ErrSSLValid: '証明書ファイルが異常です、証明書の状態を確認してください!' ErrSSLValid: '証明書ファイルが異常です、証明書の状態を確認してください!'
ErrWebsiteDir: "ウェブサイトディレクトリ内のディレクトリを選択してください。" ErrWebsiteDir: 'ウェブサイトディレクトリ内のディレクトリを選択してください。'
ErrComposerFileNotFound: "composer.json ファイルが存在しません" ErrComposerFileNotFound: 'composer.json ファイルが存在しません'
ErrRuntimeNoPort: "ランタイム環境にポートが設定されていません。先にランタイム環境を編集してください。" ErrRuntimeNoPort: 'ランタイム環境にポートが設定されていません。先にランタイム環境を編集してください。'
Status: 'ステータス' Status: 'ステータス'
start: '開始' start: '開始'
stop: '停止' stop: '停止'
@@ -168,8 +154,6 @@ delete: '削除'
ErrDefaultWebsite: 'デフォルト Web サイトが既に設定されています。設定する前にキャンセルしてください!' ErrDefaultWebsite: 'デフォルト Web サイトが既に設定されています。設定する前にキャンセルしてください!'
SSL: '証明書' SSL: '証明書'
Set: '設定' Set: '設定'
#ssl
ErrSSLCannotDelete: '{{ .name }} 証明書は Web サイトで使用されているため、削除できません' ErrSSLCannotDelete: '{{ .name }} 証明書は Web サイトで使用されているため、削除できません'
ErrAccountCannotDelete: 'アカウントは証明書に関連付けられているため、削除できません' ErrAccountCannotDelete: 'アカウントは証明書に関連付けられているため、削除できません'
ErrSSLApply: '証明書の更新は成功しましたが、openresty の再ロードに失敗しました。設定を確認してください。' ErrSSLApply: '証明書の更新は成功しましたが、openresty の再ロードに失敗しました。設定を確認してください。'
@@ -180,12 +164,12 @@ ErrSSLKeyFormat: '秘密鍵ファイルの検証に失敗しました'
ErrSSLCertificateFormat: '証明書ファイルの形式が正しくありません。pem 形式を使用してください' ErrSSLCertificateFormat: '証明書ファイルの形式が正しくありません。pem 形式を使用してください'
ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid または EabHmacKey は空白にできません' ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid または EabHmacKey は空白にできません'
ErrOpenrestyNotFound: 'Http モードでは、まず Openresty をインストールする必要があります' ErrOpenrestyNotFound: 'Http モードでは、まず Openresty をインストールする必要があります'
ApplySSLStart: '証明書の申請を開始します。ドメイン名 [{{ .domain }}] 申請方法 [{{ .type }}] ' ApplySSLStart: '証明書の申請を開始します。ドメイン名 [{{ .domain }}] 申請方法 [{{ .type }}]'
dnsAccount: 'DNS 自動' dnsAccount: 'DNS 自動'
dnsManual: 'DNS マニュアル' dnsManual: 'DNS マニュアル'
http: "HTTP" http: 'HTTP'
ApplySSLFailed: '[{{ .domain }}] 証明書の申請に失敗しました、{{ .detail }}' ApplySSLFailed: '[{{ .domain }}] 証明書の申請に失敗しました、{{ .detail }}'
ApplySSLSuccess: '[{{ .domain }}] 証明書の申請に成功しました! ' ApplySSLSuccess: '[{{ .domain }}] 証明書の申請に成功しました。'
DNSAccountName: 'DNS アカウント [{{ .name }}] ベンダー [{{ .type }}]' DNSAccountName: 'DNS アカウント [{{ .name }}] ベンダー [{{ .type }}]'
PushDirLog: '証明書がディレクトリ [{{ .path }}] {{ .status }} にプッシュされました' PushDirLog: '証明書がディレクトリ [{{ .path }}] {{ .status }} にプッシュされました'
ErrDeleteCAWithSSL: '現在の組織には発行済みの証明書があり、削除できません。' ErrDeleteCAWithSSL: '現在の組織には発行済みの証明書があり、削除できません。'
@@ -200,41 +184,33 @@ ExecShellSuccess: 'スクリプトの実行が成功しました'
StartUpdateSystemSSL: 'システム証明書の更新を開始します' StartUpdateSystemSSL: 'システム証明書の更新を開始します'
UpdateSystemSSLSuccess: 'システム証明書を正常に更新しました' UpdateSystemSSLSuccess: 'システム証明書を正常に更新しました'
ErrWildcardDomain: 'HTTP モードでワイルドカード ドメイン名証明書を申請できません' ErrWildcardDomain: 'HTTP モードでワイルドカード ドメイン名証明書を申請できません'
ErrApplySSLCanNotDelete: "申請中の証明書 {{.name}} は削除できません。しばらくしてからもう一度お試しください。" ErrApplySSLCanNotDelete: '申請中の証明書 {{ .name }} は削除できません。しばらくしてからもう一度お試しください。'
StartPushSSLToNode: "証明書をノードにプッシュ開始" StartPushSSLToNode: '証明書をノードにプッシュ開始'
PushSSLToNodeFailed: "ノードに証明書をプッシュ失敗: {{ .err }}" PushSSLToNodeFailed: 'ノードに証明書をプッシュ失敗: {{ .err }}'
PushSSLToNodeSuccess: "ノードに証明書をプッシュ成功" PushSSLToNodeSuccess: 'ノードに証明書をプッシュ成功'
#mysql
ErrUserIsExist: '現在のユーザーは既に存在します。再入力してください' ErrUserIsExist: '現在のユーザーは既に存在します。再入力してください'
ErrDatabaseIsExist: '現在のデータベースは既に存在します。再入力してください' ErrDatabaseIsExist: '現在のデータベースは既に存在します。再入力してください'
ErrExecTimeOut: 'SQL 実行がタイムアウトしました。データベースを確認してください' ErrExecTimeOut: 'SQL 実行がタイムアウトしました。データベースを確認してください'
ErrRemoteExist: 'この名前のリモート データベースは既に存在します。変更してもう一度お試しください' ErrRemoteExist: 'この名前のリモート データベースは既に存在します。変更してもう一度お試しください'
ErrLocalExist: '名前はローカル データベースに既に存在します。変更してもう一度お試しください' ErrLocalExist: '名前はローカル データベースに既に存在します。変更してもう一度お試しください'
RemoteBackup: "リモートデータベースをバックアップするには、まずイメージ {{ .name }} を使用してローカルコンテナデータベースサービスを起動する必要があります。しばらくお待ちください..." RemoteBackup: 'リモートデータベースをバックアップするには、まずイメージ {{ .name }} を使用してローカルコンテナデータベースサービスを起動する必要があります。しばらくお待ちください...'
RemoteRecover: "リモートデータベースを復元するには、まずイメージ {{ .name }} を使用してローカルコンテナデータベースサービスを起動する必要があります。しばらくお待ちください..." RemoteRecover: 'リモートデータベースを復元するには、まずイメージ {{ .name }} を使用してローカルコンテナデータベースサービスを起動する必要があります。しばらくお待ちください...'
Arg: "引数" Arg: '引数'
#redis
ErrTypeOfRedis: 'リカバリ ファイルの種類が現在の永続化方法と一致しません。変更して再試行してください' ErrTypeOfRedis: 'リカバリ ファイルの種類が現在の永続化方法と一致しません。変更して再試行してください'
ErrInUsed: '{{ .detail }} は使用中であり、削除できません!'
#container ErrObjectInUsed: 'このオブジェクトは使用中であり、削除できません!'
ErrInUsed: "{{ .detail }} は使用中であり、削除できません!" ErrObjectBeDependent: 'このイメージは他のイメージに依存されているため、削除できません!'
ErrObjectInUsed: "このオブジェクトは使用中であり、削除できません!"
ErrObjectBeDependent: "このイメージは他のイメージに依存されているため、削除できません!"
ErrPortRules: 'ポート番号が一致しません。再入力してください。' ErrPortRules: 'ポート番号が一致しません。再入力してください。'
ErrPgImagePull: 'イメージのプルがタイムアウトしました。イメージのアクセラレーションを設定するか、{{ .name }} イメージを手動でプルして再試行してください' ErrPgImagePull: 'イメージのプルがタイムアウトしました。イメージのアクセラレーションを設定するか、{{ .name }} イメージを手動でプルして再試行してください'
PruneHelper: "今回のクリーンアップ {{ .name }} でディスク領域 {{ .size }} を解放しました" PruneHelper: '今回のクリーンアップ {{ .name }} でディスク領域 {{ .size }} を解放しました'
ImageRemoveHelper: "イメージ{{ .name }}を削除し、{{ .size }}のディスク領域を解放しました" ImageRemoveHelper: 'イメージ{{ .name }}を削除し、{{ .size }}のディスク領域を解放しました'
BuildCache: "ビルドキャッシュ" BuildCache: 'ビルドキャッシュ'
Volume: "ストレージボリューム" Volume: 'ストレージボリューム'
Network: "ネットワーク" Network: 'ネットワーク'
PruneStart: "クリーンアップ中、しばらくお待ちください..." PruneStart: 'クリーンアップ中、しばらくお待ちください...'
#runtime
ErrFileNotExist: '{{ .detail }} ファイルが存在しません。ソース ファイルの整合性を確認してください。' ErrFileNotExist: '{{ .detail }} ファイルが存在しません。ソース ファイルの整合性を確認してください。'
ErrImageBuildErr: 'イメージのビルドに失敗しました' ErrImageBuildErr: 'イメージのビルドに失敗しました'
ErrImageExist: "イメージはすでに存在します!イメージ名を変更してください。" ErrImageExist: 'イメージはすでに存在します!イメージ名を変更してください。'
ErrDelWithWebsite: 'オペレーティング環境は既に Web サイトに関連付けられているため、削除できません' ErrDelWithWebsite: 'オペレーティング環境は既に Web サイトに関連付けられているため、削除できません'
ErrRuntimeStart: '起動に失敗しました' ErrRuntimeStart: '起動に失敗しました'
ErrPackageJsonNotFound: 'package.json ファイルが存在しません' ErrPackageJsonNotFound: 'package.json ファイルが存在しません'
@@ -242,55 +218,45 @@ ErrScriptsNotFound: 'スクリプト構成項目が package.json に見つかり
ErrContainerNameNotFound: 'コンテナ名を取得できません。.env ファイルを確認してください' ErrContainerNameNotFound: 'コンテナ名を取得できません。.env ファイルを確認してください'
ErrNodeModulesNotFound: 'node_modules フォルダが存在しません。ランタイム環境を編集するか、ランタイム環境が正常に起動するまでお待ちください。' ErrNodeModulesNotFound: 'node_modules フォルダが存在しません。ランタイム環境を編集するか、ランタイム環境が正常に起動するまでお待ちください。'
ErrContainerNameIsNull: 'コンテナ名が存在しません' ErrContainerNameIsNull: 'コンテナ名が存在しません'
ErrPHPPortIsDefault: "ポート9000はデフォルトポートです。修正してから再試行してください" ErrPHPPortIsDefault: 'ポート9000はデフォルトポートです。修正してから再試行してください'
ErrPHPRuntimePortFailed: "ポート {{ .name }} は現在のランタイム環境で使用されています。修正してから再試行してください" ErrPHPRuntimePortFailed: 'ポート {{ .name }} は現在のランタイム環境で使用されています。修正してから再試行してください'
#tool
ErrConfigNotFound: '構成ファイルが存在しません' ErrConfigNotFound: '構成ファイルが存在しません'
ErrConfigParse: '構成ファイルの形式が正しくありません' ErrConfigParse: '構成ファイルの形式が正しくありません'
ErrConfigIsNull: '構成ファイルは空にできません' ErrConfigIsNull: '構成ファイルは空にできません'
ErrConfigDirNotFound: '実行ディレクトリが存在しません' ErrConfigDirNotFound: '実行ディレクトリが存在しません'
ErrConfigAlreadyExist: '同じ名前の設定ファイルがすでに存在します' ErrConfigAlreadyExist: '同じ名前の設定ファイルがすでに存在します'
ErrUserFindErr: 'ユーザー {{ .name }} の検索に失敗しました {{ .err }}' ErrUserFindErr: 'ユーザー {{ .name }} の検索に失敗しました {{ .err }}'
#cronjob
CutWebsiteLogSuccess: '{{ .name }} ウェブサイトのログが正常にカットされました。バックアップ パス {{ .path }}' CutWebsiteLogSuccess: '{{ .name }} ウェブサイトのログが正常にカットされました。バックアップ パス {{ .path }}'
HandleShell: 'スクリプト {{ .name }} を実行します' HandleShell: 'スクリプト {{ .name }} を実行します'
HandleCurl: "URL {{ .name }} にアクセス" HandleCurl: 'URL {{ .name }} にアクセス'
HandleNtpSync: 'システム時刻の同期' HandleNtpSync: 'システム時刻の同期'
HandleSystemClean: 'システム キャッシュのクリーンアップ' HandleSystemClean: 'システム キャッシュのクリーンアップ'
SystemLog: 'システムログ' SystemLog: 'システムログ'
CutWebsiteLog: 'ウェブサイトログのローテーション' CutWebsiteLog: 'ウェブサイトログのローテーション'
FileOrDir: 'ディレクトリ / ファイル' FileOrDir: 'ディレクトリ / ファイル'
UploadFile: 'バックアップファイル {{ .file }} を {{ .backup }} にアップロード中' UploadFile: 'バックアップファイル {{ .file }} を {{ .backup }} にアップロード中'
Upload: "アップロード" Upload: 'アップロード'
IgnoreBackupErr: "バックアップ失敗、エラー: {{ .detail }}、このエラーを無視します..." IgnoreBackupErr: 'バックアップ失敗、エラー: {{ .detail }}、このエラーを無視します...'
IgnoreUploadErr: "アップロード失敗、エラー: {{ .detail }}、このエラーを無視します..." IgnoreUploadErr: 'アップロード失敗、エラー: {{ .detail }}、このエラーを無視します...'
LoadBackupFailed: "バックアップアカウントの接続取得に失敗、エラー: {{ .detail }}" LoadBackupFailed: 'バックアップアカウントの接続取得に失敗、エラー: {{ .detail }}'
InExecuting: "現在のタスクは実行中です。重複して実行しないでください!" InExecuting: '現在のタスクは実行中です。重複して実行しないでください!'
NoSuchResource: "データベースにバックアップ内容が見つかりませんでした。スキップします..." NoSuchResource: 'データベースにバックアップ内容が見つかりませんでした。スキップします...'
CleanLog: "ログをクリーン" CleanLog: 'ログをクリーン'
CleanLogByName: "{{.name}} のログをクリーン" CleanLogByName: '{{ .name }} のログをクリーン'
WafIpGroupNotFound: "WAF IPグループが見つかりません。[高度な機能 - WAF - ブラックリスト/ホワイトリスト - IPグループ]に移動し、リモートダウンロード方式でIPグループを追加してください。" WafIpGroupNotFound: 'WAF IPグループが見つかりません。[高度な機能 - WAF - ブラックリスト/ホワイトリスト - IPグループ]に移動し、リモートダウンロード方式でIPグループを追加してください。'
#toolbox
ErrNotExistUser: '現在のユーザーは存在しません。変更してもう一度お試しください。' ErrNotExistUser: '現在のユーザーは存在しません。変更してもう一度お試しください。'
ErrBanAction: '設定に失敗しました。現在の {{ .name }} サービスは利用できません。確認してもう一度お試しください。' ErrBanAction: '設定に失敗しました。現在の {{ .name }} サービスは利用できません。確認してもう一度お試しください。'
ErrClamdscanNotFound: 'clamdscan コマンドが検出されませんでした。インストールするにはドキュメントを参照してください。' ErrClamdscanNotFound: 'clamdscan コマンドが検出されませんでした。インストールするにはドキュメントを参照してください。'
TaskSwapSet: "Swap設定" TaskSwapSet: 'Swap設定'
SetSwap: "Swap設定 {{ .path }} - {{ .size }}" SetSwap: 'Swap設定 {{ .path }} - {{ .size }}'
CreateSwap: "Swapファイル作成" CreateSwap: 'Swapファイル作成'
FormatSwap: "Swapファイルフォーマット" FormatSwap: 'Swapファイルフォーマット'
EnableSwap: "Swapファイル有効化" EnableSwap: 'Swapファイル有効化'
CleanTamperSetting: '履歴保護設定をクリーンアップ'
#tamper SetTamperWithRules: 'ルールに従ってディレクトリ保護を開始'
CleanTamperSetting: "履歴保護設定をクリーンアップ" ProtectDir: 'ディレクトリを保護 {{ .name }}'
SetTamperWithRules: "ルールに従ってディレクトリ保護を開始" IgnoreFile: 'ファイルを保護 {{ .name }}'
ProtectDir: "ディレクトリを保護 {{ .name }}" TamperSetSuccessful: '保護設定が完了し、以下のディレクトリの監視を開始します:'
IgnoreFile: "ファイルを保護 {{ .name }}"
TamperSetSuccessful: "保護設定が完了し、以下のディレクトリの監視を開始します:"
#waf
ErrScope: 'この構成の変更はサポートされていません' ErrScope: 'この構成の変更はサポートされていません'
ErrStateChange: '状態の変更に失敗しました' ErrStateChange: '状態の変更に失敗しました'
ErrRuleExist: 'ルールは既に存在します' ErrRuleExist: 'ルールは既に存在します'
@@ -298,7 +264,7 @@ ErrRuleNotExist: 'ルールが存在しません'
ErrParseIP: 'IP 形式が間違っています' ErrParseIP: 'IP 形式が間違っています'
ErrDefaultIP: 'デフォルトは予約名です。別の名前に変更してください' ErrDefaultIP: 'デフォルトは予約名です。別の名前に変更してください'
ErrGroupInUse: 'IP グループはブラックリスト/ホワイトリストで使用されており、削除できません' ErrGroupInUse: 'IP グループはブラックリスト/ホワイトリストで使用されており、削除できません'
ErrIPGroupAclUse: "IPグループはウェブサイト {{ .name }} のカスタムルールで使用されているため、削除できません" ErrIPGroupAclUse: 'IPグループはウェブサイト {{ .name }} のカスタムルールで使用されているため、削除できません'
ErrGroupExist: 'IP グループ名がすでに存在します' ErrGroupExist: 'IP グループ名がすでに存在します'
ErrIPRange: 'IP 範囲が間違っています' ErrIPRange: 'IP 範囲が間違っています'
ErrIPExist: 'IP がすでに存在します' ErrIPExist: 'IP がすでに存在します'
@@ -309,10 +275,10 @@ xss: 'XSS'
phpExec: 'PHP スクリプトの実行' phpExec: 'PHP スクリプトの実行'
oneWordTrojan: 'ワンワードトロイの木馬' oneWordTrojan: 'ワンワードトロイの木馬'
appFilter: '危険なディレクトリフィルタリングを適用する' appFilter: '危険なディレクトリフィルタリングを適用する'
webshell: 'ウェブシェル' webShell: 'ウェブシェル'
args: 'パラメータルール' args: 'パラメータルール'
protocolFilter: 'プロトコルフィルタリング' protocolFilter: 'プロトコルフィルタリング'
javaFileter: 'Java 危険ファイル フィルター' javaFilter: 'Java 危険ファイル フィルター'
scannerFilter: 'スキャナ フィルタ' scannerFilter: 'スキャナ フィルタ'
escapeFilter: 'エスケープフィルター' escapeFilter: 'エスケープフィルター'
customRule: 'カスタムルール' customRule: 'カスタムルール'
@@ -342,10 +308,9 @@ ErrDBNotExist: 'データベースが存在しません'
allow: '許可' allow: '許可'
deny: '拒否' deny: '拒否'
OpenrestyNotFound: 'Openresty がインストールされていません' OpenrestyNotFound: 'Openresty がインストールされていません'
remoteIpIsNull: "IPリストが空です" remoteIpIsNull: 'IPリストが空です'
OpenrestyVersionErr: "Openrestyのバージョンが低すぎます。Openrestyを1.27.1.2-2-2-focalにアップグレードしてください" OpenrestyVersionErr: 'Openrestyのバージョンが低すぎます。Openrestyを1.27.1.2-2-2-focalにアップグレードしてください'
ErrFileTooLarge: 'ファイルが 1MB を超えているためアップロードできません'
#task
TaskStart: '{{ .name }} タスクが開始されました [START]' TaskStart: '{{ .name }} タスクが開始されました [START]'
TaskEnd: '{{ .name }} タスクが完了しました [COMPLETED]' TaskEnd: '{{ .name }} タスクが完了しました [COMPLETED]'
TaskFailed: '{{ .name }} タスクが失敗しました' TaskFailed: '{{ .name }} タスクが失敗しました'
@@ -361,7 +326,7 @@ TaskDelete: '削除'
TaskUpgrade: 'アップグレード' TaskUpgrade: 'アップグレード'
TaskUpdate: '更新' TaskUpdate: '更新'
TaskRestart: '再起動' TaskRestart: '再起動'
TaskProtect: "保護" TaskProtect: '保護'
TaskBackup: 'バックアップ' TaskBackup: 'バックアップ'
TaskRecover: '回復' TaskRecover: '回復'
TaskRollback: 'ロールバック' TaskRollback: 'ロールバック'
@@ -369,10 +334,10 @@ TaskPull: 'プル'
TaskCommit: 'コミット' TaskCommit: 'コミット'
TaskBuild: 'ビルド' TaskBuild: 'ビルド'
TaskPush: 'プッシュ' TaskPush: 'プッシュ'
TaskClean: "クリーンアップ" TaskClean: 'クリーンアップ'
TaskHandle: '実行' TaskHandle: '実行'
TaskImport: "インポート" TaskImport: 'インポート'
TaskExport: "エクスポート" TaskExport: 'エクスポート'
Website: 'ウェブサイト' Website: 'ウェブサイト'
App: 'アプリケーション' App: 'アプリケーション'
Runtime: 'ランタイム環境' Runtime: 'ランタイム環境'
@@ -404,18 +369,12 @@ RuntimeExtension: 'ランタイム環境拡張'
TaskIsExecuting: 'タスクは実行中です' TaskIsExecuting: 'タスクは実行中です'
CustomAppstore: 'カスタム アプリケーション ウェアハウス' CustomAppstore: 'カスタム アプリケーション ウェアハウス'
TaskExec: '実行' TaskExec: '実行'
TaskBatch: "一括操作" TaskBatch: '一括操作'
FileConvert: 'ファイル形式の変換' FileConvert: 'ファイル形式の変換'
Clamscan: '{{ .name }} をスキャン'
# task - clam TaskScan: 'スキャン'
Clamscan: "{{ .name }} をスキャン"
TaskScan: "スキャン"
#task - ai
OllamaModelPull: 'Ollama モデル {{ .name }} をプルします' OllamaModelPull: 'Ollama モデル {{ .name }} をプルします'
OllamaModelSize: "Ollama モデル {{ .name }} のサイズを取得します" OllamaModelSize: 'Ollama モデル {{ .name }} のサイズを取得します'
#task - snapshot
Snapshot: 'スナップショット' Snapshot: 'スナップショット'
SnapDBInfo: '1Panel データベース情報を書き込む' SnapDBInfo: '1Panel データベース情報を書き込む'
SnapCopy: 'ファイルとディレクトリ {{ .name }} をコピーします' SnapCopy: 'ファイルとディレクトリ {{ .name }} をコピーします'
@@ -441,7 +400,6 @@ SnapCompressSize: 'スナップショット ファイル サイズ {{ .name }}'
SnapUpload: 'スナップショット ファイルをアップロード' SnapUpload: 'スナップショット ファイルをアップロード'
SnapUploadTo: 'スナップショット ファイルを {{ .name }} にアップロードします' SnapUploadTo: 'スナップショット ファイルを {{ .name }} にアップロードします'
SnapUploadRes: 'スナップショット ファイルを {{ .name }} にアップロードします' SnapUploadRes: 'スナップショット ファイルを {{ .name }} にアップロードします'
SnapshotRecover: 'スナップショットの復元' SnapshotRecover: 'スナップショットの復元'
RecoverDownload: 'スナップショット ファイルをダウンロード' RecoverDownload: 'スナップショット ファイルをダウンロード'
Download: 'ダウンロード' Download: 'ダウンロード'
@@ -449,10 +407,10 @@ RecoverDownloadAccount: 'スナップショット ダウンロード バック
RecoverDecompress: 'スナップショット圧縮ファイルを解凍する' RecoverDecompress: 'スナップショット圧縮ファイルを解凍する'
Decompress: '減圧' Decompress: '減圧'
BackupBeforeRecover: 'スナップショットの前にシステム関連データをバックアップする' BackupBeforeRecover: 'スナップショットの前にシステム関連データをバックアップする'
Readjson: 'スナップショット内の Json ファイルを読み取ります' ReadJson: 'スナップショット内の Json ファイルを読み取ります'
ReadjsonPath: 'スナップショット内の Json ファイル パスを取得します' ReadJsonPath: 'スナップショット内の Json ファイル パスを取得します'
ReadjsonContent: 'Json ファイルを読み取ります' ReadJsonContent: 'Json ファイルを読み取ります'
ReadjsonMarshal: 'Json エスケープ処理' ReadJsonMarshal: 'Json エスケープ処理'
RecoverApp: 'インストールされたアプリを復元する' RecoverApp: 'インストールされたアプリを復元する'
RecoverWebsite: 'ウェブサイトディレクトリを回復する' RecoverWebsite: 'ウェブサイトディレクトリを回復する'
RecoverAppImage: 'スナップショットイメージのバックアップを復元する' RecoverAppImage: 'スナップショットイメージのバックアップを復元する'
@@ -466,9 +424,6 @@ RecoverDaemonJson: 'コンテナ構成 daemon.json ファイルを復元する'
RecoverDBData: 'データベース データを回復する' RecoverDBData: 'データベース データを回復する'
RecoverBackups: 'ローカル バックアップ ディレクトリを復元する' RecoverBackups: 'ローカル バックアップ ディレクトリを復元する'
RecoverPanelData: 'リカバリデータディレクトリ' RecoverPanelData: 'リカバリデータディレクトリ'
#task - container
ContainerNewCliet: 'Docker クライアントを初期化する'
ContainerImagePull: 'コンテナ イメージ {{ .name }} をプルします' ContainerImagePull: 'コンテナ イメージ {{ .name }} をプルします'
ContainerRemoveOld: '元のコンテナ {{ .name }} を削除します' ContainerRemoveOld: '元のコンテナ {{ .name }} を削除します'
ContainerImageCheck: 'イメージが正常にプルされているかどうかを確認します' ContainerImageCheck: 'イメージが正常にプルされているかどうかを確認します'
@@ -477,22 +432,13 @@ ContainerRecreate: 'コンテナの更新に失敗しました。元のコンテ
ContainerCreate: '新しいコンテナ {{ .name }} を作成します' ContainerCreate: '新しいコンテナ {{ .name }} を作成します'
ContainerCreateFailed: 'コンテナの作成に失敗しました。失敗したコンテナを削除してください' ContainerCreateFailed: 'コンテナの作成に失敗しました。失敗したコンテナを削除してください'
ContainerStartCheck: 'コンテナが起動されているかどうかを確認します' ContainerStartCheck: 'コンテナが起動されているかどうかを確認します'
#task - image
ImageBuild: 'イメージビルド' ImageBuild: 'イメージビルド'
ImageBuildStdoutCheck: '画像出力コンテンツを解析する'
ImageBuildRes: 'イメージビルド出力: {{ .name }}'
ImagePull: '画像をプル' ImagePull: '画像をプル'
ImageRepoAuthFromDB: 'データベースからリポジトリ認証情報を取得する' ImageRepoAuthFromDB: 'データベースからリポジトリ認証情報を取得する'
ImaegPullRes: "画像プル出力: {{ .name }}"
ImagePush: '画像をプッシュ' ImagePush: '画像をプッシュ'
ImageRenameTag: '画像タグを変更する' ImageRenameTag: '画像タグを変更する'
ImageNewTag: '新しい画像タグ {{ .name }}' ImageNewTag: '新しい画像タグ {{ .name }}'
ImaegPushRes: '画像プッシュ出力: {{ .name }}'
ComposeCreate: 'コンポジションを作成する' ComposeCreate: 'コンポジションを作成する'
ComposeCreateRes: "Compose 作成出力: {{ .name }}"
#task - website
BackupNginxConfig: 'ウェブサイトの OpenResty 構成ファイルをバックアップする' BackupNginxConfig: 'ウェブサイトの OpenResty 構成ファイルをバックアップする'
CompressFileSuccess: 'ディレクトリを正常に圧縮しました。{{ .name }} に圧縮されました' CompressFileSuccess: 'ディレクトリを正常に圧縮しました。{{ .name }} に圧縮されました'
CompressDir: '圧縮ディレクトリ' CompressDir: '圧縮ディレクトリ'
@@ -503,40 +449,27 @@ websiteDir: 'ウェブサイトディレクトリ'
RecoverFailedStartRollBack: 'リカバリに失敗しました。ロールバックを開始します' RecoverFailedStartRollBack: 'リカバリに失敗しました。ロールバックを開始します'
AppBackupFileIncomplete: 'バックアップ ファイルが不完全で、app.json または app.tar.gz ファイルが不足しています' AppBackupFileIncomplete: 'バックアップ ファイルが不完全で、app.json または app.tar.gz ファイルが不足しています'
AppAttributesNotMatch: 'アプリケーションの種類または名前が一致しません' AppAttributesNotMatch: 'アプリケーションの種類または名前が一致しません'
#alert
ErrAlert: '警告メッセージの形式が正しくありません。確認してもう一度お試しください。'
ErrAlertPush: 'アラート情報のプッシュ中にエラーが発生しました。確認してもう一度お試しください。'
ErrAlertSave: 'アラーム情報の保存中にエラーが発生しました。確認してもう一度お試しください。'
ErrAlertSync: 'アラーム情報の同期エラーです。確認してもう一度お試しください。' ErrAlertSync: 'アラーム情報の同期エラーです。確認してもう一度お試しください。'
ErrAlertRemote: 'アラーム メッセージのリモート エラーです。確認してもう一度お試しください。' ErrInstallExtension: 'インストールタスクが進行中です、タスクが終了するのを待ってください'
PanelAlertTitle: 'パネルアラート通知'
#task - runtime TestAlertTitle: 'テストメール - メール接続の確認'
ErrInstallExtension: "インストールタスクが進行中です、タスクが終了するのを待ってください" TestAlert: 'これはテストメールです。メール送信設定が正しく構成されているかを確認します。'
LicenseExpirationAlert: 'あなたの {{ .node }}{{ .ip }} パネル、ライセンスは {{ .day }} 日後に期限切れになります。詳細はパネルにログインして'
# alert mail template CronJobFailedAlert: 'あなたの {{ .node }}{{ .ip }} パネル、スケジュールタスク {{ .name }} の実行に失敗しました。詳細はパネルにログインして'
PanelAlertTitle: "パネルアラート通知" ClamAlert: 'あなたの {{ .node }}{{ .ip }} パネル、ウイルススキャンタスクで {{ .num }} 個の感染ファイルを検出しました。詳細はパネルにログインして'
TestAlertTitle: "テストメール - メール接続の確認" WebSiteAlert: 'あなたの {{ .node }}{{ .ip }} パネル、{{ .num }} 個のウェブサイトが {{ .day }} 日後に期限切れになります。詳細はパネルにログインして'
TestAlert: "これはテストメールです。メール送信設定が正しく構成されているかを確認します。" SSLAlert: 'あなたの {{ .node }}{{ .ip }} パネル、{{ .num }} 枚のSSL証明書が {{ .day }} 日後に期限切れになります。詳細はパネルにログインして'
LicenseExpirationAlert: "あなたの {{ .node }}{{ .ip }} パネル、ライセンスは {{ .day }} 日後に期限切れになります。詳細はパネルにログインしてご確認ください。" DiskUsedAlert: 'あなたの {{ .node }}{{ .ip }} パネル、ディスク {{ .name }} の使用率が {{ .used }} に達しました。詳細はパネルにログインして'
CronJobFailedAlert: "あなたの {{ .node }}{{ .ip }} パネル、スケジュールタスク {{ .name }} の実行に失敗しました。詳細はパネルにログインしてご確認ください。" ResourceAlert: 'あなたの {{ .node }}{{ .ip }} パネル、過去 {{ .time }} 分間の {{ .name }} 平均使用率は {{ .used }} です。詳細はパネルにログインして'
ClamAlert: "あなたの {{ .node }}{{ .ip }} パネル、ウイルススキャンタスクで {{ .num }} 個の感染ファイルを検出しました。詳細はパネルにログインしてご確認ください。" PanelVersionAlert: 'あなたの {{ .node }}{{ .ip }} パネル、最新バージョンがアップグレード可能です。詳細はパネルにログインして'
WebSiteAlert: "あなたの {{ .node }}{{ .ip }} パネル、{{ .num }} 個のウェブサイトが {{ .day }} 日後に期限切れになります。詳細はパネルにログインしてご確認ください。" PanelPwdExpirationAlert: 'あなたの {{ .node }}{{ .ip }} パネル、パネルパスワードは {{ .day }} 日後に期限切れになります。詳細はパネルにログインして'
SSLAlert: "あなたの {{ .node }}{{ .ip }} パネル、{{ .num }} 枚のSSL証明書が {{ .day }} 日後に期限切れになります。詳細はパネルにログインしてご確認ください。" CommonAlert: 'あなたの {{ .node }}{{ .ip }} パネル、{{ .msg }}。詳細はパネルにログインして'
DiskUsedAlert: "あなたの {{ .node }}{{ .ip }} パネル、ディスク {{ .name }} の使用率が {{ .used }} に達しました。詳細はパネルにログインしてご確認ください。" NodeExceptionAlert: 'あなたの {{ .node }}{{ .ip }} パネル、{{ .num }} 個のノードに異常が発生しています。詳細はパネルにログインして'
ResourceAlert: "あなたの {{ .node }}{{ .ip }} パネル、過去 {{ .time }} 分間の {{ .name }} 平均使用率は {{ .used }} です。詳細はパネルにログインしてご確認ください。" LicenseExceptionAlert: 'あなたの {{ .node }}{{ .ip }} パネル、{{ .num }} 個のライセンスに異常が発生しています。詳細はパネルにログインして'
PanelVersionAlert: "あなたの {{ .node }}{{ .ip }} パネル、最新バージョンがアップグレード可能です。詳細はパネルにログインしてご確認ください。" SSHAndPanelLoginAlert: 'あなたの {{ .node }}{{ .ip }} パネル、{{ .loginIp }} からの {{ .name }} ログインに異常があります。詳細はパネルにログインして'
PanelPwdExpirationAlert: "あなたの {{ .node }}{{ .ip }} パネル、パネルパスワードは {{ .day }} 日後に期限切れになります。詳細はパネルにログインしてご確認ください。" DeviceNotFound: 'デバイス {{ .name }} が見つかりません'
CommonAlert: "あなたの {{ .node }}{{ .ip }} パネル、{{ .msg }}。詳細はパネルにログインしてご確認ください。" DeviceIsMounted: 'デバイス {{ .name }} はマウントされています、まずアンマウントしてください'
NodeExceptionAlert: "あなたの {{ .node }}{{ .ip }} パネル、{{ .num }} 個のノードに異常が発生しています。詳細はパネルにログインしてご確認ください。" PartitionDiskErr: 'パーティションに失敗しました、{{ .err }}'
LicenseExceptionAlert: "あなたの {{ .node }}{{ .ip }} パネル、{{ .num }} 個のライセンスに異常が発生しています。詳細はパネルにログインしてご確認ください。" FormatDiskErr: 'ディスクのフォーマットに失敗しました、{{ .err }}'
SSHAndPanelLoginAlert: "あなたの {{ .node }}{{ .ip }} パネル、{{ .loginIp }} からの {{ .name }} ログインに異常があります。詳細はパネルにログインしてご確認ください。" MountDiskErr: 'ディスクのマウントに失敗しました、{{ .err }}'
XfsNotFound: 'xfs ファイルシステムが検出されませんでした、最初に xfsprogs をインストールしてください'
#disk
DeviceNotFound: "デバイス {{ .name }} が見つかりません"
DeviceIsMounted: "デバイス {{ .name }} はマウントされています、まずアンマウントしてください"
PartitionDiskErr: "パーティションに失敗しました、{{ .err }}"
FormatDiskErr: "ディスクのフォーマットに失敗しました、{{ .err }}"
MountDiskErr: "ディスクのマウントに失敗しました、{{ .err }}"
UnMountDiskErr: "ディスクのアンマウントに失敗しました、{{ .err }}"
XfsNotFound: "xfs ファイルシステムが検出されませんでした、最初に xfsprogs をインストールしてください"
+171 -239
View File
@@ -1,31 +1,28 @@
ErrInvalidParams: '요청 매개변수 오류: {{ .detail }}' ErrInvalidParams: '잘못된 요청: {{ .detail }}'
ErrTokenParse: '토큰 생성 오류: {{ .detail }}' ErrTokenParse: '토큰 오류: {{ .detail }}'
ErrInitialPassword: '원래 비밀번호가 올바르지 않습니다' ErrInitialPassword: '원래 비밀번호가 틀립니다'
ErrInternalServer: '내부 서버 오류: {{ .detail }}' ErrInternalServer: '서버 오류: {{ .detail }}'
ErrRecordExist: '레코드가 이미 존재합니다' ErrRecordExist: '레코드가 이미 있습니다'
ErrRecordNotFound: '레코드를 찾을 수 없습니다' ErrRecordNotFound: '레코드를 찾을 수 없습니다'
ErrStructTransform: '유형 변환에 실패했습니다: {{ .err }}' ErrStructTransform: '형 변환 실패: {{ .err }}'
ErrNotLogin: '사용자가 로그인하지 않았습니다: {{ .detail }}' ErrNotLogin: '로그인하지 않음: {{ .detail }}'
ErrPasswordExpired: '현재 비밀번호가 만료되었습니다: {{ .detail }}' ErrPasswordExpired: '비밀번호 만료: {{ .detail }}'
ErrNotSupportType: '시스템은 현재 유형 {{ .name }}을 지원하지 않습니다.' ErrNotSupportType: '지원하지 않는 타입: {{ .name }}'
ErrProxy: '요청 오류, 노드 상태를 확인하세요: {{ .detail }}' ErrProxy: '요청 실패: {{ .detail }}'
ErrApiConfigStatusInvalid: 'API 인터페이스에 대한 액세스가 금지되었습니다: {{ .detail }}' ErrApiConfigStatusInvalid: 'API 사용 중지: {{ .detail }}'
ErrApiConfigKeyInvalid: 'API 인터페이스 키 오류: {{ .detail }}' ErrApiConfigKeyInvalid: 'API 키가 잘못됨: {{ .detail }}'
ErrApiConfigIPInvalid: 'API 인터페이스를 호출하는 데 사용된 IP가 허용 목록에 없습니다: {{ .detail }}' ErrApiConfigIPInvalid: 'IP 허용되지 않음: {{ .detail }}'
ErrApiConfigDisable: '이 인터페이스는 API 인터페이스 호출 사용을 금지합니다: {{ .detail }}' ErrApiConfigDisable: 'API 접근 금지: {{ .detail }}'
ErrApiConfigKeyTimeInvalid: 'API 인터페이스 타임스탬프 오류: {{ .detail }}' ErrApiConfigKeyTimeInvalid: '타임스탬프 오류: {{ .detail }}'
ErrShutDown: "명령이 수동으로 종료되었습니다!" ErrShutDown: '명령이 수동으로 중단되었습니다'
ErrMinQuickJump: '퀵 액세스를 하나 이상 추가하세요'
ErrMinQuickJump: "최소 하나의 빠른 점프 항목을 설정해 주세요!" ErrMaxQuickJump: '퀵 액세스는 최대 4개'
ErrMaxQuickJump: "최대 네 개의 빠른 점프 항목을 설정할 수 있습니다!" ErrUsernameIsExist: '아이디가 이미 존재합니다'
#흔한
ErrUsernameIsExist: '사용자 이름이 이미 존재합니다'
ErrNameIsExist: '이름이 이미 존재합니다' ErrNameIsExist: '이름이 이미 존재합니다'
ErrDemoEnvironment: '데모 서버, 이 작업은 금지되어 있습니다!' ErrDemoEnvironment: '데모 환경에서는 불가'
ErrCmdTimeout: '명령 실행 시간이 초과되었습니다!' ErrCmdTimeout: '명령이 시간 초과했습니다'
ErrCmdIllegal: '실행 명령에 잘못된 문자가 있습니다. 수정하여 다시 시도하세요!' ErrCmdIllegal: '명령어에 허용되지 않은 문자가 포함됨'
ErrPortExist: '{{ .port }} 포트는 이미 {{ .type }} [{{ .name }}]에 의해 사용되고 있습니다.' ErrPortExist: '포트 {{ .port }}는 {{ .type }} [{{ .name }}]에서 사용 중입니다'
TYPE_APP: '응용 프로그램' TYPE_APP: '응용 프로그램'
TYPE_RUNTIME: '런타임 환경' TYPE_RUNTIME: '런타임 환경'
TYPE_DOMAIN: '도메인 이름' TYPE_DOMAIN: '도메인 이름'
@@ -36,45 +33,39 @@ Failed: '실패했습니다'
SystemRestart: '시스템 재시작으로 인해 작업이 중단되었습니다' SystemRestart: '시스템 재시작으로 인해 작업이 중단되었습니다'
ErrGroupIsDefault: '기본 그룹, 삭제할 수 없습니다' ErrGroupIsDefault: '기본 그룹, 삭제할 수 없습니다'
ErrGroupIsInWebsiteUse: '그룹이 다른 웹사이트에서 사용 중이므로 삭제할 수 없습니다.' ErrGroupIsInWebsiteUse: '그룹이 다른 웹사이트에서 사용 중이므로 삭제할 수 없습니다.'
Decrypt: "복호화" Decrypt: '복호화'
ErrAgentAccountBound: '계정이 에이전트에 묶여 있습니다'
#agent ErrAgentAccountUnavailable: '계정 연결 불가: {{ .err }}'
ErrAgentAccountBound: '이 계정은 에이전트에 바인딩되어 있어 삭제할 수 없습니다. 확인 후 다시 시도하세요!' ErrAgentProviderNotSupported: '지원되지 않는 에이전트 공급자'
ErrAgentAccountUnavailable: '계정 연결 정보를 사용할 수 없습니다. 오류: {{ .err }}. 확인 후 다시 시도하세요!' ErrAgentAccountRequired: '먼저 에이전트 계정을 선택하세요'
ErrAgentProviderNotSupported: '이 에이전트 제공자는 지원되지 않습니다. 확인 후 다시 시도하세요!' ErrAgentAccountNotVerified: '에이전트 계정 미확인'
ErrAgentAccountRequired: '에이전트 계정을 선택한 후 다시 시도하세요.' ErrAgentProviderMismatch: '에이전트 공급자 불일치'
ErrAgentAccountNotVerified: '계정이 검증되지 않았습니다. 확인 후 다시 시도하세요!' ErrAgentBaseURLRequired: '기본 URL 필요'
ErrAgentProviderMismatch: '계정 제공자가 일치하지 않습니다. 확인 후 다시 시도하세요!' ErrAgentApiKeyRequired: 'API 키 필요'
ErrAgentBaseURLRequired: 'Base URL은 비워 둘 수 없습니다. 확인 후 다시 시도하세요!' ErrAgentComposeRequired: 'Compose 내용 필요'
ErrAgentApiKeyRequired: 'API Key는 비워 둘 수 없습니다. 확인 후 다시 시도하세요!' ErrAgentIDRequired: '에이전트 ID 필요'
ErrAgentComposeRequired: '사용자 정의 compose 내용은 비워 둘 수 없습니다. 확인 후 다시 시도하세요!' ErrAgentAccountIDRequired: '계정 ID 필요'
ErrAgentIDRequired: '에이전트 ID는 비워 둘 수 없습니다. 확인 후 다시 시도하세요!'
ErrAgentAccountIDRequired: '계정 ID는 비워 둘 수 없습니다. 확인 후 다시 시도하세요!'
#지원
Localhost: '로컬 머신' Localhost: '로컬 머신'
ErrBackupInUsed: '백업 계정이 예약된 작업에 사용되었으므로 삭제할 수 없습니다.' ErrBackupInUsed: '백업 계정이 예약에 사용 중'
ErrBackupCheck: '백업 계정 테스트 연결에 실패했습니다 {{ .err }}' ErrBackupCheck: '연결 테스트 실패: {{ .err }}'
ErrBackupLocalDelete: '로컬 서버 백업 계정 삭제는 아직 지원되지 않습니다.' ErrBackupLocalDelete: '로컬 백업은 삭제할 수 없습니다'
ErrBackupLocalCreate: '로컬 서버 백업 계정 생성은 아직 지원되지 않습니다.' ErrBackupLocalCreate: '로컬 백업은 만들 수 없습니다'
ErrPortInUsed: '{{ .detail }} 포트가 이미 사용 중입니다'
#앱
ErrPortInUsed: '{{ .detail }} 포트가 이미 사용 중입니다!'
ErrAppLimit: '설치된 애플리케이션 수가 한도를 초과했습니다' ErrAppLimit: '설치된 애플리케이션 수가 한도를 초과했습니다'
ErrNotInstall: '응용 프로그램이 설치되지 않았습니다' ErrNotInstall: '응용 프로그램이 설치되지 않았습니다'
ErrPortInOtherApp: '{{ .port }} 포트는 이미 {{ .apps }} 애플리케이션에 의해 사용되고 있습니다!' ErrPortInOtherApp: '{{ .port }} 포트는 이미 {{ .apps }} 애플리케이션에 의해 사용되고 있습니다'
ErrDbUserNotValid: '기존 데이터베이스, 사용자 이름 및 비밀번호가 일치하지 않습니다!' ErrDbUserNotValid: '기존 데이터베이스, 사용자 이름 및 비밀번호가 일치하지 않습니다'
ErrUpdateBuWebsite: '응용 프로그램이 성공적으로 업데이트되었지만, 웹사이트 구성 파일 수정에 실패했습니다. 구성을 확인하세요! ' ErrUpdateBuWebsite: '응용 프로그램이 성공적으로 업데이트되었지만, 웹사이트 구성 파일 수정에 실패했습니다. 구성을 확인하세요'
Err1PanelNetworkFailed: '기본 컨테이너 네트워크 생성에 실패했습니다! {{ .세부 사항 }}' Err1PanelNetworkFailed: '기본 컨테이너 네트워크 생성에 실패했습니다 {{ .세부 사항 }}'
ErrFileParse: '응용 프로그램 docker-compose 파일 구문 분석에 실패했습니다!' ErrFileParse: '응용 프로그램 docker-compose 파일 구문 분석에 실패했습니다'
ErrInstallDirNotFound: '설치 디렉토리가 존재하지 않습니다. 제거를 원하실 경우 강제 제거 를 선택해주세요.' ErrInstallDirNotFound: '설치 디렉토리가 존재하지 않습니다. 제거를 원하실 경우 강제 제거 를 선택해주세요.'
AppStoreIsUpToDate: '앱 스토어가 이미 최신 버전입니다' AppStoreIsUpToDate: '앱 스토어가 이미 최신 버전입니다'
LocalAppVersionNull: '{{ .name }} 애플리케이션이 버전과 동기화되지 않았습니다! 앱 목록에 추가할 수 없습니다.' LocalAppVersionNull: '{{ .name }} 애플리케이션이 버전과 동기화되지 않았습니다 앱 목록에 추가할 수 없습니다.'
LocalAppVersionErr: '{{ .name }} 동기화 버전 {{ .version }}이 실패했습니다! {{ .err }}' LocalAppVersionErr: '{{ .name }} 동기화 버전 {{ .version }}이 실패했습니다 {{ .err }}'
ErrFileNotFound: '{{ .name }} 파일이 존재하지 않습니다' ErrFileNotFound: '{{ .name }} 파일이 존재하지 않습니다'
ErrFileParseApp: '{{ .name }} 파일 구문 분석에 실패했습니다 {{ .err }}' ErrFileParseApp: '{{ .name }} 파일 구문 분석에 실패했습니다 {{ .err }}'
ErrAppDirNull: '버전 폴더가 존재하지 않습니다' ErrAppDirNull: '버전 폴더가 존재하지 않습니다'
LocalAppErr: '애플리케이션 {{ .name }} 동기화에 실패했습니다! {{ .err }}' LocalAppErr: '애플리케이션 {{ .name }} 동기화에 실패했습니다 {{ .err }}'
ErrContainerName: '컨테이너 이름이 이미 존재합니다' ErrContainerName: '컨테이너 이름이 이미 존재합니다'
ErrCreateHttpClient: '요청 {{ .err }}을(를) 생성하지 못했습니다.' ErrCreateHttpClient: '요청 {{ .err }}을(를) 생성하지 못했습니다.'
ErrHttpReqTimeOut: '요청 시간이 초과되었습니다 {{ .err }}' ErrHttpReqTimeOut: '요청 시간이 초과되었습니다 {{ .err }}'
@@ -87,64 +78,58 @@ ErrAppBackup: '{{ .name }} 애플리케이션 백업에 실패했습니다 {{ .e
ErrVersionTooLow: '현재 1Panel 버전이 너무 낮아 App Store를 업데이트할 수 없습니다. 작동하시기 전에 버전을 업그레이드하세요.' ErrVersionTooLow: '현재 1Panel 버전이 너무 낮아 App Store를 업데이트할 수 없습니다. 작동하시기 전에 버전을 업그레이드하세요.'
ErrAppNameExist: '응용 프로그램 이름이 이미 존재합니다' ErrAppNameExist: '응용 프로그램 이름이 이미 존재합니다'
AppStoreIsSyncing: 'App Store가 동기화 중입니다. 나중에 다시 시도하세요.' AppStoreIsSyncing: 'App Store가 동기화 중입니다. 나중에 다시 시도하세요.'
ErrGetCompose: 'docker-compose.yml 파일을 가져오지 못했습니다! {{ .detail }}' ErrGetCompose: 'docker-compose.yml 파일을 가져오지 못했습니다 {{ .detail }}'
ErrAppWarn: '비정상적인 상태입니다. 로그를 확인해 주세요.' ErrAppWarn: '비정상적인 상태입니다. 로그를 확인해 주세요.'
ErrAppParamKey: '매개변수 {{ .name }} 필드가 비정상입니다.' ErrAppParamKey: '매개변수 {{ .name }} 필드가 비정상입니다.'
ErrAppUpgrade: '애플리케이션 {{ .name }} 업그레이드에 실패했습니다 {{ .err }}' ErrAppUpgrade: '애플리케이션 {{ .name }} 업그레이드에 실패했습니다 {{ .err }}'
AppRecover: '롤백 애플리케이션 {{ .name }}' AppRecover: '롤백 애플리케이션 {{ .name }}'
PullImageStart: '이미지 [{{ .name }}] 가져오기 시작' PullImageStart: '이미지 [{{ .name }}] 가져오기 시작'
PullImageSuccess: '이미지 가져오기 성공' PullImageSuccess: '이미지 가져오기 성공'
AppStoreIsLastVersion: '앱스토어가 이미 최신 버전입니다'
AppStoreSyncSuccess: '앱스토어 동기화 성공' AppStoreSyncSuccess: '앱스토어 동기화 성공'
SyncAppDetail: '애플리케이션 구성 동기화' SyncAppDetail: '애플리케이션 구성 동기화'
AppVersionNotMatch: '{{ .name }} 애플리케이션에 더 높은 1Panel 버전이 필요하므로 동기화를 건너뜁니다.' AppVersionNotMatch: '{{ .name }} 애플리케이션에 더 높은 1Panel 버전이 필요하므로 동기화를 건너뜁니다.'
MoveSiteDir: "웹사이트 디렉토리 변경이 감지되었습니다. OpenResty 웹사이트 디렉토리를 {{ .name }} 로 마이그레이션해야 합니다" MoveSiteDir: '웹사이트 디렉토리 변경이 감지되었습니다. OpenResty 웹사이트 디렉토리를 {{ .name }} 로 마이그레이션해야 합니다'
MoveSiteDirSuccess: '웹사이트 디렉토리 마이그레이션 성공' MoveSiteDirSuccess: '웹사이트 디렉토리 마이그레이션 성공'
DeleteRuntimePHP: 'PHP 런타임 삭제' DeleteRuntimePHP: 'PHP 런타임 삭제'
CustomAppStoreFileValid: '앱 스토어 패키지는 .tar.gz 형식이어야 합니다.' CustomAppStoreFileValid: '앱 스토어 패키지는.tar.gz 형식이어야 합니다.'
PullImageTimeout: '이미지 가져오기 시간 초과, 이미지 가속을 높이거나 다른 이미지 가속으로 변경해 보세요.' PullImageTimeout: '이미지 가져오기 시간 초과, 이미지 가속을 높이거나 다른 이미지 가속으로 변경해 보세요.'
ErrAppIsDown: '{{ .name }} 애플리케이션 상태가 비정상적입니다. 확인해 주세요' ErrAppIsDown: '{{ .name }} 애플리케이션 상태가 비정상적입니다. 확인해 주세요'
ErrCustomApps: '설치된 애플리케이션이 있습니다. 먼저 제거해 주세요' ErrCustomApps: '설치된 애플리케이션이 있습니다. 먼저 제거해 주세요'
ErrCustomRuntimes: '설치된 런타임 환경이 있습니다. 먼저 삭제해 주세요' ErrCustomRuntimes: '설치된 런타임 환경이 있습니다. 먼저 삭제해 주세요'
ErrAppVersionDeprecated: "{{ .name }} 응용 프로그램은 현재 1Panel 버전과 호환되지 않아 건너뛰었습니다" ErrAppVersionDeprecated: '{{ .name }} 응용 프로그램은 현재 1Panel 버전과 호환되지 않아 건너뛰었습니다'
ErrDockerFailed: "Docker의 상태가 비정상입니다. 서비스 상태를 확인하세요" ErrDockerFailed: 'Docker의 상태가 비정상입니다. 서비스 상태를 확인하세요'
ErrDockerComposeCmdNotFound: "Docker Compose 명령이 없습니다. 호스트 머신에 먼저 이 명령을 설치하세요" ErrDockerComposeCmdNotFound: 'Docker Compose 명령이 없습니다. 호스트 머신에 먼저 이 명령을 설치하세요'
UseExistImage: '이미지 가져오기 실패, 기존 이미지 사용' UseExistImage: '이미지가 이미 존재하여 기존 이미지를 사용합니다'
ErrDatabaseNotFound: '데이터베이스 {{ .name }} 이(가) 존재하지 않습니다'
#ssh ExportIP: '로그인 IP'
ExportIP: "로그인 IP" ExportArea: '위치'
ExportArea: "위치" ExportPort: '포트'
ExportPort: "포트" ExportAuthMode: '로그인 방식'
ExportAuthMode: "로그인 방식" ExportUser: '사용자'
ExportUser: "사용자" ExportStatus: '로그인 상태'
ExportStatus: "로그인 상태" ExportDate: '시간'
ExportDate: "시간"
#파일
ErrFileCanNotRead: '이 파일은 미리보기를 지원하지 않습니다' ErrFileCanNotRead: '이 파일은 미리보기를 지원하지 않습니다'
ErrFileToLarge: '파일이 10M보다 커서 열 수 없습니다' ErrFileToLarge: '파일이 10M보다 커서 열 수 없습니다'
ErrPathNotFound: '디렉토리가 존재하지 않습니다' ErrPathNotFound: '디렉토리가 존재하지 않습니다'
ErrMovePathFailed: '대상 경로에는 원래 경로가 포함될 수 없습니다!' ErrMovePathFailed: '대상 경로에는 원래 경로가 포함될 수 없습니다'
ErrLinkPathNotFound: '대상 경로가 존재하지 않습니다!' ErrLinkPathNotFound: '대상 경로가 존재하지 않습니다'
ErrFileIsExist: '파일이나 폴더가 이미 존재합니다!' ErrFileIsExist: '파일이나 폴더가 이미 존재합니다'
ErrFileUpload: '{{ .name }}이 파일 {{ .detail }}을 업로드하지 못했습니다.' ErrFileUpload: '{{ .name }}이 파일 {{ .detail }}을 업로드하지 못했습니다.'
ErrFileDownloadDir: '다운로드 폴더가 지원되지 않습니다' ErrFileDownloadDir: '다운로드 폴더가 지원되지 않습니다'
ErrCmdNotFound: '{{ .name}} 명령이 존재하지 않습니다. 먼저 호스트에 이 명령을 설치하세요' ErrCmdNotFound: '{{ .name }} 명령이 존재하지 않습니다. 먼저 호스트에 이 명령을 설치하세요'
ErrSourcePathNotFound: '소스 디렉토리가 존재하지 않습니다' ErrSourcePathNotFound: '소스 디렉토리가 존재하지 않습니다'
ErrFavoriteExist: '이 경로는 이미 즐겨찾기되었습니다' ErrFavoriteExist: '이 경로는 이미 즐겨찾기되었습니다'
ErrInvalidChar: '불법 문자는 허용되지 않습니다' ErrInvalidChar: '불법 문자는 허용되지 않습니다'
ErrPathNotDelete: '선택한 디렉토리를 삭제할 수 없습니다' ErrPathNotDelete: '선택한 디렉토리를 삭제할 수 없습니다'
ErrLogFileToLarge: "로그 파일이 500MB를 초과하여 열 수 없습니다" ErrLogFileToLarge: '로그 파일이 500MB를 초과하여 열 수 없습니다'
FileDropFailed: "파일 {{ .name }} 정리 실패: {{ .err }}" FileDropFailed: '파일 {{ .name }} 정리 실패: {{ .err }}'
FileDropSuccess: "파일 {{ .name }} 정리 성공, {{ .count }}개 파일 삭제, {{ .size }} 디스크 공간 확보" FileDropSuccess: '파일 {{ .name }} 정리 성공, {{ .count }}개 파일 삭제, {{ .size }} 디스크 공간 확보'
FileDropSum: "파일 정리 완료, 총 {{ .count }}개 파일 삭제, 총 {{ .size }} 디스크 공간 확보" FileDropSum: '파일 정리 완료, 총 {{ .count }}개 파일 삭제, 총 {{ .size }} 디스크 공간 확보'
ErrBadDecrypt: "압축 패키지 암호 해제 비밀번호 오류, 압축 해제 실패, 확인 후 다시 시도하세요!" ErrBadDecrypt: '압축 패키지 암호 해제 비밀번호 오류, 압축 해제 실패, 확인 후 다시 시도하세요'
#웹사이트
ErrAliasIsExist: '별칭이 이미 존재합니다' ErrAliasIsExist: '별칭이 이미 존재합니다'
ErrBackupMatch: '백업 파일이 현재 웹사이트 데이터 중 일부 {{ .detail }}와 일치하지 않습니다.' ErrBackupMatch: '백업 파일이 현재 웹사이트 데이터 중 일부 {{ .detail }}와 일치하지 않습니다.'
ErrBackupExist: '백업 파일에 있는 소스 데이터의 해당 부분이 존재하지 않습니다 {{ .detail }}' ErrBackupExist: '백업 파일에 있는 소스 데이터의 해당 부분이 존재하지 않습니다 {{ .detail }}'
ErrPHPResource: '로컬 운영 환경이 전환을 지원하지 않습니다! ' ErrPHPResource: '로컬 운영 환경이 전환을 지원하지 않습니다'
ErrPathPermission: '인덱스 디렉토리에서 1000:1000이 아닌 권한을 가진 폴더가 감지되었습니다. 이로 인해 웹사이트에서 액세스 거부 오류가 발생할 수 있습니다. 위의 저장 버튼을 클릭해주세요.' ErrPathPermission: '인덱스 디렉토리에서 1000:1000이 아닌 권한을 가진 폴더가 감지되었습니다. 이로 인해 웹사이트에서 액세스 거부 오류가 발생할 수 있습니다. 위의 저장 버튼을 클릭해주세요.'
ErrDomainIsUsed: '[{{ .name }}] 웹사이트에서 이미 도메인 이름을 사용하고 있습니다.' ErrDomainIsUsed: '[{{ .name }}] 웹사이트에서 이미 도메인 이름을 사용하고 있습니다.'
ErrDomainFormat: '{{ .name }} 도메인 이름 형식이 올바르지 않습니다' ErrDomainFormat: '{{ .name }} 도메인 이름 형식이 올바르지 않습니다'
@@ -152,11 +137,11 @@ ErrDefaultAlias: '기본값은 예약된 코드입니다. 다른 코드를 사
ErrParentWebsite: '먼저 하위 사이트 {{ .name }}을 삭제해야 합니다.' ErrParentWebsite: '먼저 하위 사이트 {{ .name }}을 삭제해야 합니다.'
ErrBuildDirNotFound: '빌드 디렉토리가 존재하지 않습니다' ErrBuildDirNotFound: '빌드 디렉토리가 존재하지 않습니다'
ErrImageNotExist: '운영 환경 {{ .name }} 이미지가 존재하지 않습니다. 운영 환경을 다시 편집하세요.' ErrImageNotExist: '운영 환경 {{ .name }} 이미지가 존재하지 않습니다. 운영 환경을 다시 편집하세요.'
ErrProxyIsUsed: "로드 밸런싱이 역방향 프록시에 의해 사용되었으므로 삭제할 수 없습니다" ErrProxyIsUsed: '로드 밸런싱이 역방향 프록시에 의해 사용되었으므로 삭제할 수 없습니다'
ErrSSLValid: '인증서 파일에 문제가 있습니다. 인증서 상태를 확인하세요!' ErrSSLValid: '인증서 파일에 문제가 있습니다. 인증서 상태를 확인하세요'
ErrWebsiteDir: "웹사이트 디렉토리 내의 디렉토리를 선택하세요." ErrWebsiteDir: '웹사이트 디렉토리 내의 디렉토리를 선택하세요.'
ErrComposerFileNotFound: "composer.json 파일이 존재하지 않습니다" ErrComposerFileNotFound: 'composer.json 파일이 존재하지 않습니다'
ErrRuntimeNoPort: "런타임 환경에 포트가 설정되지 않았습니다. 먼저 런타임 환경을 편집하세요." ErrRuntimeNoPort: '런타임 환경에 포트가 설정되지 않았습니다. 먼저 런타임 환경을 편집하세요.'
Status: '상태' Status: '상태'
start: '시작' start: '시작'
stop: '중지' stop: '중지'
@@ -166,14 +151,12 @@ pause: '일시 정지'
unpause: '재개' unpause: '재개'
remove: '삭제' remove: '삭제'
delete: '삭제' delete: '삭제'
ErrDefaultWebsite: '기본 웹사이트가 이미 설정되었습니다. 설정하기 전에 취소하세요!' ErrDefaultWebsite: '기본 웹사이트가 이미 설정되었습니다. 설정하기 전에 취소하세요'
SSL: '인증서' SSL: '인증서'
Set: '설정' Set: '설정'
#SSL인증
ErrSSLCannotDelete: '{{ .name }} 인증서는 웹사이트에서 사용 중이므로 삭제할 수 없습니다.' ErrSSLCannotDelete: '{{ .name }} 인증서는 웹사이트에서 사용 중이므로 삭제할 수 없습니다.'
ErrAccountCannotDelete: '계정이 인증서와 연결되어 있어 삭제할 수 없습니다.' ErrAccountCannotDelete: '계정이 인증서와 연결되어 있어 삭제할 수 없습니다.'
ErrSSLApply: '인증서 갱신이 성공했으나, openresty 재로드에 실패했습니다. 구성을 확인해 주세요!' ErrSSLApply: '인증서 갱신이 성공했으나, openresty 재로드에 실패했습니다. 구성을 확인해 주세요'
ErrEmailIsExist: '사서함이 이미 존재합니다' ErrEmailIsExist: '사서함이 이미 존재합니다'
ErrSSLKeyNotFound: '개인 키 파일이 존재하지 않습니다' ErrSSLKeyNotFound: '개인 키 파일이 존재하지 않습니다'
ErrSSLCertificateNotFound: '인증서 파일이 존재하지 않습니다' ErrSSLCertificateNotFound: '인증서 파일이 존재하지 않습니다'
@@ -181,12 +164,12 @@ ErrSSLKeyFormat: '개인 키 파일 검증에 실패했습니다'
ErrSSLCertificateFormat: '인증서 파일 형식이 올바르지 않습니다. pem 형식을 사용하세요.' ErrSSLCertificateFormat: '인증서 파일 형식이 올바르지 않습니다. pem 형식을 사용하세요.'
ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid 또는 EabHmacKey는 비워둘 수 없습니다' ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid 또는 EabHmacKey는 비워둘 수 없습니다'
ErrOpenrestyNotFound: 'Http 모드를 사용하려면 먼저 Openresty를 설치해야 합니다.' ErrOpenrestyNotFound: 'Http 모드를 사용하려면 먼저 Openresty를 설치해야 합니다.'
ApplySSLStart: '인증서 신청 시작, 도메인 이름 [{{ .domain }}] 신청 방법 [{{ .type }}] ' ApplySSLStart: '인증서 신청 시작, 도메인 이름 [{{ .domain }}] 신청 방법 [{{ .type }}]'
dnsAccount: 'DNS 자동' dnsAccount: 'DNS 자동'
dnsManual: 'DNS 매뉴얼' dnsManual: 'DNS 매뉴얼'
http: 'HTTP' http: 'HTTP'
ApplySSLFailed: '[{{ .domain }}] 인증서 신청이 실패했습니다. {{ .detail }} ' ApplySSLFailed: '[{{ .domain }}] 인증서 신청이 실패했습니다. {{ .detail }}'
ApplySSLSuccess: '[{{ .domain }}] 인증서 신청이 성공적으로 완료되었습니다! ! ' ApplySSLSuccess: '[{{ .domain }}] 인증서 신청이 성공적으로 완료되었습니다'
DNSAccountName: 'DNS 계정 [{{ .name }}] 공급업체 [{{ .type }}]' DNSAccountName: 'DNS 계정 [{{ .name }}] 공급업체 [{{ .type }}]'
PushDirLog: '인증서가 [{{ .path }}] {{ .status }} 디렉토리로 푸시되었습니다.' PushDirLog: '인증서가 [{{ .path }}] {{ .status }} 디렉토리로 푸시되었습니다.'
ErrDeleteCAWithSSL: '현재 조직에는 발급된 인증서가 있어 삭제할 수 없습니다.' ErrDeleteCAWithSSL: '현재 조직에는 발급된 인증서가 있어 삭제할 수 없습니다.'
@@ -201,97 +184,79 @@ ExecShellSuccess: '스크립트 실행 성공'
StartUpdateSystemSSL: '시스템 인증서 업데이트 시작' StartUpdateSystemSSL: '시스템 인증서 업데이트 시작'
UpdateSystemSSLSuccess: '시스템 인증서 업데이트가 성공적으로 완료되었습니다.' UpdateSystemSSLSuccess: '시스템 인증서 업데이트가 성공적으로 완료되었습니다.'
ErrWildcardDomain: 'HTTP 모드에서 와일드카드 도메인 이름 인증서를 신청할 수 없습니다' ErrWildcardDomain: 'HTTP 모드에서 와일드카드 도메인 이름 인증서를 신청할 수 없습니다'
ErrApplySSLCanNotDelete: "신청 중인 인증서 {{.name}}는 삭제할 수 없습니다. 나중에 다시 시도해 주세요." ErrApplySSLCanNotDelete: '신청 중인 인증서 {{ .name }}는 삭제할 수 없습니다. 나중에 재시도'
StartPushSSLToNode: "인증서를 노드로 푸시 시작" StartPushSSLToNode: '인증서를 노드로 푸시 시작'
PushSSLToNodeFailed: "노드로 인증서 푸시 실패: {{ .err }}" PushSSLToNodeFailed: '노드로 인증서 푸시 실패: {{ .err }}'
PushSSLToNodeSuccess: "노드로 인증서 푸시 성공" PushSSLToNodeSuccess: '노드로 인증서 푸시 성공'
#마이SQL
ErrUserIsExist: '현재 사용자가 이미 존재합니다. 다시 입력하세요' ErrUserIsExist: '현재 사용자가 이미 존재합니다. 다시 입력하세요'
ErrDatabaseIsExist: '현재 데이터베이스가 이미 존재합니다. 다시 입력하세요' ErrDatabaseIsExist: '현재 데이터베이스가 이미 존재합니다. 다시 입력하세요'
ErrExecTimeOut: 'SQL 실행 시간이 초과되었습니다. 데이터베이스를 확인하십시오.' ErrExecTimeOut: 'SQL 실행 시간이 초과되었습니다. 데이터베이스를 확인하십시오.'
ErrRemoteExist: '이 이름을 가진 원격 데이터베이스가 이미 존재합니다. 수정하고 다시 시도하세요' ErrRemoteExist: '이 이름을 가진 원격 데이터베이스가 이미 존재합니다. 수정하고 다시 시도하세요'
ErrLocalExist: '이름이 로컬 데이터베이스에 이미 존재합니다. 이름을 수정하고 다시 시도하세요' ErrLocalExist: '이름이 로컬 데이터베이스에 이미 존재합니다. 이름을 수정하고 다시 시도하세요'
RemoteBackup: "원격 데이터베이스를 백업하려면 먼저 이미지 {{ .name }}을(를) 사용하여 로컬 컨테이너 데이터베이스 서비스를 시작해야 합니다. 잠시만 기다려 주세요..." RemoteBackup: '원격 데이터베이스를 백업하려면 먼저 이미지 {{ .name }}을(를) 사용하여 로컬 컨테이너 데이터베이스 서비스를 시작해야 합니다. 잠시만 기다려 주세요...'
RemoteRecover: "원격 데이터베이스를 복원하려면 먼저 이미지 {{ .name }}을(를) 사용하여 로컬 컨테이너 데이터베이스 서비스를 시작해야 합니다. 잠시만 기다려 주세요..." RemoteRecover: '원격 데이터베이스를 복원하려면 먼저 이미지 {{ .name }}을(를) 사용하여 로컬 컨테이너 데이터베이스 서비스를 시작해야 합니다. 잠시만 기다려 주세요...'
Arg: "인수" Arg: '인수'
#레디스
ErrTypeOfRedis: '복구 파일 유형이 현재 지속성 방법과 일치하지 않습니다. 수정하고 다시 시도하세요' ErrTypeOfRedis: '복구 파일 유형이 현재 지속성 방법과 일치하지 않습니다. 수정하고 다시 시도하세요'
ErrInUsed: '{{ .detail }}(이)가 사용 중이어서 삭제할 수 없습니다'
#컨테이너 ErrObjectInUsed: '이 객체는 사용 중이어서 삭제할 수 없습니다'
ErrInUsed: "{{ .detail }}(이)가 사용 중이어서 삭제할 수 없습니다!" ErrObjectBeDependent: '이 이미지는 다른 이미지에 의존되어 있어 삭제할 수 없습니다'
ErrObjectInUsed: "이 객체는 사용 중이어서 삭제할 수 없습니다!" ErrPortRules: '포트 번호가 일치하지 않습니다. 다시 입력하세요'
ErrObjectBeDependent: "이 이미지는 다른 이미지에 의존되어 있어 삭제할 수 없습니다!"
ErrPortRules: '포트 번호가 일치하지 않습니다. 다시 입력하세요!'
ErrPgImagePull: '이미지 풀링 시간이 초과되었습니다. 이미지 가속을 구성하거나 {{ .name }} 이미지를 수동으로 풀링한 다음 다시 시도하세요.' ErrPgImagePull: '이미지 풀링 시간이 초과되었습니다. 이미지 가속을 구성하거나 {{ .name }} 이미지를 수동으로 풀링한 다음 다시 시도하세요.'
PruneHelper: "이번 정리 {{ .name }}가 디스크 공간 {{ .size }}을(를) 확보했습니다" PruneHelper: '이번 정리 {{ .name }}가 디스크 공간 {{ .size }}을(를) 확보했습니다'
ImageRemoveHelper: "이미지 {{ .name }} 삭제, {{ .size }} 디스크 공간 확보" ImageRemoveHelper: '이미지 {{ .name }} 삭제, {{ .size }} 디스크 공간 확보'
BuildCache: "빌드 캐시" BuildCache: '빌드 캐시'
Volume: "스토리지 볼륨" Volume: '스토리지 볼륨'
Network: "네트워크" Network: '네트워크'
PruneStart: "정리 중입니다. 잠시만 기다려주세요..." PruneStart: '정리 중입니다. 잠시만 기다려주세요...'
ErrFileNotExist: '{{ .detail }} 파일이 존재하지 않습니다 소스 파일의 무결성을 확인하세요'
#실행 시간
ErrFileNotExist: '{{ .detail }} 파일이 존재하지 않습니다! 소스 파일의 무결성을 확인하세요!'
ErrImageBuildErr: '이미지 빌드 실패' ErrImageBuildErr: '이미지 빌드 실패'
ErrImageExist: "이미지가 이미 존재합니다! 이미지 이름을 수정하세요." ErrImageExist: '이미지가 이미 존재합니다 이미지 이름을 수정하세요.'
ErrDelWithWebsite: '운영 환경이 이미 웹사이트와 연결되어 있어 삭제할 수 없습니다' ErrDelWithWebsite: '운영 환경이 이미 웹사이트와 연결되어 있어 삭제할 수 없습니다'
ErrRuntimeStart: '시작 실패' ErrRuntimeStart: '시작 실패'
ErrPackageJsonNotFound: 'package.json 파일이 존재하지 않습니다' ErrPackageJsonNotFound: 'package.json 파일이 존재하지 않습니다'
ErrScriptsNotFound: 'package.json에서 스크립트 구성 항목을 찾을 수 없습니다.' ErrScriptsNotFound: 'package.json에서 스크립트 구성 항목을 찾을 수 없습니다.'
ErrContainerNameNotFound: '컨테이너 이름을 가져올 수 없습니다. .env 파일을 확인하세요.' ErrContainerNameNotFound: '컨테이너 이름을 가져올 수 없습니다..env 파일을 확인하세요.'
ErrNodeModulesNotFound: 'node_modules 폴더가 없습니다! 런타임 환경을 편집하거나 런타임 환경이 성공적으로 시작될 때까지 기다리십시오' ErrNodeModulesNotFound: 'node_modules 폴더가 없습니다 런타임 환경을 편집하거나 런타임 환경이 성공적으로 시작될 때까지 기다리십시오'
ErrContainerNameIsNull: '컨테이너 이름이 존재하지 않습니다' ErrContainerNameIsNull: '컨테이너 이름이 존재하지 않습니다'
ErrPHPPortIsDefault: "9000 포트는 기본 포트입니다. 수정 후 다시 시도하세요" ErrPHPPortIsDefault: '9000 포트는 기본 포트입니다. 수정 후 다시 시도하세요'
ErrPHPRuntimePortFailed: "포트 {{ .name }} 는 현재 런타임 환경에서 이미 사용 중입니다. 수정 후 다시 시도하세요" ErrPHPRuntimePortFailed: '포트 {{ .name }} 는 현재 런타임 환경에서 이미 사용 중입니다. 수정 후 다시 시도하세요'
#도구
ErrConfigNotFound: '구성 파일이 존재하지 않습니다' ErrConfigNotFound: '구성 파일이 존재하지 않습니다'
ErrConfigParse: '구성 파일 형식이 올바르지 않습니다' ErrConfigParse: '구성 파일 형식이 올바르지 않습니다'
ErrConfigIsNull: '구성 파일은 비어 있을 수 없습니다' ErrConfigIsNull: '구성 파일은 비어 있을 수 없습니다'
ErrConfigDirNotFound: '실행 디렉토리가 존재하지 않습니다' ErrConfigDirNotFound: '실행 디렉토리가 존재하지 않습니다'
ErrConfigAlreadyExist: '같은 이름의 구성 파일이 이미 존재합니다' ErrConfigAlreadyExist: '같은 이름의 구성 파일이 이미 존재합니다'
ErrUserFindErr: '사용자 {{ .name }} 검색에 실패했습니다 {{ .err }}' ErrUserFindErr: '사용자 {{ .name }} 검색에 실패했습니다 {{ .err }}'
#크론잡
CutWebsiteLogSuccess: '{{ .name }} 웹사이트 로그가 성공적으로 잘렸습니다. 백업 경로 {{ .path }}' CutWebsiteLogSuccess: '{{ .name }} 웹사이트 로그가 성공적으로 잘렸습니다. 백업 경로 {{ .path }}'
HandleShell: '스크립트 {{ .name }} 실행' HandleShell: '스크립트 {{ .name }} 실행'
HandleCurl: "URL {{ .name }} 접근" HandleCurl: 'URL {{ .name }} 접근'
HandleNtpSync: '시스템 시간 동기화' HandleNtpSync: '시스템 시간 동기화'
HandleSystemClean: '시스템 캐시 정리' HandleSystemClean: '시스템 캐시 정리'
SystemLog: '시스템 로그' SystemLog: '시스템 로그'
CutWebsiteLog: '웹사이트 로그 회전' CutWebsiteLog: '웹사이트 로그 회전'
FileOrDir: '디렉터리 / 파일' FileOrDir: '디렉터리 / 파일'
UploadFile: '백업 파일 {{ .file }} 을(를) {{ .backup }}(으)로 업로드 중' UploadFile: '백업 파일 {{ .file }} 을(를) {{ .backup }}(으)로 업로드 중'
Upload: "업로드" Upload: '업로드'
IgnoreBackupErr: "백업 실패, 오류: {{ .detail }}, 이 오류를 무시합니다..." IgnoreBackupErr: '백업 실패, 오류: {{ .detail }}, 이 오류를 무시합니다...'
IgnoreUploadErr: "업로드 실패, 오류: {{ .detail }}, 이 오류를 무시합니다..." IgnoreUploadErr: '업로드 실패, 오류: {{ .detail }}, 이 오류를 무시합니다...'
LoadBackupFailed: "백업 계정 연결 획득 실패, 오류: {{ .detail }}" LoadBackupFailed: '백업 계정 연결 획득 실패, 오류: {{ .detail }}'
InExecuting: "현재 작업이 실행 중입니다. 중복 실행하지 마세요!" InExecuting: '현재 작업이 실행 중입니다. 중복 실행하지 마세요'
NoSuchResource: "데이터베이스에서 백업 내용을 찾을 수 없어 건너뜁니다..." NoSuchResource: '데이터베이스에서 백업 내용을 찾을 수 없어 건너뜁니다...'
CleanLog: "로그 정리" CleanLog: '로그 정리'
CleanLogByName: "{{.name}} 로그 정리" CleanLogByName: '{{ .name }} 로그 정리'
WafIpGroupNotFound: "WAF IP 그룹을 찾을 수 없습니다. [고급 기능 - WAF - 블랙/화이트 목록 - IP 그룹]으로 이동하여 원격 다운로드 방식으로 IP 그룹을 추가하십시오." WafIpGroupNotFound: 'WAF IP 그룹을 찾을 수 없습니다. [고급 기능 - WAF - 블랙/화이트 목록 - IP 그룹]으로 이동하여 원격 다운로드 방식으로 IP 그룹을 추가하십시오.'
ErrNotExistUser: '현재 사용자가 존재하지 않습니다. 수정한 후 다시 시도하세요'
#도구상자 ErrBanAction: '설정에 실패했습니다. 현재 {{ .name }} 서비스를 사용할 수 없습니다. 확인하고 다시 시도하세요'
ErrNotExistUser: '현재 사용자가 존재하지 않습니다. 수정한 후 다시 시도하세요!' ErrClamdscanNotFound: 'clamdscan 명령이 감지되지 않았습니다. 설명서를 참조하여 설치하세요'
ErrBanAction: '설정에 실패했습니다. 현재 {{ .name }} 서비스를 사용할 수 없습니다. 확인하고 다시 시도하세요!' TaskSwapSet: 'Swap 설정'
ErrClamdscanNotFound: 'clamdscan 명령이 감지되지 않았습니다. 설명서를 참조하여 설치하세요!' SetSwap: 'Swap 설정 {{ .path }} - {{ .size }}'
TaskSwapSet: "Swap 설정" CreateSwap: 'Swap 파일 생성'
SetSwap: "Swap 설정 {{ .path }} - {{ .size }}" FormatSwap: 'Swap 파일 포맷'
CreateSwap: "Swap 파일 생성" EnableSwap: 'Swap 활성화'
FormatSwap: "Swap 파일 포맷" CleanTamperSetting: '히스토리 보호 설정 정리'
EnableSwap: "Swap 활성화" SetTamperWithRules: '규칙에 따라 디렉토리 보호 시작'
ProtectDir: '디렉토리 보호 {{ .name }}'
#tamper IgnoreFile: '파일 보호 {{ .name }}'
CleanTamperSetting: "히스토리 보호 설정 정리" TamperSetSuccessful: '보호 설정 완료, 다음 디렉토리 모니터링 시작:'
SetTamperWithRules: "규칙에 따라 디렉토리 보호 시작"
ProtectDir: "디렉토리 보호 {{ .name }}"
IgnoreFile: "파일 보호 {{ .name }}"
TamperSetSuccessful: "보호 설정 완료, 다음 디렉토리 모니터링 시작:"
#와프
ErrScope: '이 구성을 수정하는 것은 지원되지 않습니다' ErrScope: '이 구성을 수정하는 것은 지원되지 않습니다'
ErrStateChange: '상태 변경에 실패했습니다' ErrStateChange: '상태 변경에 실패했습니다'
ErrRuleExist: '규칙이 이미 존재합니다' ErrRuleExist: '규칙이 이미 존재합니다'
@@ -299,7 +264,7 @@ ErrRuleNotExist: '규칙이 존재하지 않습니다'
ErrParseIP: '잘못된 IP 형식' ErrParseIP: '잘못된 IP 형식'
ErrDefaultIP: '기본값은 예약된 이름입니다. 다른 이름으로 변경해 주세요' ErrDefaultIP: '기본값은 예약된 이름입니다. 다른 이름으로 변경해 주세요'
ErrGroupInUse: 'IP 그룹이 블랙리스트/화이트리스트에 사용 중이므로 삭제할 수 없습니다.' ErrGroupInUse: 'IP 그룹이 블랙리스트/화이트리스트에 사용 중이므로 삭제할 수 없습니다.'
ErrIPGroupAclUse: "IP 그룹은 웹사이트 {{ .name }} 의 사용자 정의 규칙에 사용되므로 삭제할 수 없습니다" ErrIPGroupAclUse: 'IP 그룹은 웹사이트 {{ .name }} 의 사용자 정의 규칙에 사용되므로 삭제할 수 없습니다'
ErrGroupExist: 'IP 그룹 이름이 이미 존재합니다' ErrGroupExist: 'IP 그룹 이름이 이미 존재합니다'
ErrIPRange: '잘못된 IP 범위' ErrIPRange: '잘못된 IP 범위'
ErrIPExist: 'IP가 이미 존재합니다' ErrIPExist: 'IP가 이미 존재합니다'
@@ -310,10 +275,10 @@ xss: 'XSS'
phpExec: 'PHP 스크립트 실행' phpExec: 'PHP 스크립트 실행'
oneWordTrojan: '한 단어 트로이' oneWordTrojan: '한 단어 트로이'
appFilter: '위험한 디렉토리 필터링 적용' appFilter: '위험한 디렉토리 필터링 적용'
webshell: '웹쉘' webShell: '웹쉘'
args: '매개변수 규칙' args: '매개변수 규칙'
protocolFilter: '프로토콜 필터링' protocolFilter: '프로토콜 필터링'
javaFileter: 'Java 위험 파일 필터' javaFilter: 'Java 위험 파일 필터'
scannerFilter: '스캐너 필터' scannerFilter: '스캐너 필터'
escapeFilter: '탈출 필터' escapeFilter: '탈출 필터'
customRule: '사용자 정의 규칙' customRule: '사용자 정의 규칙'
@@ -343,10 +308,9 @@ ErrDBNotExist: '데이터베이스가 존재하지 않습니다'
allow: '허용하다' allow: '허용하다'
deny: '거부하다' deny: '거부하다'
OpenrestyNotFound: 'Openresty가 설치되지 않았습니다' OpenrestyNotFound: 'Openresty가 설치되지 않았습니다'
remoteIpIsNull: "IP 목록이 비어 있습니다" remoteIpIsNull: 'IP 목록이 비어 있습니다'
OpenrestyVersionErr: "Openresty 버전이 너무 낮습니다. Openresty를 1.27.1.2-2-2-focal로 업그레이드하세요" OpenrestyVersionErr: 'Openresty 버전이 너무 낮습니다. Openresty를 1.27.1.2-2-2-focal로 업그레이드하세요'
ErrFileTooLarge: '파일이 1MB를 초과하여 업로드할 수 없습니다'
#일
TaskStart: '[START] {{ .name }} 작업이 시작됩니다.' TaskStart: '[START] {{ .name }} 작업이 시작됩니다.'
TaskEnd: '{{ .name }} 작업이 완료되었습니다 [완료]' TaskEnd: '{{ .name }} 작업이 완료되었습니다 [완료]'
TaskFailed: '{{ .name }} 작업이 실패했습니다' TaskFailed: '{{ .name }} 작업이 실패했습니다'
@@ -362,7 +326,7 @@ TaskDelete: '삭제'
TaskUpgrade: '업그레이드' TaskUpgrade: '업그레이드'
TaskUpdate: '업데이트' TaskUpdate: '업데이트'
TaskRestart: '다시 시작' TaskRestart: '다시 시작'
TaskProtect: "보호" TaskProtect: '보호'
TaskBackup: '백업' TaskBackup: '백업'
TaskRecover: '복구' TaskRecover: '복구'
TaskRollback: '롤백' TaskRollback: '롤백'
@@ -370,10 +334,10 @@ TaskPull: '당기기'
TaskCommit: '커밋' TaskCommit: '커밋'
TaskBuild: '빌드' TaskBuild: '빌드'
TaskPush: '푸시' TaskPush: '푸시'
TaskClean: "정리" TaskClean: '정리'
TaskHandle: '실행' TaskHandle: '실행'
TaskImport: "가져오기" TaskImport: '가져오기'
TaskExport: "내보내기" TaskExport: '내보내기'
Website: '웹사이트' Website: '웹사이트'
App: '애플리케이션' App: '애플리케이션'
Runtime: '런타임 환경' Runtime: '런타임 환경'
@@ -393,7 +357,7 @@ Start: '시작'
Run: '시작' Run: '시작'
Stop: '정지' Stop: '정지'
Image: '거울' Image: '거울'
Compose : '오케스트레이션' Compose: '오케스트레이션'
Container: '컨테이너' Container: '컨테이너'
AppLink: '연결된 애플리케이션' AppLink: '연결된 애플리케이션'
EnableSSL: 'HTTPS 활성화' EnableSSL: 'HTTPS 활성화'
@@ -405,18 +369,12 @@ RuntimeExtension: '런타임 환경 확장'
TaskIsExecuting: '작업이 실행 중입니다' TaskIsExecuting: '작업이 실행 중입니다'
CustomAppstore: '사용자 정의 애플리케이션 웨어하우스' CustomAppstore: '사용자 정의 애플리케이션 웨어하우스'
TaskExec: '실행' TaskExec: '실행'
TaskBatch: "일괄 작업" TaskBatch: '일괄 작업'
FileConvert: '파일 형식 변환' FileConvert: '파일 형식 변환'
Clamscan: '{{ .name }} 스캔'
# task - clam TaskScan: '스캔'
Clamscan: "{{ .name }} 스캔"
TaskScan: "스캔"
# 작업 - ai
OllamaModelPull: 'Ollama 모델 {{ .name }}을(를) 끌어오세요' OllamaModelPull: 'Ollama 모델 {{ .name }}을(를) 끌어오세요'
OllamaModelSize: 'Ollama 모델 {{ .name }}의 크기를 가져옵니다' OllamaModelSize: 'Ollama 모델 {{ .name }}의 크기를 가져옵니다'
# 작업-스냅샷
Snapshot: '스냅샷' Snapshot: '스냅샷'
SnapDBInfo: '1Panel 데이터베이스 정보 쓰기' SnapDBInfo: '1Panel 데이터베이스 정보 쓰기'
SnapCopy: '파일 및 디렉토리 {{ .name }} 복사' SnapCopy: '파일 및 디렉토리 {{ .name }} 복사'
@@ -442,7 +400,6 @@ SnapCompressSize: '스냅샷 파일 크기 {{ .name }}'
SnapUpload: '스냅샷 파일 업로드' SnapUpload: '스냅샷 파일 업로드'
SnapUploadTo: '스냅샷 파일을 {{ .name }}에 업로드' SnapUploadTo: '스냅샷 파일을 {{ .name }}에 업로드'
SnapUploadRes: '스냅샷 파일을 {{ .name }}에 업로드' SnapUploadRes: '스냅샷 파일을 {{ .name }}에 업로드'
SnapshotRecover: '스냅샷 복원' SnapshotRecover: '스냅샷 복원'
RecoverDownload: '스냅샷 파일 다운로드' RecoverDownload: '스냅샷 파일 다운로드'
Download: '다운로드' Download: '다운로드'
@@ -450,10 +407,10 @@ RecoverDownloadAccount: '스냅샷 다운로드 백업 계정 {{ .name }} 가져
RecoverDecompress: '스냅샷 압축 파일 압축 해제' RecoverDecompress: '스냅샷 압축 파일 압축 해제'
Decompress: '감압' Decompress: '감압'
BackupBeforeRecover: '스냅샷 전에 시스템 관련 데이터 백업' BackupBeforeRecover: '스냅샷 전에 시스템 관련 데이터 백업'
Readjson: '스냅샷에서 Json 파일을 읽습니다' ReadJson: '스냅샷에서 Json 파일을 읽습니다'
ReadjsonPath: '스냅샷의 Json 파일 경로 가져오기' ReadJsonPath: '스냅샷의 Json 파일 경로 가져오기'
ReadjsonContent: 'Json 파일 읽기' ReadJsonContent: 'Json 파일 읽기'
ReadjsonMarshal: 'Json 이스케이프 처리' ReadJsonMarshal: 'Json 이스케이프 처리'
RecoverApp: '설치된 앱 복원' RecoverApp: '설치된 앱 복원'
RecoverWebsite: '웹사이트 디렉토리 복구' RecoverWebsite: '웹사이트 디렉토리 복구'
RecoverAppImage: '스냅샷 이미지 백업 복원' RecoverAppImage: '스냅샷 이미지 백업 복원'
@@ -467,9 +424,6 @@ RecoverDaemonJson: '컨테이너 구성 daemon.json 파일 복원'
RecoverDBData: '데이터베이스 데이터 복구' RecoverDBData: '데이터베이스 데이터 복구'
RecoverBackups: '로컬 백업 디렉토리 복원' RecoverBackups: '로컬 백업 디렉토리 복원'
RecoverPanelData: '복구 데이터 디렉토리' RecoverPanelData: '복구 데이터 디렉토리'
# 작업 - 컨테이너
ContainerNewCliet: 'Docker 클라이언트 초기화'
ContainerImagePull: '컨테이너 이미지 {{ .name }} 가져오기' ContainerImagePull: '컨테이너 이미지 {{ .name }} 가져오기'
ContainerRemoveOld: '원래 컨테이너 {{ .name }} 제거' ContainerRemoveOld: '원래 컨테이너 {{ .name }} 제거'
ContainerImageCheck: '이미지가 정상적으로 당겨졌는지 확인' ContainerImageCheck: '이미지가 정상적으로 당겨졌는지 확인'
@@ -478,22 +432,13 @@ ContainerRecreate: '컨테이너 업데이트에 실패했습니다. 이제 원
ContainerCreate: '새로운 컨테이너 {{ .name }}를 만듭니다' ContainerCreate: '새로운 컨테이너 {{ .name }}를 만듭니다'
ContainerCreateFailed: '컨테이너 생성에 실패했습니다. 실패한 컨테이너를 삭제하세요' ContainerCreateFailed: '컨테이너 생성에 실패했습니다. 실패한 컨테이너를 삭제하세요'
ContainerStartCheck: '컨테이너가 시작되었는지 확인' ContainerStartCheck: '컨테이너가 시작되었는지 확인'
# 작업 - 이미지
ImageBuild: '이미지 빌드' ImageBuild: '이미지 빌드'
ImageBuildStdoutCheck: '이미지 출력 콘텐츠 구문 분석'
ImageBuildRes: '이미지 빌드 출력: {{ .name }}'
ImagePull: '이미지 가져오기' ImagePull: '이미지 가져오기'
ImageRepoAuthFromDB: '데이터베이스에서 저장소 인증 정보 가져오기' ImageRepoAuthFromDB: '데이터베이스에서 저장소 인증 정보 가져오기'
ImaegPullRes: '이미지 풀 출력: {{ .name }}'
ImagePush: '이미지 푸시' ImagePush: '이미지 푸시'
ImageRenameTag: '이미지 태그 수정' ImageRenameTag: '이미지 태그 수정'
ImageNewTag: '새로운 이미지 태그 {{ .name }}' ImageNewTag: '새로운 이미지 태그 {{ .name }}'
ImaegPushRes: '이미지 푸시 출력: {{ .name }}'
ComposeCreate: '작곡 만들기' ComposeCreate: '작곡 만들기'
ComposeCreateRes: 'Compose 생성 출력: {{ .name }}'
# 작업 - 웹사이트
BackupNginxConfig: '웹사이트 OpenResty 구성 파일 백업' BackupNginxConfig: '웹사이트 OpenResty 구성 파일 백업'
CompressFileSuccess: '디렉토리 압축이 성공했습니다. {{ .name }}으로 압축되었습니다.' CompressFileSuccess: '디렉토리 압축이 성공했습니다. {{ .name }}으로 압축되었습니다.'
CompressDir: '압축 디렉토리' CompressDir: '압축 디렉토리'
@@ -504,40 +449,27 @@ websiteDir: '웹사이트 디렉토리'
RecoverFailedStartRollBack: '복구 실패, 롤백 시작' RecoverFailedStartRollBack: '복구 실패, 롤백 시작'
AppBackupFileIncomplete: '백업 파일이 불완전하며 app.json 또는 app.tar.gz 파일이 없습니다.' AppBackupFileIncomplete: '백업 파일이 불완전하며 app.json 또는 app.tar.gz 파일이 없습니다.'
AppAttributesNotMatch: '애플리케이션 유형 또는 이름이 일치하지 않습니다' AppAttributesNotMatch: '애플리케이션 유형 또는 이름이 일치하지 않습니다'
ErrAlertSync: '알람 정보 동기화 오류입니다. 확인하고 다시 시도하세요'
#알리다 ErrInstallExtension: '이미 설치 작업이 진행 중입니다. 작업이 완료될 때까지 기다려 주세요.'
ErrAlert: '경고 메시지의 형식이 올바르지 않습니다. 확인하고 다시 시도하세요!' PanelAlertTitle: '패널 알림 통지'
ErrAlertPush: '알림 정보를 푸시하는 중 오류가 발생했습니다. 확인하고 다시 시도하세요!' TestAlertTitle: '테스트 이메일 - 이메일 연결 확인'
ErrAlertSave: '알람 정보를 저장하는 중 오류가 발생했습니다. 확인하고 다시 시도하세요!' TestAlert: '이것은 테스트 이메일이며 이메일 발송 설정이 올바른지 확인합니다.'
ErrAlertSync: '알람 정보 동기화 오류입니다. 확인하고 다시 시도하세요!' LicenseExpirationAlert: '귀하의 {{ .node }}{{ .ip }} 패널, 라이센스가 {{ .day }}일 후에 만료됩니다. 자세한 내용은 패널에 로그인하십시오.'
ErrAlertRemote: '알람 메시지 원격 오류, 확인하고 다시 시도하세요!' CronJobFailedAlert: '귀하의 {{ .node }}{{ .ip }} 패널, 예약 작업 {{ .name }} 실행에 실패했습니다. 자세한 내용은 패널에 로그인하십시오.'
ClamAlert: '귀하의 {{ .node }}{{ .ip }} 패널, 바이러스 스캔 작업에서 {{ .num }}개의 감염 파일이 감지되었습니다. 자세한 내용은 패널에 로그인하십시오.'
#task - runtime WebSiteAlert: '귀하의 {{ .node }}{{ .ip }} 패널, {{ .num }}개의 웹사이트가 {{ .day }}일 후에 만료됩니다. 자세한 내용은 패널에 로그인하십시오.'
ErrInstallExtension: "이미 설치 작업이 진행 중입니다. 작업이 완료될 때까지 기다려 주세요." SSLAlert: '귀하의 {{ .node }}{{ .ip }} 패널, {{ .num }}개의 SSL 인증서가 {{ .day }}일 후에 만료됩니다. 자세한 내용은 패널에 로그인하십시오.'
DiskUsedAlert: '귀하의 {{ .node }}{{ .ip }} 패널, 디스크 {{ .name }} 사용률이 {{ .used }}에 도달했습니다. 자세한 내용은 패널에 로그인하십시오.'
# alert mail template ResourceAlert: '귀하의 {{ .node }}{{ .ip }} 패널, 최근 {{ .time }}분간 {{ .name }} 평균 사용률은 {{ .used }}입니다. 자세한 내용은 패널에 로그인하십시오.'
PanelAlertTitle: "패널 알림 통지" PanelVersionAlert: '귀하의 {{ .node }}{{ .ip }} 패널, 최신 버전으로 업그레이드할 수 있습니다. 자세한 내용은 패널에 로그인하십시오.'
TestAlertTitle: "테스트 이메일 - 이메일 연결 확인" PanelPwdExpirationAlert: '귀하의 {{ .node }}{{ .ip }} 패널, 패널 비밀번호가 {{ .day }}일 후에 만료됩니다. 자세한 내용은 패널에 로그인하십시오.'
TestAlert: "이것은 테스트 이메일이며 이메일 발송 설정이 올바른지 확인합니다." CommonAlert: '귀하의 {{ .node }}{{ .ip }} 패널, {{ .msg }}。자세한 내용은 패널에 로그인하십시오.'
LicenseExpirationAlert: "귀하의 {{ .node }}{{ .ip }} 패널, 라이센스가 {{ .day }}일 후에 만료됩니다. 자세한 내용은 패널에 로그인하십시오." NodeExceptionAlert: '귀하의 {{ .node }}{{ .ip }} 패널, {{ .num }}개의 노드에 이상이 있습니다. 자세한 내용은 패널에 로그인하십시오.'
CronJobFailedAlert: "귀하의 {{ .node }}{{ .ip }} 패널, 예약 작업 {{ .name }} 실행에 실패했습니다. 자세한 내용은 패널에 로그인하십시오." LicenseExceptionAlert: '귀하의 {{ .node }}{{ .ip }} 패널, {{ .num }}개의 라이센스에 이상이 있습니다. 자세한 내용은 패널에 로그인하십시오.'
ClamAlert: "귀하의 {{ .node }}{{ .ip }} 패널, 바이러스 스캔 작업에서 {{ .num }}개의 감염 파일이 감지되었습니다. 자세한 내용은 패널에 로그인하십시오." SSHAndPanelLoginAlert: '귀하의 {{ .node }}{{ .ip }} 패널, {{ .loginIp }}에서의 {{ .name }} 로그인에 이상이 있습니다. 자세한 내용은 패널에 로그인하십시오.'
WebSiteAlert: "귀하의 {{ .node }}{{ .ip }} 패널, {{ .num }}개의 웹사이트가 {{ .day }}일 후에 만료됩니다. 자세한 내용은 패널에 로그인하십시오." DeviceNotFound: '장치 {{ .name }} 을(를) 찾을 수 없습니다'
SSLAlert: "귀하의 {{ .node }}{{ .ip }} 패널, {{ .num }}개의 SSL 인증서가 {{ .day }}일 후에 만료됩니다. 자세한 내용은 패널에 로그인하십시오." DeviceIsMounted: '장치 {{ .name }} 이(가) 마운트되었습니다, 먼저 마운트 해제하세요'
DiskUsedAlert: "귀하의 {{ .node }}{{ .ip }} 패널, 디스크 {{ .name }} 사용률이 {{ .used }}에 도달했습니다. 자세한 내용은 패널에 로그인하십시오." PartitionDiskErr: '파티션 분할에 실패했습니다, {{ .err }}'
ResourceAlert: "귀하의 {{ .node }}{{ .ip }} 패널, 최근 {{ .time }}분간 {{ .name }} 평균 사용률은 {{ .used }}입니다. 자세한 내용은 패널에 로그인하십시오." FormatDiskErr: '디스크 포맷에 실패했습니다, {{ .err }}'
PanelVersionAlert: "귀하의 {{ .node }}{{ .ip }} 패널, 최신 버전으로 업그레이드할 수 있습니다. 자세한 내용은 패널에 로그인하십시오." MountDiskErr: '디스크 마운트에 실패했습니다, {{ .err }}'
PanelPwdExpirationAlert: "귀하의 {{ .node }}{{ .ip }} 패널, 패널 비밀번호가 {{ .day }}일 후에 만료됩니다. 자세한 내용은 패널에 로그인하십시오." XfsNotFound: 'xfs 파일 시스템이 감지되지 않았습니다, 먼저 xfsprogs 를 설치하세요'
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 를 설치하세요"
+172 -240
View File
@@ -1,83 +1,71 @@
ErrInvalidParams: 'Permintaan ralat parameter: {{ .detail }}' ErrInvalidParams: 'Permintaan tidak sah: {{ .detail }}'
ErrTokenParse: 'Ralat penjanaan token: {{ .detail }}' ErrTokenParse: 'Token tidak sah: {{ .detail }}'
ErrInitialPassword: 'Kata laluan asal tidak betul' ErrInitialPassword: 'Kata laluan asal salah'
ErrInternalServer: 'Ralat pelayan dalaman: {{ .detail }}' ErrInternalServer: 'Ralat pelayan: {{ .detail }}'
ErrRecordExist: 'Rekod sudah wujud' ErrRecordExist: 'Rekod sudah wujud'
ErrRecordNotFound: 'Rekod tidak ditemui' ErrRecordNotFound: 'Rekod tidak ditemui'
ErrStructTransform: 'Penukaran jenis gagal: {{ .err }}' ErrStructTransform: 'Ralat penukaran: {{ .err }}'
ErrNotLogin: 'Pengguna tidak log masuk: {{ .detail }}' ErrNotLogin: 'Belum log masuk: {{ .detail }}'
ErrPasswordExpired: 'Kata laluan semasa telah tamat tempoh: {{ .detail }}' ErrPasswordExpired: 'Kata laluan tamat: {{ .detail }}'
ErrNotSupportType: 'Sistem tidak menyokong jenis semasa: {{ .name }}' ErrNotSupportType: 'Jenis tidak disokong: {{ .name }}'
ErrProxy: 'Ralat permintaan, sila semak status nod: {{ .detail }}' ErrProxy: 'Permintaan gagal: {{ .detail }}'
ErrApiConfigStatusInvalid: 'Akses kepada antara muka API adalah dilarang: {{ .detail }}' ErrApiConfigStatusInvalid: 'API dilumpuhkan: {{ .detail }}'
ErrApiConfigKeyInvalid: 'Ralat kunci antara muka API: {{ .detail }}' ErrApiConfigKeyInvalid: 'Kunci API tidak sah: {{ .detail }}'
ErrApiConfigIPInvalid: 'IP yang digunakan untuk memanggil antara muka API tiada dalam senarai putih: {{ .detail }}' ErrApiConfigIPInvalid: 'IP tidak dibenarkan: {{ .detail }}'
ErrApiConfigDisable: 'Antara muka ini melarang penggunaan panggilan antara muka API: {{ .detail }}' ErrApiConfigDisable: 'API tidak dibenarkan: {{ .detail }}'
ErrApiConfigKeyTimeInvalid: 'Ralat cap masa antara muka API: {{ .detail }}' ErrApiConfigKeyTimeInvalid: 'Cap masa tidak sah: {{ .detail }}'
StartPushSSLToNode: "Mula menolak sijil ke nod" ErrShutDown: 'Arahan diberhentikan manual'
PushSSLToNodeFailed: "Gagal menolak sijil ke nod: {{ .err }}" ErrMinQuickJump: 'Tambah sekurang-kurangnya satu pintasan pantas'
PushSSLToNodeSuccess: "Berjaya menolak sijil ke nod" ErrMaxQuickJump: 'Maksimum 4 pintasan pantas'
ErrShutDown: "Arahan dihentikan secara manual!"
ErrMinQuickJump: "Sila tetapkan sekurang-kurangnya satu entri lompat pantas!"
ErrMaxQuickJump: "Anda boleh menetapkan sehingga empat entri lompat pantas!"
#biasa
ErrUsernameIsExist: 'Nama pengguna sudah wujud' ErrUsernameIsExist: 'Nama pengguna sudah wujud'
ErrNameIsExist: 'Nama sudah wujud' ErrNameIsExist: 'Nama sudah wujud'
ErrDemoEnvironment: 'Pelayan demo, operasi ini dilarang!' ErrDemoEnvironment: 'Tidak tersedia dalam demo'
ErrCmdTimeout: 'Pelaksanaan arahan tamat masa!' ErrCmdTimeout: 'Arahan tamat masa'
ErrCmdIllegal: 'Terdapat aksara yang menyalahi undang-undang dalam perintah pelaksanaan, sila ubah suainya dan cuba lagi!' ErrCmdIllegal: 'Arahan ada aksara tidak sah'
ErrPortExist: '{{ .port }} port sudah diduduki oleh {{ .type }} [{{ .name }}]' ErrPortExist: 'Port {{ .port }} sudah digunakan oleh {{ .type }} [{{ .name }}]'
TYPE_APP: 'Aplikasi' TYPE_APP: 'Aplikasi'
TYPE_RUNTIME: 'Persekitaran masa jalan' TYPE_RUNTIME: 'Persekitaran masa jalan'
TYPE_DOMAIN: 'Nama Domain' TYPE_DOMAIN: 'Nama Domain'
ErrTypePort: Format 'Port {{ .name }} tidak betul' ErrTypePort: 'Format ''Port {{ .name }} tidak betul'''
ErrTypePortRange: 'Julat port perlu antara 1-65535' ErrTypePortRange: 'Julat port perlu antara 1-65535'
Success: 'Kejayaan' Success: 'Kejayaan'
Failed: 'Gagal' Failed: 'Gagal'
SystemRestart: 'Tugas terganggu kerana sistem mula semula' SystemRestart: 'Tugas terganggu kerana sistem mula semula'
ErrGroupIsDefault: 'Kumpulan lalai, tidak boleh dipadamkan' ErrGroupIsDefault: 'Kumpulan lalai, tidak boleh dipadamkan'
ErrGroupIsInWebsiteUse: 'Kumpulan sedang digunakan oleh tapak web lain dan tidak boleh dipadamkan.' ErrGroupIsInWebsiteUse: 'Kumpulan sedang digunakan oleh tapak web lain dan tidak boleh dipadamkan.'
Decrypt: "Dekripsi" Decrypt: 'Dekripsi'
ErrAgentAccountBound: 'Akaun terikat kepada ejen'
#agent ErrAgentAccountUnavailable: 'Sambungan akaun tidak tersedia: {{ .err }}'
ErrAgentAccountBound: 'Akaun ini telah dipautkan kepada ejen dan tidak boleh dipadam. Sila semak dan cuba lagi!' ErrAgentProviderNotSupported: 'Penyedia ejen tidak disokong'
ErrAgentAccountUnavailable: 'Maklumat sambungan akaun tidak tersedia. Ralat: {{ .err }}. Sila semak dan cuba lagi!' ErrAgentAccountRequired: 'Pilih akaun ejen terlebih dahulu'
ErrAgentProviderNotSupported: 'Penyedia ejen ini tidak disokong. Sila semak dan cuba lagi!' ErrAgentAccountNotVerified: 'Akaun ejen belum disahkan'
ErrAgentAccountRequired: 'Sila pilih akaun ejen dan cuba lagi.' ErrAgentProviderMismatch: 'Penyedia ejen tidak sepadan'
ErrAgentAccountNotVerified: 'Akaun belum disahkan. Sila semak dan cuba lagi!' ErrAgentBaseURLRequired: 'URL asas diperlukan'
ErrAgentProviderMismatch: 'Penyedia akaun tidak sepadan. Sila semak dan cuba lagi!' ErrAgentApiKeyRequired: 'Kunci API diperlukan'
ErrAgentBaseURLRequired: 'Base URL tidak boleh kosong. Sila semak dan cuba lagi!' ErrAgentComposeRequired: 'Kandungan compose diperlukan'
ErrAgentApiKeyRequired: 'API Key tidak boleh kosong. Sila semak dan cuba lagi!' ErrAgentIDRequired: 'ID ejen diperlukan'
ErrAgentComposeRequired: 'Kandungan compose tersuai tidak boleh kosong. Sila semak dan cuba lagi!' ErrAgentAccountIDRequired: 'ID akaun diperlukan'
ErrAgentIDRequired: 'ID ejen tidak boleh kosong. Sila semak dan cuba lagi!'
ErrAgentAccountIDRequired: 'ID akaun tidak boleh kosong. Sila semak dan cuba lagi!'
#sandaran
Localhost: 'Mesin Tempatan' Localhost: 'Mesin Tempatan'
ErrBackupInUsed: 'Akaun sandaran telah digunakan dalam tugas yang dijadualkan dan tidak boleh dipadamkan.' ErrBackupInUsed: 'Akaun sandaran sedang digunakan oleh tugas'
ErrBackupCheck: 'Sambungan ujian akaun sandaran gagal {{ .err }}' ErrBackupCheck: 'Ujian sambungan gagal: {{ .err }}'
ErrBackupLocalDelete: 'Memadam akaun sandaran pelayan tempatan belum disokong lagi' ErrBackupLocalDelete: 'Tidak boleh padam sandaran tempatan'
ErrBackupLocalCreate: 'Membuat akaun sandaran pelayan tempatan belum disokong lagi' ErrBackupLocalCreate: 'Tidak boleh buat sandaran tempatan'
ErrPortInUsed: 'Port {{ .detail }} sudah diduduki'
#app
ErrPortInUsed: 'Port {{ .detail }} sudah diduduki!'
ErrAppLimit: 'Bilangan aplikasi yang dipasang telah melebihi had' ErrAppLimit: 'Bilangan aplikasi yang dipasang telah melebihi had'
ErrNotInstall: 'Aplikasi tidak dipasang' ErrNotInstall: 'Aplikasi tidak dipasang'
ErrPortInOtherApp: 'Port {{ .port }} sudah diduduki oleh aplikasi {{ .apps }}!' ErrPortInOtherApp: 'Port {{ .port }} sudah diduduki oleh aplikasi {{ .apps }}'
ErrDbUserNotValid: 'Pangkalan data sedia ada, nama pengguna dan kata laluan tidak sepadan!' 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! ' ErrUpdateBuWebsite: 'Aplikasi telah berjaya dikemas kini, tetapi pengubahsuaian fail konfigurasi tapak web gagal. Sila semak konfigurasi'
Err1PanelNetworkFailed: 'Pembuatan rangkaian kontena lalai gagal! {{ .detail }}' Err1PanelNetworkFailed: 'Pembuatan rangkaian kontena lalai gagal {{ .detail }}'
ErrFileParse: 'Penghuraian fail karang docker aplikasi gagal!' ErrFileParse: 'Penghuraian fail karang docker aplikasi gagal'
ErrInstallDirNotFound: 'Direktori pemasangan tidak wujud. Jika anda perlu menyahpasang, sila pilih Paksa Nyahpasang' ErrInstallDirNotFound: 'Direktori pemasangan tidak wujud. Jika anda perlu menyahpasang, sila pilih Paksa Nyahpasang'
AppStoreIsUpToDate: 'Gedung aplikasi sudah pun versi terkini' AppStoreIsUpToDate: 'Gedung aplikasi sudah pun versi terkini'
LocalAppVersionNull: Aplikasi '{{ .name }} tidak disegerakkan ke versi! Tidak dapat menambah pada senarai apl' LocalAppVersionNull: 'Aplikasi ''{{ .name }} tidak disegerakkan ke versi Tidak dapat menambah pada senarai apl'''
LocalAppVersionErr: '{{ .name }} versi penyegerakan {{ .version }} gagal! {{ .err }}' LocalAppVersionErr: '{{ .name }} versi penyegerakan {{ .version }} gagal {{ .err }}'
ErrFileNotFound: 'Fail {{ .name }} tidak wujud' ErrFileNotFound: 'Fail {{ .name }} tidak wujud'
ErrFileParseApp: '{{ .name }} penghuraian fail gagal {{ .err }}' ErrFileParseApp: '{{ .name }} penghuraian fail gagal {{ .err }}'
ErrAppDirNull: 'Folder versi tidak wujud' ErrAppDirNull: 'Folder versi tidak wujud'
LocalAppErr: 'Penyegerakan {{ .name }} aplikasi gagal! {{ .err }}' LocalAppErr: 'Penyegerakan {{ .name }} aplikasi gagal {{ .err }}'
ErrContainerName: 'Nama kontena sudah wujud' ErrContainerName: 'Nama kontena sudah wujud'
ErrCreateHttpClient: 'Gagal membuat permintaan {{ .err }}' ErrCreateHttpClient: 'Gagal membuat permintaan {{ .err }}'
ErrHttpReqTimeOut: 'Permintaan tamat masa {{ .err }}' ErrHttpReqTimeOut: 'Permintaan tamat masa {{ .err }}'
@@ -85,69 +73,63 @@ ErrHttpReqFailed: 'Permintaan gagal {{ .err }}'
ErrNoSuchHost: 'Tidak dapat mencari pelayan yang diminta {{ .err }}' ErrNoSuchHost: 'Tidak dapat mencari pelayan yang diminta {{ .err }}'
ErrHttpReqNotFound: 'Sumber yang diminta {{ .err }} tidak dapat ditemui' ErrHttpReqNotFound: 'Sumber yang diminta {{ .err }} tidak dapat ditemui'
ErrContainerNotFound: 'Bekas {{ .name }} tidak wujud' ErrContainerNotFound: 'Bekas {{ .name }} tidak wujud'
ErrContainerMsg: Bekas '{{ .name }} adalah tidak normal. Sila semak log pada halaman kontena untuk butiran' ErrContainerMsg: 'Bekas ''{{ .name }} adalah tidak normal. Sila semak log pada halaman kontena untuk butiran'''
ErrAppBackup: '{{ .name }} sandaran aplikasi gagal {{ .err }}' ErrAppBackup: '{{ .name }} sandaran aplikasi gagal {{ .err }}'
ErrVersionTooLow: 'Versi 1Panel semasa terlalu rendah untuk mengemas kini App Store. Sila tingkatkan versi sebelum beroperasi.' ErrVersionTooLow: 'Versi 1Panel semasa terlalu rendah untuk mengemas kini App Store. Sila tingkatkan versi sebelum beroperasi.'
ErrAppNameExist: 'Nama aplikasi sudah wujud' ErrAppNameExist: 'Nama aplikasi sudah wujud'
AppStoreIsSyncing: 'App Store sedang menyegerak, sila cuba sebentar lagi' AppStoreIsSyncing: 'App Store sedang menyegerak, sila cuba sebentar lagi'
ErrGetCompose: 'Gagal mendapatkan fail docker-compose.yml! {{ .detail }}' ErrGetCompose: 'Gagal mendapatkan fail docker-compose.yml {{ .detail }}'
ErrAppWarn: 'Status tidak normal, sila semak log' ErrAppWarn: 'Status tidak normal, sila semak log'
ErrAppParamKey: 'Parameter {{ .name }} medan tidak normal' ErrAppParamKey: 'Parameter {{ .name }} medan tidak normal'
ErrAppUpgrade: 'Peningkatan {{ .name }} aplikasi gagal {{ .err }}' ErrAppUpgrade: 'Peningkatan {{ .name }} aplikasi gagal {{ .err }}'
AppRecover: 'Aplikasi tarik balik {{ .name }}' AppRecover: 'Aplikasi tarik balik {{ .name }}'
PullImageStart: 'Mula tarik imej [{{ .name }}]' PullImageStart: 'Mula tarik imej [{{ .name }}]'
PullImageSuccess: 'Tarik imej berjaya' PullImageSuccess: 'Tarik imej berjaya'
AppStoreIsLastVersion: 'App Store sudah pun versi terkini'
AppStoreSyncSuccess: 'Penyegerakan App Store berjaya' AppStoreSyncSuccess: 'Penyegerakan App Store berjaya'
SyncAppDetail: 'Segerakkan konfigurasi aplikasi' SyncAppDetail: 'Segerakkan konfigurasi aplikasi'
AppVersionNotMatch: 'Aplikasi {{ .name }} memerlukan versi 1Panel yang lebih tinggi, melangkau penyegerakan' 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' MoveSiteDirSuccess: 'Penghijrahan direktori tapak web yang berjaya'
DeleteRuntimePHP: 'Padam masa jalan PHP' 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' PullImageTimeout: 'Tarik tamat masa imej, sila cuba tingkatkan pecutan imej atau tukar kepada pecutan imej lain'
ErrAppIsDown: 'Status permohonan {{ .name }} tidak normal, sila semak' ErrAppIsDown: 'Status permohonan {{ .name }} tidak normal, sila semak'
ErrCustomApps: 'Ada aplikasi yang dipasang, sila nyahpasangnya dahulu' ErrCustomApps: 'Ada aplikasi yang dipasang, sila nyahpasangnya dahulu'
ErrCustomRuntimes: 'Terdapat persekitaran masa jalan yang dipasang, sila padamkannya dahulu' ErrCustomRuntimes: 'Terdapat persekitaran masa jalan yang dipasang, sila padamkannya dahulu'
ErrAppVersionDeprecated: "Aplikasi {{ .name }} tidak sesuai dengan versi 1Panel saat ini, dilewati" ErrAppVersionDeprecated: 'Aplikasi {{ .name }} tidak sesuai dengan versi 1Panel saat ini, dilewati'
ErrDockerFailed: "Keadaan Docker tidak normal, sila periksa status perkhidmatan" ErrDockerFailed: 'Keadaan Docker tidak normal, sila periksa status perkhidmatan'
ErrDockerComposeCmdNotFound: "Perintah Docker Compose tidak wujud, sila pasang perintah ini di mesin tuan terlebih dahulu" ErrDockerComposeCmdNotFound: 'Perintah Docker Compose tidak wujud, sila pasang perintah ini di mesin tuan terlebih dahulu'
UseExistImage: 'Gagal menarik imej, menggunakan imej sedia ada' UseExistImage: 'Imej sudah wujud, menggunakan imej sedia ada'
ErrDatabaseNotFound: 'Pangkalan data {{ .name }} tidak wujud'
#ssh ExportIP: 'IP Log Masuk'
ExportIP: "IP Log Masuk" ExportArea: 'Lokasi'
ExportArea: "Lokasi" ExportPort: 'Port'
ExportPort: "Port" ExportAuthMode: 'Kaedah Log Masuk'
ExportAuthMode: "Kaedah Log Masuk" ExportUser: 'Pengguna'
ExportUser: "Pengguna" ExportStatus: 'Status Log Masuk'
ExportStatus: "Status Log Masuk" ExportDate: 'Masa'
ExportDate: "Masa"
#fail
ErrFileCanNotRead: 'Fail ini tidak menyokong pratonton' ErrFileCanNotRead: 'Fail ini tidak menyokong pratonton'
ErrFileToLarge: 'Fail lebih besar daripada 10M dan tidak boleh dibuka' ErrFileToLarge: 'Fail lebih besar daripada 10M dan tidak boleh dibuka'
ErrPathNotFound: 'Direktori tidak wujud' ErrPathNotFound: 'Direktori tidak wujud'
ErrMovePathFailed: 'Laluan sasaran tidak boleh mengandungi laluan asal!' ErrMovePathFailed: 'Laluan sasaran tidak boleh mengandungi laluan asal'
ErrLinkPathNotFound: 'Laluan sasaran tidak wujud!' ErrLinkPathNotFound: 'Laluan sasaran tidak wujud'
ErrFileIsExist: 'Fail atau folder sudah wujud!' ErrFileIsExist: 'Fail atau folder sudah wujud'
ErrFileUpload: '{{ .name }} gagal memuat naik fail {{ .detail }}' ErrFileUpload: '{{ .name }} gagal memuat naik fail {{ .detail }}'
ErrFileDownloadDir: 'Folder muat turun tidak disokong' 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' ErrSourcePathNotFound: 'Direktori sumber tidak wujud'
ErrFavoriteExist: 'Laluan ini telah digemari' ErrFavoriteExist: 'Laluan ini telah digemari'
ErrInvalidChar: 'Aksara haram tidak dibenarkan' ErrInvalidChar: 'Aksara haram tidak dibenarkan'
ErrPathNotDelete: 'Direktori yang dipilih tidak boleh dipadamkan' ErrPathNotDelete: 'Direktori yang dipilih tidak boleh dipadamkan'
ErrLogFileTooLarge: "Fail log melebihi 500MB dan tidak boleh dibuka" ErrLogFileToLarge: 'Fail log melebihi 500MB dan tidak boleh dibuka'
FileDropFailed: "Gagal membersihkan fail {{ .name }}: {{ .err }}" FileDropFailed: 'Gagal membersihkan fail {{ .name }}: {{ .err }}'
FileDropSuccess: "Berjaya membersihkan fail {{ .name }}, {{ .count }} fail dibersihkan, {{ .size }} ruang cakera dibebaskan" FileDropSuccess: 'Berjaya membersihkan fail {{ .name }}, {{ .count }} fail dibersihkan, {{ .size }} ruang cakera dibebaskan'
FileDropSum: "Pembersihan fail selesai, sejumlah {{ .count }} fail dibersihkan, sejumlah {{ .size }} ruang cakera dibebaskan" FileDropSum: 'Pembersihan fail selesai, sejumlah {{ .count }} fail dibersihkan, sejumlah {{ .size }} ruang cakera dibebaskan'
ErrBadDecrypt: "Kata laluan penyahsulitan pakej termampat salah, penyahmampatan gagal, sila periksa dan cuba lagi!" ErrBadDecrypt: 'Kata laluan penyahsulitan pakej termampat salah, penyahmampatan gagal, sila periksa dan cuba lagi'
#laman web
ErrAliasIsExist: 'Alias sudah wujud' ErrAliasIsExist: 'Alias sudah wujud'
ErrBackupMatch: 'Fail sandaran tidak sepadan dengan beberapa data tapak web semasa {{ .detail }}' ErrBackupMatch: 'Fail sandaran tidak sepadan dengan beberapa data tapak web semasa {{ .detail }}'
ErrBackupExist: 'Bahagian sepadan data sumber dalam fail sandaran tidak wujud {{ .detail }}' ErrBackupExist: 'Bahagian sepadan data sumber dalam fail sandaran tidak wujud {{ .detail }}'
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' 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 }}]' ErrDomainIsUsed: 'Nama domain telah digunakan oleh tapak web [{{ .name }}]'
ErrDomainFormat: 'Format nama domain {{ .name }} tidak betul' ErrDomainFormat: 'Format nama domain {{ .name }} tidak betul'
@@ -155,11 +137,11 @@ ErrDefaultAlias: 'lalai ialah kod simpanan, sila gunakan kod lain'
ErrParentWebsite: 'Anda perlu memadamkan subtapak {{ .name }} dahulu' ErrParentWebsite: 'Anda perlu memadamkan subtapak {{ .name }} dahulu'
ErrBuildDirNotFound: 'Direktori binaan tidak wujud' ErrBuildDirNotFound: 'Direktori binaan tidak wujud'
ErrImageNotExist: 'Imej persekitaran operasi {{ .name }} tidak wujud, sila edit semula persekitaran pengendalian' ErrImageNotExist: 'Imej persekitaran operasi {{ .name }} tidak wujud, sila edit semula persekitaran pengendalian'
ErrProxyIsUsed: "Pengimbang beban telah digunakan oleh pengganti terbalik, tidak boleh dipadamkan" ErrProxyIsUsed: 'Pengimbang beban telah digunakan oleh pengganti terbalik, tidak boleh dipadamkan'
ErrSSLValid: 'Fail sijil bermasalah, sila periksa status sijil!' ErrSSLValid: 'Fail sijil bermasalah, sila periksa status sijil'
ErrWebsiteDir: "Sila pilih direktori dalam direktori laman web." ErrWebsiteDir: 'Sila pilih direktori dalam direktori laman web.'
ErrComposerFileNotFound: "Fail composer.json tidak wujud" ErrComposerFileNotFound: 'Fail composer.json tidak wujud'
ErrRuntimeNoPort: "Persekitaran runtime tidak diset dengan port, sila edit persekitaran runtime terlebih dahulu." ErrRuntimeNoPort: 'Persekitaran runtime tidak diset dengan port, sila edit persekitaran runtime terlebih dahulu.'
Status: 'Status' Status: 'Status'
start: 'Mulakan' start: 'Mulakan'
stop: 'Berhenti' stop: 'Berhenti'
@@ -169,27 +151,25 @@ pause: 'Jeda'
unpause: 'Sambung Semula' unpause: 'Sambung Semula'
remove: 'Padam' remove: 'Padam'
delete: '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' SSL: 'Sijil'
Set: 'Tetapan' Set: 'Tetapan'
#ssl
ErrSSLCannotDelete: 'Sijil {{ .name }} sedang digunakan oleh tapak web dan tidak boleh dipadamkan' ErrSSLCannotDelete: 'Sijil {{ .name }} sedang digunakan oleh tapak web dan tidak boleh dipadamkan'
ErrAccountCannotDelete: 'Akaun dikaitkan dengan sijil dan tidak boleh dipadamkan' ErrAccountCannotDelete: 'Akaun dikaitkan dengan sijil dan tidak boleh dipadamkan'
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' ErrEmailIsExist: 'Peti mel sudah wujud'
ErrSSLKeyNotFound: 'Fail kunci peribadi tidak wujud' ErrSSLKeyNotFound: 'Fail kunci peribadi tidak wujud'
ErrSSLCertificateNotFound: 'Fail sijil tidak wujud' ErrSSLCertificateNotFound: 'Fail sijil tidak wujud'
ErrSSLKeyFormat: 'Pengesahan fail kunci peribadi gagal' ErrSSLKeyFormat: 'Pengesahan fail kunci peribadi gagal'
ErrSSLCertificateFormat: 'Format fail sijil tidak betul, sila gunakan format pem' 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' 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' dnsAccount: 'DNS Auto'
dnsManual: 'Manual DNS' dnsManual: 'Manual DNS'
http: 'HTTP' http: 'HTTP'
ApplySSLFailed: 'Permohonan untuk sijil [{{ .domain }}] gagal, {{ .detail }} ' ApplySSLFailed: 'Permohonan untuk sijil [{{ .domain }}] gagal, {{ .detail }}'
ApplySSLSuccess: 'Berjaya memohon sijil [{{ .domain }}]! ! ' ApplySSLSuccess: 'Berjaya memohon sijil [{{ .domain }}]'
DNSAccountName: 'Akaun DNS [{{ .name }}] vendor [{{ .type }}]' DNSAccountName: 'Akaun DNS [{{ .name }}] vendor [{{ .type }}]'
PushDirLog: 'Sijil ditolak ke direktori [{{ .path }}] {{ .status }}' PushDirLog: 'Sijil ditolak ke direktori [{{ .path }}] {{ .status }}'
ErrDeleteCAWithSSL: 'Organisasi semasa mempunyai sijil yang telah dikeluarkan dan tidak boleh dipadamkan.' ErrDeleteCAWithSSL: 'Organisasi semasa mempunyai sijil yang telah dikeluarkan dan tidak boleh dipadamkan.'
@@ -204,94 +184,79 @@ ExecShellSuccess: 'Pelaksanaan skrip berjaya'
StartUpdateSystemSSL: 'Mula mengemas kini sijil sistem' StartUpdateSystemSSL: 'Mula mengemas kini sijil sistem'
UpdateSystemSSLSuccess: 'Berjaya kemas kini sijil sistem' UpdateSystemSSLSuccess: 'Berjaya kemas kini sijil sistem'
ErrWildcardDomain: 'Tidak dapat memohon sijil nama domain kad bebas dalam mod HTTP' 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." ErrApplySSLCanNotDelete: 'Sertifikat {{ .name }} yang sedang diajukan tidak dapat dihapus, sila cuba lagi kemudian.'
StartPushSSLToNode: 'Mula menolak sijil ke nod'
#mysql PushSSLToNodeFailed: 'Gagal menolak sijil ke nod: {{ .err }}'
PushSSLToNodeSuccess: 'Berjaya menolak sijil ke nod'
ErrUserIsExist: 'Pengguna semasa sudah wujud, sila masukkan semula' ErrUserIsExist: 'Pengguna semasa sudah wujud, sila masukkan semula'
ErrDatabaseIsExist: 'Pangkalan data semasa sudah wujud, sila masukkan semula' ErrDatabaseIsExist: 'Pangkalan data semasa sudah wujud, sila masukkan semula'
ErrExecTimeOut: 'Pelaksanaan SQL tamat masa, sila semak pangkalan data' ErrExecTimeOut: 'Pelaksanaan SQL tamat masa, sila semak pangkalan data'
ErrRemoteExist: 'Pangkalan data jauh sudah wujud dengan nama ini, sila ubah suainya dan cuba lagi' 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' 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..." RemoteBackup: 'Untuk menyandarkan pangkalan data jauh, perkhidmatan pangkalan data bekas tempatan perlu dimulakan terlebih dahulu menggunakan imej {{ .name }}, sila tunggu...'
RemoteRecover: "Untuk memulihkan pangkalan data jauh, perkhidmatan pangkalan data bekas tempatan perlu dimulakan terlebih dahulu menggunakan imej {{ .name }}, sila tunggu..." RemoteRecover: 'Untuk memulihkan pangkalan data jauh, perkhidmatan pangkalan data bekas tempatan perlu dimulakan terlebih dahulu menggunakan imej {{ .name }}, sila tunggu...'
Arg: "Hujah" Arg: 'Hujah'
#redis
ErrTypeOfRedis: 'Jenis fail pemulihan tidak sepadan dengan kaedah kegigihan semasa, sila ubah suai dan cuba lagi' ErrTypeOfRedis: 'Jenis fail pemulihan tidak sepadan dengan kaedah kegigihan semasa, sila ubah suai dan cuba lagi'
ErrInUsed: '{{ .detail }} sedang digunakan dan tidak boleh dipadam'
#bekas ErrObjectInUsed: 'Objek ini sedang digunakan dan tidak boleh dipadam'
ErrInUsed: "{{ .detail }} sedang digunakan dan tidak boleh dipadam!" ErrObjectBeDependent: 'Imej ini digantungkan oleh imej lain dan tidak boleh dipadam'
ErrObjectInUsed: "Objek ini sedang digunakan dan tidak boleh dipadam!" ErrPortRules: 'Nombor port tidak sepadan, sila masukkan semula'
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' 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 }}" PruneHelper: 'Pembersihan ini {{ .name }} membebaskan ruang cakera {{ .size }}'
ImageRemoveHelper: "Padam imej {{ .name }}, membebaskan {{ .size }} ruang cakera" ImageRemoveHelper: 'Padam imej {{ .name }}, membebaskan {{ .size }} ruang cakera'
BuildCache: "Cache binaan" BuildCache: 'Cache binaan'
Volume: "Jilid storan" Volume: 'Jilid storan'
Network: "Rangkaian" Network: 'Rangkaian'
PruneStart: "Pembersihan sedang dijalankan, sila tunggu..." PruneStart: 'Pembersihan sedang dijalankan, sila tunggu...'
ErrFileNotExist: 'Fail {{ .detail }} tidak wujud Sila semak integriti fail sumber'
#masa berjalan
ErrFileNotExist: 'Fail {{ .detail }} tidak wujud! Sila semak integriti fail sumber!'
ErrImageBuildErr: 'Pembinaan imej gagal' ErrImageBuildErr: 'Pembinaan imej gagal'
ErrImageExist: "Imej sudah wujud! Sila ubah nama imej." ErrImageExist: 'Imej sudah wujud Sila ubah nama imej.'
ErrDelWithWebsite: 'Persekitaran pengendalian sudah dikaitkan dengan tapak web dan tidak boleh dipadamkan' ErrDelWithWebsite: 'Persekitaran pengendalian sudah dikaitkan dengan tapak web dan tidak boleh dipadamkan'
ErrRuntimeStart: 'Permulaan gagal' ErrRuntimeStart: 'Permulaan gagal'
ErrPackageJsonNotFound: 'fail package.json tidak wujud' ErrPackageJsonNotFound: 'fail package.json tidak wujud'
ErrScriptsNotFound: 'Item konfigurasi skrip tidak ditemui dalam package.json' ErrScriptsNotFound: 'Item konfigurasi skrip tidak ditemui dalam package.json'
ErrContainerNameNotFound: 'Tidak dapat mendapatkan nama kontena, sila semak fail .env' 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' ErrNodeModulesNotFound: 'Folder node_modules tidak wujud Sila edit persekitaran masa jalan atau tunggu persekitaran masa jalan berjaya dimulakan'
ErrContainerNameIsNull: 'Nama kontena tidak wujud' ErrContainerNameIsNull: 'Nama kontena tidak wujud'
ErrPHPPortIsDefault: "Порт 9000 является портом по умолчанию, пожалуйста, измените и попробуйте снова" ErrPHPPortIsDefault: 'Порт 9000 является портом по умолчанию, пожалуйста, измените и попробуйте снова'
ErrPHPRuntimePortFailed: "Порт {{ .name }} уже используется текущей средой выполнения, пожалуйста, измените и попробуйте снова" ErrPHPRuntimePortFailed: 'Порт {{ .name }} уже используется текущей средой выполнения, пожалуйста, измените и попробуйте снова'
#alat
ErrConfigNotFound: 'Fail konfigurasi tidak wujud' ErrConfigNotFound: 'Fail konfigurasi tidak wujud'
ErrConfigParse: 'Format fail konfigurasi tidak betul' ErrConfigParse: 'Format fail konfigurasi tidak betul'
ErrConfigIsNull: 'Fail konfigurasi tidak boleh kosong' ErrConfigIsNull: 'Fail konfigurasi tidak boleh kosong'
ErrConfigDirNotFound: 'Direktori berjalan tidak wujud' ErrConfigDirNotFound: 'Direktori berjalan tidak wujud'
ErrConfigAlreadyExist: 'Fail konfigurasi dengan nama yang sama sudah wujud' ErrConfigAlreadyExist: 'Fail konfigurasi dengan nama yang sama sudah wujud'
ErrUserFindErr: 'Pengguna {{ .name }} carian gagal {{ .err }}' ErrUserFindErr: 'Pengguna {{ .name }} carian gagal {{ .err }}'
#cronjob
CutWebsiteLogSuccess: '{{ .name }} log tapak web berjaya dipotong, laluan sandaran {{ .path }}' CutWebsiteLogSuccess: '{{ .name }} log tapak web berjaya dipotong, laluan sandaran {{ .path }}'
HandleShell: 'Laksanakan skrip {{ .name }}' HandleShell: 'Laksanakan skrip {{ .name }}'
HandleCurl: "Akses URL {{ .name }}" HandleCurl: 'Akses URL {{ .name }}'
HandleNtpSync: 'Penyegerakan masa sistem' HandleNtpSync: 'Penyegerakan masa sistem'
HandleSystemClean: 'Pembersihan cache sistem' HandleSystemClean: 'Pembersihan cache sistem'
SystemLog: 'Log Sistem' SystemLog: 'Log Sistem'
CutWebsiteLog: 'Putar Log Laman Web' CutWebsiteLog: 'Putar Log Laman Web'
FileOrDir: 'Direktori / Fail' FileOrDir: 'Direktori / Fail'
UploadFile: 'Muat naik fail sandaran {{ .file }} ke {{ .backup }}' UploadFile: 'Muat naik fail sandaran {{ .file }} ke {{ .backup }}'
Upload: "Muat Naik" Upload: 'Muat Naik'
IgnoreBackupErr: "Sandaran gagal, ralat: {{ .detail }}, abaikan ralat ini..." IgnoreBackupErr: 'Sandaran gagal, ralat: {{ .detail }}, abaikan ralat ini...'
IgnoreUploadErr: "Muat naik gagal, ralat: {{ .detail }}, abaikan ralat ini..." IgnoreUploadErr: 'Muat naik gagal, ralat: {{ .detail }}, abaikan ralat ini...'
LoadBackupFailed: "Gagal mendapatkan sambungan akaun sandaran, ralat: {{ .detail }}" LoadBackupFailed: 'Gagal mendapatkan sambungan akaun sandaran, ralat: {{ .detail }}'
InExecuting: "Tugas semasa sedang dilaksanakan, jangan ulangi pelaksanaan!" InExecuting: 'Tugas semasa sedang dilaksanakan, jangan ulangi pelaksanaan'
NoSuchResource: "Tiada kandungan sandaran ditemui dalam pangkalan data, dilangkau..." NoSuchResource: 'Tiada kandungan sandaran ditemui dalam pangkalan data, dilangkau...'
CleanLog: "Bersihkan log" CleanLog: 'Bersihkan log'
CleanLogByName: "Bersihkan log {{.name}}" CleanLogByName: 'Bersihkan log {{ .name }}'
WafIpGroupNotFound: "Kumpulan IP WAF tidak ditemui. Sila pergi ke [Ciri Lanjutan - WAF - Senarai Hitam/Putih - Kumpulan IP] untuk menambah kumpulan IP melalui kaedah muat turun jauh." WafIpGroupNotFound: 'Kumpulan IP WAF tidak ditemui. Sila pergi ke [Ciri Lanjutan - WAF - Senarai Hitam/Putih - Kumpulan IP] untuk menambah kumpulan IP melalui kaedah muat turun jauh.'
ErrNotExistUser: 'Pengguna semasa tidak wujud, sila ubah suai dan cuba lagi'
#kotak alat ErrBanAction: 'Tetapan gagal. Perkhidmatan {{ .name }} semasa tidak tersedia. Sila semak dan cuba lagi'
ErrNotExistUser: 'Pengguna semasa tidak wujud, sila ubah suai dan cuba lagi!' ErrClamdscanNotFound: 'Arahan clamdscan tidak dikesan, sila rujuk dokumentasi untuk memasangnya'
ErrBanAction: 'Tetapan gagal. Perkhidmatan {{ .name }} semasa tidak tersedia. Sila semak dan cuba lagi!' TaskSwapSet: 'Tetapkan Swap'
ErrClamdscanNotFound: 'Arahan clamdscan tidak dikesan, sila rujuk dokumentasi untuk memasangnya!' SetSwap: 'Tetapkan Swap {{ .path }} - {{ .size }}'
TaskSwapSet: "Tetapkan Swap" CreateSwap: 'Buat Fail Swap'
SetSwap: "Tetapkan Swap {{ .path }} - {{ .size }}" FormatSwap: 'Format Fail Swap'
CreateSwap: "Buat Fail Swap" EnableSwap: 'Dayakan Swap'
FormatSwap: "Format Fail Swap" CleanTamperSetting: 'Bersihkan tetapan perlindungan sejarah'
EnableSwap: "Dayakan Swap" SetTamperWithRules: 'Mulakan perlindungan direktori mengikut peraturan'
ProtectDir: 'Lindungi direktori {{ .name }}'
#tamper IgnoreFile: 'Lindungi fail {{ .name }}'
CleanTamperSetting: "Bersihkan tetapan perlindungan sejarah" TamperSetSuccessful: 'Tetapan perlindungan selesai, mula memantau direktori berikut:'
SetTamperWithRules: "Mulakan perlindungan direktori mengikut peraturan"
ProtectDir: "Lindungi direktori {{ .name }}"
IgnoreFile: "Lindungi fail {{ .name }}"
TamperSetSuccessful: "Tetapan perlindungan selesai, mula memantau direktori berikut:"
#waf
ErrScope: 'Mengubah suai konfigurasi ini tidak disokong' ErrScope: 'Mengubah suai konfigurasi ini tidak disokong'
ErrStateChange: 'Perubahan keadaan gagal' ErrStateChange: 'Perubahan keadaan gagal'
ErrRuleExist: 'Peraturan sudah wujud' ErrRuleExist: 'Peraturan sudah wujud'
@@ -299,7 +264,7 @@ ErrRuleNotExist: 'Peraturan tidak wujud'
ErrParseIP: 'Format IP salah' ErrParseIP: 'Format IP salah'
ErrDefaultIP: 'default ialah nama simpanan, sila tukar kepada nama lain' ErrDefaultIP: 'default ialah nama simpanan, sila tukar kepada nama lain'
ErrGroupInUse: 'Kumpulan IP digunakan oleh senarai hitam/senarai putih dan tidak boleh dipadamkan' 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' ErrGroupExist: 'Nama kumpulan IP sudah wujud'
ErrIPRange: 'Julat IP salah' ErrIPRange: 'Julat IP salah'
ErrIPExist: 'IP sudah wujud' ErrIPExist: 'IP sudah wujud'
@@ -310,11 +275,11 @@ xss: 'XSS'
phpExec: 'Pelaksanaan skrip PHP' phpExec: 'Pelaksanaan skrip PHP'
oneWordTrojan: 'One Word Trojan' oneWordTrojan: 'One Word Trojan'
appFilter: 'Gunakan penapisan direktori berbahaya' appFilter: 'Gunakan penapisan direktori berbahaya'
webshell: 'Webshell' webShell: 'Webshell'
args: 'Peraturan parameter' args: 'Peraturan parameter'
protocolFilter: 'Penapisan protokol' protocolFilter: 'Penapisan protokol'
javaFileter: 'Penapis fail berbahaya Java' javaFilter: 'Penapis fail berbahaya Java'
Penapis pengimbas: 'Penapis pengimbas' scannerFilter: 'Penapis pengimbas'
escapeFilter: 'penapis melarikan diri' escapeFilter: 'penapis melarikan diri'
customRule: 'Peraturan tersuai' customRule: 'Peraturan tersuai'
httpMethod: 'Penapisan kaedah HTTP' httpMethod: 'Penapisan kaedah HTTP'
@@ -343,10 +308,9 @@ ErrDBNotExist: 'Pangkalan data tidak wujud'
allow: 'membenarkan' allow: 'membenarkan'
deny: 'menafikan' deny: 'menafikan'
OpenrestyNotFound: 'Openresty tidak dipasang' OpenrestyNotFound: 'Openresty tidak dipasang'
remoteIpIsNull: "Senarai IP kosong" remoteIpIsNull: 'Senarai IP kosong'
OpenrestyVersionErr: "Versi Openresty terlalu rendah, sila naik taraf Openresty ke 1.27.1.2-2-2-focal" 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'
#tugas
TaskStart: '{{ .name }} Task mula [MULA]' TaskStart: '{{ .name }} Task mula [MULA]'
TaskEnd: '{{ .name }} Task selesai [SELESAI]' TaskEnd: '{{ .name }} Task selesai [SELESAI]'
TaskFailed: 'tugas {{ .name }} gagal' TaskFailed: 'tugas {{ .name }} gagal'
@@ -362,7 +326,7 @@ TaskDelete: 'Padam'
TaskUpgrade: 'Naik taraf' TaskUpgrade: 'Naik taraf'
TaskUpdate: 'Kemas kini' TaskUpdate: 'Kemas kini'
TaskRestart: 'Mulakan semula' TaskRestart: 'Mulakan semula'
TaskProtect: "Lindungi" TaskProtect: 'Lindungi'
TaskBackup: 'Sandaran' TaskBackup: 'Sandaran'
TaskRecover: 'Pulihkan' TaskRecover: 'Pulihkan'
TaskRollback: 'Rollback' TaskRollback: 'Rollback'
@@ -370,10 +334,10 @@ TaskPull: 'Tarik'
TaskCommit: 'Komit' TaskCommit: 'Komit'
TaskBuild: 'Bina' TaskBuild: 'Bina'
TaskPush: 'Tolak' TaskPush: 'Tolak'
TaskClean: "Pembersihan" TaskClean: 'Pembersihan'
TaskHandle: 'Laksanakan' TaskHandle: 'Laksanakan'
TaskImport: "Import" TaskImport: 'Import'
TaskExport: "Eksport" TaskExport: 'Eksport'
Website: 'Laman web' Website: 'Laman web'
App: 'Aplikasi' App: 'Aplikasi'
Runtime: 'Persekitaran masa jalan' Runtime: 'Persekitaran masa jalan'
@@ -405,18 +369,12 @@ RuntimeExtension: 'Sambungan Persekitaran Runtime'
TaskIsExecuting: 'Tugas sedang berjalan' TaskIsExecuting: 'Tugas sedang berjalan'
CustomAppstore: 'Gudang aplikasi tersuai' CustomAppstore: 'Gudang aplikasi tersuai'
TaskExec: 'Laksanakan' TaskExec: 'Laksanakan'
TaskBatch: "Operasi Batch" TaskBatch: 'Operasi Batch'
FileConvert: 'Penukaran Format Fail' FileConvert: 'Penukaran Format Fail'
Clamscan: 'Imbas {{ .name }}'
# task - clam TaskScan: 'Imbas'
Clamscan: "Imbas {{ .name }}"
TaskScan: "Imbas"
# tugasan - ai
OllamaModelPull: 'Tarik model Ollama {{ .name }}' OllamaModelPull: 'Tarik model Ollama {{ .name }}'
OllamaModelSize: 'Dapatkan saiz model Ollama {{ .name }}' OllamaModelSize: 'Dapatkan saiz model Ollama {{ .name }}'
# gambar tugasan
Snapshot: 'Snapshot' Snapshot: 'Snapshot'
SnapDBInfo: 'Tulis maklumat pangkalan data 1Panel' SnapDBInfo: 'Tulis maklumat pangkalan data 1Panel'
SnapCopy: 'Salin fail & direktori {{ .name }}' SnapCopy: 'Salin fail & direktori {{ .name }}'
@@ -442,7 +400,6 @@ SnapCompressSize: 'Saiz fail syot kilat {{ .name }}'
SnapUpload: 'Muat naik fail syot kilat' SnapUpload: 'Muat naik fail syot kilat'
SnapUploadTo: 'Muat naik fail syot kilat ke {{ .name }}' SnapUploadTo: 'Muat naik fail syot kilat ke {{ .name }}'
SnapUploadRes: 'Muat naik fail syot kilat ke {{ .name }}' SnapUploadRes: 'Muat naik fail syot kilat ke {{ .name }}'
SnapshotRecover: 'Snapshot Restore' SnapshotRecover: 'Snapshot Restore'
RecoverDownload: 'Muat turun fail syot kilat' RecoverDownload: 'Muat turun fail syot kilat'
Download: 'Muat turun' Download: 'Muat turun'
@@ -450,10 +407,10 @@ RecoverDownloadAccount: 'Dapatkan syot kilat muat turun akaun sandaran {{ .name
RecoverDecompress: 'Nyahmampatkan fail termampat syot kilat' RecoverDecompress: 'Nyahmampatkan fail termampat syot kilat'
Decompress: 'Penyahmampatan' Decompress: 'Penyahmampatan'
BackupBeforeRecover: 'Sandarkan data berkaitan sistem sebelum syot kilat' BackupBeforeRecover: 'Sandarkan data berkaitan sistem sebelum syot kilat'
Readjson: 'Baca fail Json dalam petikan' ReadJson: 'Baca fail Json dalam petikan'
ReadjsonPath: 'Dapatkan laluan fail Json dalam petikan' ReadJsonPath: 'Dapatkan laluan fail Json dalam petikan'
ReadjsonContent: 'Baca fail Json' ReadJsonContent: 'Baca fail Json'
ReadjsonMarshal: 'Pemprosesan melarikan diri Json' ReadJsonMarshal: 'Pemprosesan melarikan diri Json'
RecoverApp: 'Pulihkan apl yang dipasang' RecoverApp: 'Pulihkan apl yang dipasang'
RecoverWebsite: 'Pulihkan direktori tapak web' RecoverWebsite: 'Pulihkan direktori tapak web'
RecoverAppImage: 'Pulihkan sandaran imej syot kilat' RecoverAppImage: 'Pulihkan sandaran imej syot kilat'
@@ -467,9 +424,6 @@ RecoverDaemonJson: 'Pulihkan fail daemon.json konfigurasi bekas'
RecoverDBData: 'Pulihkan data pangkalan data' RecoverDBData: 'Pulihkan data pangkalan data'
RecoverBackups: 'Pulihkan direktori sandaran tempatan' RecoverBackups: 'Pulihkan direktori sandaran tempatan'
RecoverPanelData: 'Direktori data pemulihan' RecoverPanelData: 'Direktori data pemulihan'
# tugas - bekas
ContainerNewCliet: 'Memulakan Klien Docker'
ContainerImagePull: 'Tarik imej bekas {{ .name }}' ContainerImagePull: 'Tarik imej bekas {{ .name }}'
ContainerRemoveOld: 'Alih keluar bekas asal {{ .name }}' ContainerRemoveOld: 'Alih keluar bekas asal {{ .name }}'
ContainerImageCheck: 'Periksa sama ada imej ditarik seperti biasa' ContainerImageCheck: 'Periksa sama ada imej ditarik seperti biasa'
@@ -478,22 +432,13 @@ ContainerRecreate: 'Kemas kini kontena gagal, kini mula memulihkan bekas asal'
ContainerCreate: 'Buat bekas baharu {{ .name }}' ContainerCreate: 'Buat bekas baharu {{ .name }}'
ContainerCreateFailed: 'Penciptaan bekas gagal, padamkan bekas yang gagal' ContainerCreateFailed: 'Penciptaan bekas gagal, padamkan bekas yang gagal'
ContainerStartCheck: 'Periksa sama ada bekas telah dimulakan' ContainerStartCheck: 'Periksa sama ada bekas telah dimulakan'
# tugas - imej
ImageBuild: 'Membina Imej' ImageBuild: 'Membina Imej'
ImageBuildStdoutCheck: 'Menghuraikan kandungan output imej'
ImageBuildRes: 'Output binaan imej: {{ .name }}'
ImagePull: 'Tarik imej' ImagePull: 'Tarik imej'
ImageRepoAuthFromDB: 'Dapatkan maklumat pengesahan repositori daripada pangkalan data' ImageRepoAuthFromDB: 'Dapatkan maklumat pengesahan repositori daripada pangkalan data'
ImaegPullRes: 'Output tarik imej: {{ .name }}'
ImagePush: 'Tolak imej' ImagePush: 'Tolak imej'
ImageRenameTag: 'Ubah suai teg imej' ImageRenameTag: 'Ubah suai teg imej'
ImageNewTag: 'Teg imej baharu {{ .name }}' ImageNewTag: 'Teg imej baharu {{ .name }}'
ImaegPushRes: 'Output tolak imej: {{ .name }}'
ComposeCreate: 'Buat gubahan' ComposeCreate: 'Buat gubahan'
ComposeCreateRes: 'Karang cipta output: {{ .name }}'
# tugas - laman web
BackupNginxConfig: 'Fail konfigurasi OpenResty tapak web sandaran' BackupNginxConfig: 'Fail konfigurasi OpenResty tapak web sandaran'
CompressFileSuccess: 'Mampatkan direktori berjaya, dimampatkan ke {{ .name }}' CompressFileSuccess: 'Mampatkan direktori berjaya, dimampatkan ke {{ .name }}'
CompressDir: 'Direktori mampatan' CompressDir: 'Direktori mampatan'
@@ -504,40 +449,27 @@ websiteDir: 'Direktori Laman Web'
RecoverFailedStartRollBack: 'Pemulihan gagal, mulakan rollback' RecoverFailedStartRollBack: 'Pemulihan gagal, mulakan rollback'
AppBackupFileIncomplete: 'Fail sandaran tidak lengkap dan tidak mempunyai fail app.json atau app.tar.gz' AppBackupFileIncomplete: 'Fail sandaran tidak lengkap dan tidak mempunyai fail app.json atau app.tar.gz'
AppAttributesNotMatch: 'Jenis atau nama aplikasi tidak sepadan' AppAttributesNotMatch: 'Jenis atau nama aplikasi tidak sepadan'
ErrAlertSync: 'Ralat penyegerakan maklumat penggera, sila semak dan cuba lagi'
#alert ErrInstallExtension: 'Tugas pemasangan sudah sedang berjalan, silakan tunggu tugas selesai'
ErrAlert: 'Format mesej amaran tidak betul, sila semak dan cuba lagi!' PanelAlertTitle: 'Notifikasi Amaran Panel'
ErrAlertPush: 'Ralat dalam menolak maklumat amaran, sila semak dan cuba lagi!' TestAlertTitle: 'E-mel Ujian - Sahkan Sambungan E-mel'
ErrAlertSave: 'Ralat menyimpan maklumat penggera, sila semak dan cuba lagi!' TestAlert: 'Ini adalah e-mel ujian untuk mengesahkan konfigurasi penghantaran e-mel anda betul.'
ErrAlertSync: 'Ralat penyegerakan maklumat penggera, sila semak dan cuba lagi!' LicenseExpirationAlert: 'Panel {{ .node }}{{ .ip }} Anda, lesen akan tamat tempoh dalam {{ .day }} hari. Sila log masuk ke panel untuk butiran lanjut.'
ErrAlertRemote: 'Ralat jauh mesej penggera, sila semak dan cuba lagi!' 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.'
#task - runtime WebSiteAlert: 'Panel {{ .node }}{{ .ip }} Anda, {{ .num }} laman web akan tamat tempoh dalam {{ .day }} hari. Sila log masuk ke panel untuk butiran lanjut.'
ErrInstallExtension: "Tugas pemasangan sudah sedang berjalan, silakan tunggu tugas selesai" 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.'
# alert mail template ResourceAlert: 'Panel {{ .node }}{{ .ip }} Anda, kadar penggunaan purata {{ .name }} dalam tempoh {{ .time }} minit ialah {{ .used }}. Sila log masuk ke panel untuk butiran lanjut.'
PanelAlertTitle: "Notifikasi Amaran Panel" PanelVersionAlert: 'Panel {{ .node }}{{ .ip }} Anda, versi panel terkini tersedia untuk dinaik taraf. Sila log masuk ke panel untuk butiran lanjut.'
TestAlertTitle: "E-mel Ujian - Sahkan Sambungan E-mel" PanelPwdExpirationAlert: 'Panel {{ .node }}{{ .ip }} Anda, kata laluan panel akan tamat tempoh dalam {{ .day }} hari. Sila log masuk ke panel untuk butiran lanjut.'
TestAlert: "Ini adalah e-mel ujian untuk mengesahkan konfigurasi penghantaran e-mel anda betul." CommonAlert: 'Panel {{ .node }}{{ .ip }} Anda, {{ .msg }}. Sila log masuk ke panel untuk butiran lanjut.'
LicenseExpirationAlert: "Panel {{ .node }}{{ .ip }} Anda, lesen akan tamat tempoh dalam {{ .day }} hari. 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.'
CronJobFailedAlert: "Panel {{ .node }}{{ .ip }} Anda, tugas jadual {{ .name }} gagal dilaksanakan. 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.'
ClamAlert: "Panel {{ .node }}{{ .ip }} Anda, tugas imbasan virus mengesan {{ .num }} fail yang dijangkiti. 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.'
WebSiteAlert: "Panel {{ .node }}{{ .ip }} Anda, {{ .num }} laman web akan tamat tempoh dalam {{ .day }} hari. Sila log masuk ke panel untuk butiran lanjut." DeviceNotFound: 'Peranti {{ .name }} tidak ditemui'
SSLAlert: "Panel {{ .node }}{{ .ip }} Anda, {{ .num }} sijil SSL akan tamat tempoh dalam {{ .day }} hari. Sila log masuk ke panel untuk butiran lanjut." DeviceIsMounted: 'Peranti {{ .name }} telah dikaitkan, sila nyahkaitkan terlebih dahulu'
DiskUsedAlert: "Panel {{ .node }}{{ .ip }} Anda, penggunaan cakera {{ .name }} telah mencapai {{ .used }}. Sila log masuk ke panel untuk butiran lanjut." PartitionDiskErr: 'Gagal membahagikan, {{ .err }}'
ResourceAlert: "Panel {{ .node }}{{ .ip }} Anda, kadar penggunaan purata {{ .name }} dalam tempoh {{ .time }} minit ialah {{ .used }}. Sila log masuk ke panel untuk butiran lanjut." FormatDiskErr: 'Gagal memformat cakera, {{ .err }}'
PanelVersionAlert: "Panel {{ .node }}{{ .ip }} Anda, versi panel terkini tersedia untuk dinaik taraf. Sila log masuk ke panel untuk butiran lanjut." MountDiskErr: 'Gagal mengkaitkan cakera, {{ .err }}'
PanelPwdExpirationAlert: "Panel {{ .node }}{{ .ip }} Anda, kata laluan panel akan tamat tempoh dalam {{ .day }} hari. Sila log masuk ke panel untuk butiran lanjut." XfsNotFound: 'Sistem fail xfs tidak dikesan, sila pasang xfsprogs terlebih dahulu'
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"
+177 -245
View File
@@ -1,34 +1,28 @@
ErrInvalidParams: 'Erro de parâmetro de solicitação: {{ .detail }}' ErrInvalidParams: 'Requisição inválida: {{ .detail }}'
ErrTokenParse: 'Erro de geração de token: {{ .detail }}' ErrTokenParse: 'Erro de token: {{ .detail }}'
ErrInitialPassword: 'A senha original está incorreta' ErrInitialPassword: 'Senha original incorreta'
ErrInternalServer: 'Erro interno do servidor: {{ .detail }}' ErrInternalServer: 'Erro interno: {{ .detail }}'
ErrRecordExist: 'O registro já existe' ErrRecordExist: 'Registro já existe'
ErrRecordNotFound: 'Registro não encontrado' ErrRecordNotFound: 'Registro não encontrado'
ErrStructTransform: 'Falha na conversão de tipo: {{ .err }}' ErrStructTransform: 'Erro de conversão: {{ .err }}'
ErrNotLogin: 'Usuário não logado: {{ .detail }}' ErrNotLogin: 'Sem sessão: {{ .detail }}'
ErrPasswordExpired: 'A senha atual expirou: {{ .detail }}' ErrPasswordExpired: 'Senha expirada: {{ .detail }}'
ErrNotSupportType: 'O sistema não suporta o tipo atual: {{ .name }}' ErrNotSupportType: 'Tipo não suportado: {{ .name }}'
ErrProxy: 'Erro de solicitação, verifique o status do nó: {{ .detail }}' ErrProxy: 'Requisição falhou: {{ .detail }}'
ErrApiConfigStatusInvalid: 'O acesso à interface da API é proibido: {{ .detail }}' ErrApiConfigStatusInvalid: 'API desativada: {{ .detail }}'
ErrApiConfigKeyInvalid: 'Erro de chave da interface da API: {{ .detail }}' ErrApiConfigKeyInvalid: 'Chave API inválida: {{ .detail }}'
ErrApiConfigIPInvalid: 'O IP usado para chamar a interface da API não está na lista de permissões: {{ .detail }}' ErrApiConfigIPInvalid: 'IP sem permissão: {{ .detail }}'
ErrApiConfigDisable: 'Esta interface proíbe o uso de chamadas de interface de API: {{ .detail }}' ErrApiConfigDisable: 'API bloqueada: {{ .detail }}'
ErrApiConfigKeyTimeInvalid: 'Erro de registro de data e hora da interface da API: {{ .detail }}' ErrApiConfigKeyTimeInvalid: 'Timestamp inválido: {{ .detail }}'
StartPushSSLToNode: "Iniciando o envio do certificado para o nó" ErrShutDown: 'Comando parado manualmente'
PushSSLToNodeFailed: "Falha ao enviar o certificado para o nó: {{ .err }}" ErrMinQuickJump: 'Adicione pelo menos um atalho rápido'
PushSSLToNodeSuccess: "Certificado enviado com sucesso para o nó" ErrMaxQuickJump: 'Máximo 4 atalhos rápidos'
ErrShutDown: "Comando terminado manualmente!" ErrUsernameIsExist: 'Usuário já existe'
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'
ErrNameIsExist: 'Nome já existe' ErrNameIsExist: 'Nome já existe'
ErrDemoEnvironment: 'Servidor de demonstração, esta operação é proibida!' ErrDemoEnvironment: 'Indisponível em demo'
ErrCmdTimeout: 'Tempo limite de execução do comando expirou!' ErrCmdTimeout: 'Comando expirou'
ErrCmdIllegal: 'Há caracteres ilegais no comando de execução, modifique-o e tente novamente!' ErrCmdIllegal: 'Comando tem caracteres inválidos'
ErrPortExist: 'A porta {{ .port }} já está ocupada por {{ .type }} [{{ .name }}]' ErrPortExist: 'Porta {{ .port }} já ocupada por {{ .type }} [{{ .name }}]'
TYPE_APP: 'Aplicativo' TYPE_APP: 'Aplicativo'
TYPE_RUNTIME: 'Ambiente de tempo de execução' TYPE_RUNTIME: 'Ambiente de tempo de execução'
TYPE_DOMAIN: 'Nome de domínio' TYPE_DOMAIN: 'Nome de domínio'
@@ -39,45 +33,39 @@ Failed: 'Falhou'
SystemRestart: 'Tarefa interrompida devido à reinicialização do sistema' SystemRestart: 'Tarefa interrompida devido à reinicialização do sistema'
ErrGroupIsDefault: 'Grupo padrão, não pode ser excluído' ErrGroupIsDefault: 'Grupo padrão, não pode ser excluído'
ErrGroupIsInWebsiteUse: 'O grupo está sendo usado por outro site e não pode ser excluído.' ErrGroupIsInWebsiteUse: 'O grupo está sendo usado por outro site e não pode ser excluído.'
Decrypt: "Descriptografar" Decrypt: 'Descriptografar'
ErrAgentAccountBound: 'Conta vinculada a agente'
#agent ErrAgentAccountUnavailable: 'Conexão da conta indisponível: {{ .err }}'
ErrAgentAccountBound: 'Esta conta está vinculada a um agente e não pode ser excluída. Verifique e tente novamente!' ErrAgentProviderNotSupported: 'Provedor de agente não suportado'
ErrAgentAccountUnavailable: 'As informações de conexão da conta não estão disponíveis. Erro: {{ .err }}. Verifique e tente novamente!' ErrAgentAccountRequired: 'Selecione uma conta de agente primeiro'
ErrAgentProviderNotSupported: 'Este provedor de agente não é suportado. Verifique e tente novamente!' ErrAgentAccountNotVerified: 'Conta de agente não verificada'
ErrAgentAccountRequired: 'Selecione uma conta de agente e tente novamente.' ErrAgentProviderMismatch: 'Provedor de agente diferente'
ErrAgentAccountNotVerified: 'A conta não foi verificada. Verifique e tente novamente!' ErrAgentBaseURLRequired: 'URL base obrigatória'
ErrAgentProviderMismatch: 'O provedor da conta não corresponde. Verifique e tente novamente!' ErrAgentApiKeyRequired: 'Chave API obrigatória'
ErrAgentBaseURLRequired: 'Base URL não pode estar vazio. Verifique e tente novamente!' ErrAgentComposeRequired: 'Conteúdo de compose obrigatório'
ErrAgentApiKeyRequired: 'API Key não pode estar vazio. Verifique e tente novamente!' ErrAgentIDRequired: 'ID do agente obrigatório'
ErrAgentComposeRequired: 'O conteúdo personalizado do compose não pode estar vazio. Verifique e tente novamente!' ErrAgentAccountIDRequired: 'ID da conta obrigatório'
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
Localhost: 'Máquina Local' Localhost: 'Máquina Local'
ErrBackupInUsed: 'A conta de backup foi usada na tarefa agendada e não pode ser excluída.' ErrBackupInUsed: 'Conta de backup em uso por tarefa'
ErrBackupCheck: 'Falha na conexão de teste da conta de backup {{ .err }}' ErrBackupCheck: 'Teste de conexão falhou: {{ .err }}'
ErrBackupLocalDelete: 'A exclusão da conta de backup do servidor local ainda não é suportada' ErrBackupLocalDelete: 'Não é permitido excluir contas locais'
ErrBackupLocalCreate: 'A criação de contas de backup do servidor local ainda não é suportada' ErrBackupLocalCreate: 'Não é permitido criar contas locais'
ErrPortInUsed: 'A porta {{ .detail }} já está ocupada'
#aplicativo
ErrPortInUsed: 'A porta {{ .detail }} já está ocupada!'
ErrAppLimit: 'O número de aplicativos instalados excedeu o limite' ErrAppLimit: 'O número de aplicativos instalados excedeu o limite'
ErrNotInstall: 'Aplicativo não instalado' ErrNotInstall: 'Aplicativo não instalado'
ErrPortInOtherApp: 'A porta {{ .port }} já está ocupada pelo aplicativo {{ .apps }}!' ErrPortInOtherApp: 'A porta {{ .port }} já está ocupada pelo aplicativo {{ .apps }}'
ErrDbUserNotValid: 'Banco de dados existente, nome de usuário e senha não correspondem!' 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! ' 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 }}' Err1PanelNetworkFailed: 'Falha na criação da rede de contêiner padrão {{ .detalhe }}'
ErrFileParse: 'Falha na análise do arquivo docker-compose do aplicativo!' 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' 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' 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' 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 }}' LocalAppVersionErr: '{{ .name }} sincronização da versão {{ .version }} falhou {{ .err }}'
ErrFileNotFound: 'arquivo {{ .name }} não existe' ErrFileNotFound: 'arquivo {{ .name }} não existe'
ErrFileParseApp: 'Falha na análise do arquivo {{ .name }} {{ .err }}' ErrFileParseApp: 'Falha na análise do arquivo {{ .name }} {{ .err }}'
ErrAppDirNull: 'A pasta da versão não existe' ErrAppDirNull: 'A pasta da versão não existe'
LocalAppErr: 'Falha na sincronização do aplicativo {{ .name }}! {{ .err }}' LocalAppErr: 'Falha na sincronização do aplicativo {{ .name }} {{ .err }}'
ErrContainerName: 'O nome do contêiner já existe' ErrContainerName: 'O nome do contêiner já existe'
ErrCreateHttpClient: 'Falha ao criar solicitação {{ .err }}' ErrCreateHttpClient: 'Falha ao criar solicitação {{ .err }}'
ErrHttpReqTimeOut: 'Tempo limite da solicitação esgotado {{ .err }}' ErrHttpReqTimeOut: 'Tempo limite da solicitação esgotado {{ .err }}'
@@ -85,69 +73,63 @@ ErrHttpReqFailed: 'Falha na solicitação {{ .err }}'
ErrNoSuchHost: 'Não foi possível encontrar o servidor solicitado {{ .err }}' ErrNoSuchHost: 'Não foi possível encontrar o servidor solicitado {{ .err }}'
ErrHttpReqNotFound: 'O recurso solicitado {{ .err }} não pôde ser encontrado' ErrHttpReqNotFound: 'O recurso solicitado {{ .err }} não pôde ser encontrado'
ErrContainerNotFound: '{{ .name }} container não existe' ErrContainerNotFound: '{{ .name }} container não existe'
ErrContainerMsg: 'O contêiner {{ .name }} está anormal. 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 }}' 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' ErrAppNameExist: 'O nome do aplicativo já existe'
AppStoreIsSyncing: 'A App Store está sincronizando, tente novamente mais tarde' AppStoreIsSyncing: 'A App Store está sincronizando mais tarde'
ErrGetCompose: 'Falha ao obter o arquivo docker-compose.yml! {{ .detail }}' ErrGetCompose: 'Falha ao obter o arquivo docker-compose.yml {{ .detail }}'
ErrAppWarn: 'Status anormal, verifique o log' ErrAppWarn: 'Status anormal, verifique o log'
ErrAppParamKey: 'O campo de parâmetro {{ .name }} está anormal' ErrAppParamKey: 'O campo de parâmetro {{ .name }} está anormal'
ErrAppUpgrade: 'Falha na atualização do aplicativo {{ .name }} {{ .err }}' ErrAppUpgrade: 'Falha na atualização do aplicativo {{ .name }} {{ .err }}'
AppRecover: 'Reverter aplicativo {{ .name }}' AppRecover: 'Reverter aplicativo {{ .name }}'
PullImageStart: 'Comece a extrair a imagem [{{ .name }}]' PullImageStart: 'Comece a extrair a imagem [{{ .name }}]'
PullImageSuccess: 'Imagem retirada com sucesso' PullImageSuccess: 'Imagem retirada com sucesso'
AppStoreIsLastVersion: 'A App Store já é a versão mais recente'
AppStoreSyncSuccess: 'Sincronização da App Store bem-sucedida' AppStoreSyncSuccess: 'Sincronização da App Store bem-sucedida'
SyncAppDetail: 'Sincronizar configuração do aplicativo' SyncAppDetail: 'Sincronizar configuração do aplicativo'
AppVersionNotMatch: 'o aplicativo {{ .name }} requer uma versão superior do 1Panel, ignorando a sincronização' 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' MoveSiteDirSuccess: 'Migração bem-sucedida do diretório do site'
DeleteRuntimePHP: 'Excluir tempo de execução do PHP' 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' 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' ErrAppIsDown: 'O status do aplicativo {{ .name }} é anormal, verifique'
ErrCustomApps: 'Há um aplicativo instalado, desinstale-o primeiro' ErrCustomApps: 'Há um aplicativo instalado, desinstale-o primeiro'
ErrCustomRuntimes: 'Há um ambiente de execução instalado, exclua-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" 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" 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" ErrDockerComposeCmdNotFound: 'O comando Docker Compose não existe, instale este comando na máquina host primeiro'
UseExistImage: 'Falha ao puxar a imagem, usando imagem existente' UseExistImage: 'A imagem já existe, usando imagem existente'
ErrDatabaseNotFound: 'O banco de dados {{ .name }} não existe'
#ssh ExportIP: 'IP de Login'
ExportIP: "IP de Login" ExportArea: 'Localização'
ExportArea: "Localização" ExportPort: 'Porta'
ExportPort: "Porta" ExportAuthMode: 'Método de Login'
ExportAuthMode: "Método de Login" ExportUser: 'Usuário'
ExportUser: "Usuário" ExportStatus: 'Status de Login'
ExportStatus: "Status de Login" ExportDate: 'Hora'
ExportDate: "Hora"
#arquivo
ErrFileCanNotRead: 'Este arquivo não suporta visualização' ErrFileCanNotRead: 'Este arquivo não suporta visualização'
ErrFileToLarge: 'O arquivo é maior que 10M e não pode ser aberto' ErrFileToLarge: 'O arquivo é maior que 10M e não pode ser aberto'
ErrPathNotFound: 'O diretório não existe' ErrPathNotFound: 'O diretório não existe'
ErrMovePathFailed: 'O caminho de destino não pode conter o caminho original!' ErrMovePathFailed: 'O caminho de destino não pode conter o caminho original'
ErrLinkPathNotFound: 'O caminho de destino não existe!' ErrLinkPathNotFound: 'O caminho de destino não existe'
ErrFileIsExist: 'O arquivo ou pasta já existe!' ErrFileIsExist: 'O arquivo ou pasta já existe'
ErrFileUpload: '{{ .name }} falhou ao carregar o arquivo {{ .detail }}' ErrFileUpload: '{{ .name }} falhou ao carregar o arquivo {{ .detail }}'
ErrFileDownloadDir: 'A pasta de download não é suportada' 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' ErrSourcePathNotFound: 'O diretório de origem não existe'
ErrFavoriteExist: 'Este caminho já foi favorito' ErrFavoriteExist: 'Este caminho já foi favorito'
ErrInvalidChar: 'Caracteres ilegais não são permitidos' ErrInvalidChar: 'Caracteres ilegais não são permitidos'
ErrPathNotDelete: 'O diretório selecionado não pode ser excluído' ErrPathNotDelete: 'O diretório selecionado não pode ser excluído'
ErrLogFileToLarge: "Fail log melebihi 500MB, tidak boleh dibuka" ErrLogFileToLarge: 'Fail log melebihi 500MB, tidak boleh dibuka'
FileDropFailed: "Falha ao limpar arquivo {{ .name }}: {{ .err }}" FileDropFailed: 'Falha ao limpar arquivo {{ .name }}: {{ .err }}'
FileDropSuccess: "Arquivo {{ .name }} limpo com sucesso, {{ .count }} arquivos removidos, {{ .size }} de espaço em disco liberado" FileDropSuccess: 'Arquivo {{ .name }} limpo com sucesso, {{ .count }} arquivos removidos, {{ .size }} de espaço em disco liberado'
FileDropSum: "Limpeza de arquivos concluída com sucesso, total de {{ .count }} arquivos removidos, total de {{ .size }} de espaço em disco liberado" FileDropSum: 'Limpeza de arquivos concluída com sucesso, total de {{ .count }} arquivos removidos, total de {{ .size }} de espaço em disco liberado'
ErrBadDecrypt: "Erro de senha de descriptografia do pacote compactado, descompactação falhou, verifique e tente novamente!" ErrBadDecrypt: 'Erro de senha de descriptografia do pacote compactado, descompactação falhou, verifique e'
#site
ErrAliasIsExist: 'Alias já existe' ErrAliasIsExist: 'Alias já existe'
ErrBackupMatch: 'O arquivo de backup não corresponde a alguns dados atuais do site {{ .detail }}' ErrBackupMatch: 'O arquivo de backup não corresponde a alguns dados atuais do site {{ .detail }}'
ErrBackupExist: 'A parte correspondente dos dados de origem no arquivo de backup não existe {{ .detail }}' ErrBackupExist: 'A parte correspondente dos dados de origem no arquivo de backup não existe {{ .detail }}'
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' 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 }}]' ErrDomainIsUsed: 'O nome de domínio já está sendo usado pelo site [{{ .name }}]'
ErrDomainFormat: 'o formato do nome de domínio {{ .name }} está incorreto' ErrDomainFormat: 'o formato do nome de domínio {{ .name }} está incorreto'
@@ -155,11 +137,11 @@ ErrDefaultAlias: 'padrão é um código reservado, use outro código'
ErrParentWebsite: 'Você precisa excluir o subsite {{ .name }} primeiro' ErrParentWebsite: 'Você precisa excluir o subsite {{ .name }} primeiro'
ErrBuildDirNotFound: 'O diretório de compilação não existe' 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' 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" 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!' 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." ErrWebsiteDir: ', selecione um diretório dentro do diretório do site.'
ErrComposerFileNotFound: "O arquivo composer.json não existe" 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." 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' Status: 'Status'
start: 'Iniciar' start: 'Iniciar'
stop: 'Parar' stop: 'Parar'
@@ -169,14 +151,12 @@ pause: 'Pausar'
unpause: 'Retomar' unpause: 'Retomar'
remove: 'Excluir' remove: 'Excluir'
delete: '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' SSL: 'Certificado'
Set: 'Configurações' Set: 'Configurações'
#ssl
ErrSSLCannotDelete: 'O certificado {{ .name }} está sendo usado por um site e não pode ser excluído' ErrSSLCannotDelete: 'O certificado {{ .name }} está sendo usado por um site e não pode ser excluído'
ErrAccountCannotDelete: 'A conta está associada a um certificado e não pode ser excluída' ErrAccountCannotDelete: 'A conta está associada a um certificado e não pode ser excluída'
ErrSSLApply: 'Renovação do certificado 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' ErrEmailIsExist: 'A caixa de correio já existe'
ErrSSLKeyNotFound: 'O arquivo de chave privada não existe' ErrSSLKeyNotFound: 'O arquivo de chave privada não existe'
ErrSSLCertificateNotFound: 'O arquivo de certificado não existe' ErrSSLCertificateNotFound: 'O arquivo de certificado não existe'
@@ -188,8 +168,8 @@ ApplySSLStart: 'Comece a solicitar um certificado, nome de domínio [{{ .domain
dnsAccount: 'DNS Automático' dnsAccount: 'DNS Automático'
dnsManual: 'Manual DNS' dnsManual: 'Manual DNS'
http: 'HTTP' http: 'HTTP'
ApplySSLFailed: 'Falha na solicitação de certificado [{{ .domain }}], {{ .detail }} ' ApplySSLFailed: 'Falha na solicitação de certificado [{{ .domain }}], {{ .detail }}'
ApplySSLSuccess: 'Solicitação de certificado [{{ .domain }}] realizada com sucesso! ! ' ApplySSLSuccess: 'Solicitação de certificado [{{ .domain }}] realizada com sucesso'
DNSAccountName: 'Conta DNS [{{ .name }}] fornecedor [{{ .type }}]' DNSAccountName: 'Conta DNS [{{ .name }}] fornecedor [{{ .type }}]'
PushDirLog: 'Certificado enviado para o diretório [{{ .path }}] {{ .status }}' 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.' ErrDeleteCAWithSSL: 'A organização atual tem um certificado que foi emitido e não pode ser excluído.'
@@ -204,94 +184,79 @@ ExecShellSuccess: 'Execução do script bem-sucedida'
StartUpdateSystemSSL: 'Iniciar atualização do certificado do sistema' StartUpdateSystemSSL: 'Iniciar atualização do certificado do sistema'
UpdateSystemSSLSuccess: 'Atualizar certificado do sistema com sucesso' UpdateSystemSSLSuccess: 'Atualizar certificado do sistema com sucesso'
ErrWildcardDomain: 'Não é possível solicitar certificado de nome de domínio curinga no modo HTTP' 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." 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ó'
#mysql 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' ErrUserIsExist: 'O usuário atual já existe, digite novamente'
ErrDatabaseIsExist: 'O banco de dados atual já existe, digite novamente' ErrDatabaseIsExist: 'O banco de dados atual já existe, digite novamente'
ErrExecTimeOut: 'Tempo limite de execução do SQL expirou, verifique o banco de dados' ErrExecTimeOut: 'Tempo limite de execução do SQL expirou, verifique o banco de dados'
ErrRemoteExist: 'O banco de dados remoto já existe com este nome, modifique-o e tente novamente' 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 tente novamente' 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 }}, por favor aguarde..." RemoteBackup: 'Para fazer backup do banco de dados remoto, o serviço de banco de dados do contêiner local precisa ser iniciado primeiro usando a imagem {{ .name }} aguarde...'
RemoteRecover: "Para restaurar o banco de dados remoto, o serviço de banco de dados do contêiner local precisa ser iniciado primeiro usando a imagem {{ .name }}, 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 }} aguarde...'
Arg: "Argumento" Arg: 'Argumento'
ErrTypeOfRedis: 'O tipo de arquivo de recuperação não corresponde ao método de persistência atual, modifique-o e'
#redis ErrInUsed: '{{ .detail }} está em uso e não pode ser excluído'
ErrTypeOfRedis: 'O tipo de arquivo de recuperação não corresponde ao método de persistência atual, modifique-o e tente novamente' 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'
#recipiente ErrPortRules: 'O número da porta não corresponde, digite novamente'
ErrInUsed: "{{ .detail }} está em uso e não pode ser excluído!" ErrPgImagePull: 'Tempo limite para extração de imagem. Configure a aceleração de imagem ou extraia manualmente a imagem {{ .name }} e'
ErrObjectInUsed: "Este objeto está em uso e não pode ser excluído!" PruneHelper: 'Esta limpeza {{ .name }} liberou espaço em disco {{ .size }}'
ErrObjectBeDependent: "Esta imagem é dependida por outras imagens e não pode ser excluída!" ImageRemoveHelper: 'Excluída a imagem {{ .name }}, liberando {{ .size }} de espaço em disco'
ErrPortRules: 'O número da porta não corresponde, digite novamente!' BuildCache: 'Cache de construção'
ErrPgImagePull: 'Tempo limite para extração de imagem. Configure a aceleração de imagem ou extraia manualmente a imagem {{ .name }} e tente novamente' Volume: 'Volume de armazenamento'
PruneHelper: "Esta limpeza {{ .name }} liberou espaço em disco {{ .size }}" Network: 'Rede'
ImageRemoveHelper: "Excluída a imagem {{ .name }}, liberando {{ .size }} de espaço em disco" PruneStart: 'Limpando em andamento aguarde...'
BuildCache: "Cache de construção" ErrFileNotExist: 'O arquivo {{ .detail }} não existe Verifique a integridade do arquivo de origem'
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!'
ErrImageBuildErr: 'Falha na criação da imagem' 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' ErrDelWithWebsite: 'O ambiente operacional já está associado a um site e não pode ser excluído'
ErrRuntimeStart: 'Falha na inicialização' ErrRuntimeStart: 'Falha na inicialização'
ErrPackageJsonNotFound: 'o arquivo package.json não existe' ErrPackageJsonNotFound: 'o arquivo package.json não existe'
ErrScriptsNotFound: 'O item de configuração de scripts não foi encontrado em package.json' 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' 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' 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' ErrContainerNameIsNull: 'O nome do contêiner não existe'
ErrPHPPortIsDefault: "Port 9000 adalah port lalai, sila ubah dan cuba lagi" 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" ErrPHPRuntimePortFailed: 'Port {{ .name }} telah digunakan oleh persekitaran runtime semasa, sila ubah dan cuba lagi'
#ferramenta
ErrConfigNotFound: 'O arquivo de configuração não existe' ErrConfigNotFound: 'O arquivo de configuração não existe'
ErrConfigParse: 'O formato do arquivo de configuração está incorreto' ErrConfigParse: 'O formato do arquivo de configuração está incorreto'
ErrConfigIsNull: 'O arquivo de configuração não pode estar vazio' ErrConfigIsNull: 'O arquivo de configuração não pode estar vazio'
ErrConfigDirNotFound: 'O diretório de execução não existe' ErrConfigDirNotFound: 'O diretório de execução não existe'
ErrConfigAlreadyExist: 'Um arquivo de configuração com o mesmo nome já existe' ErrConfigAlreadyExist: 'Um arquivo de configuração com o mesmo nome já existe'
ErrUserFindErr: 'Falha na pesquisa do usuário {{ .name }} {{ .err }}' ErrUserFindErr: 'Falha na pesquisa do usuário {{ .name }} {{ .err }}'
#cronjob
CutWebsiteLogSuccess: '{{ .name }} registro do site cortado com sucesso, caminho de backup {{ .path }}' CutWebsiteLogSuccess: '{{ .name }} registro do site cortado com sucesso, caminho de backup {{ .path }}'
HandleShell: 'Executar script {{ .name }}' HandleShell: 'Executar script {{ .name }}'
HandleCurl: "Acessar URL {{ .name }}" HandleCurl: 'Acessar URL {{ .name }}'
HandleNtpSync: 'Sincronização de hora do sistema' HandleNtpSync: 'Sincronização de hora do sistema'
HandleSystemClean: 'Limpeza de cache do sistema' HandleSystemClean: 'Limpeza de cache do sistema'
SystemLog: 'Log do Sistema' SystemLog: 'Log do Sistema'
CutWebsiteLog: 'Rotacionar Log do Website' CutWebsiteLog: 'Rotacionar Log do Website'
FileOrDir: 'Diretório / Arquivo' FileOrDir: 'Diretório / Arquivo'
UploadFile: 'Enviando arquivo de backup {{ .file }} para {{ .backup }}' UploadFile: 'Enviando arquivo de backup {{ .file }} para {{ .backup }}'
Upload: "Enviar" Upload: 'Enviar'
IgnoreBackupErr: "Backup falhou, erro: {{ .detail }}, ignorando este erro..." IgnoreBackupErr: 'Backup falhou, erro: {{ .detail }}, ignorando este erro...'
IgnoreUploadErr: "Upload 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 }}" 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!" 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..." NoSuchResource: 'Nenhum conteúdo de backup encontrado no banco de dados, ignorando...'
CleanLog: "Limpar log" CleanLog: 'Limpar log'
CleanLogByName: "Limpar log de {{.name}}" CleanLogByName: 'Limpar log de {{ .name }}'
WafIpGroupNotFound: "Grupo de IP do WAF não encontrado. 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." 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'
#caixa de ferramentas ErrBanAction: 'Falha na configuração. O serviço atual {{ .name }} não está disponível. Verifique e'
ErrNotExistUser: 'O usuário atual não existe, modifique e tente novamente!' ErrClamdscanNotFound: 'O comando clamdscan não foi detectado, consulte a documentação para instalá-lo'
ErrBanAction: 'Falha na configuração. O serviço atual {{ .name }} não está disponível. Verifique e tente novamente!' TaskSwapSet: 'Configurar Swap'
ErrClamdscanNotFound: 'O comando clamdscan não foi detectado, consulte a documentação para instalá-lo!' SetSwap: 'Configurar Swap {{ .path }} - {{ .size }}'
TaskSwapSet: "Configurar Swap" CreateSwap: 'Criar Arquivo Swap'
SetSwap: "Configurar Swap {{ .path }} - {{ .size }}" FormatSwap: 'Formatar Arquivo Swap'
CreateSwap: "Criar Arquivo Swap" EnableSwap: 'Ativar Swap'
FormatSwap: "Formatar Arquivo Swap" CleanTamperSetting: 'Limpar configurações de proteção históricas'
EnableSwap: "Ativar Swap" SetTamperWithRules: 'Iniciar proteção de diretório de acordo com as regras'
ProtectDir: 'Proteger diretório {{ .name }}'
#tamper IgnoreFile: 'Proteger arquivo {{ .name }}'
CleanTamperSetting: "Limpar configurações de proteção históricas" TamperSetSuccessful: 'Configurações de proteção concluídas, iniciando monitoramento dos seguintes diretórios:'
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
ErrScope: 'A modificação desta configuração não é suportada' ErrScope: 'A modificação desta configuração não é suportada'
ErrStateChange: 'Falha na alteração de estado' ErrStateChange: 'Falha na alteração de estado'
ErrRuleExist: 'A regra já existe' ErrRuleExist: 'A regra já existe'
@@ -299,7 +264,7 @@ ErrRuleNotExist: 'A regra não existe'
ErrParseIP: 'Formato de IP errado' ErrParseIP: 'Formato de IP errado'
ErrDefaultIP: 'padrão é um nome reservado, altere-o para outro nome' 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' 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' ErrGroupExist: 'O nome do grupo IP já existe'
ErrIPRange: 'Intervalo de IP errado' ErrIPRange: 'Intervalo de IP errado'
ErrIPExist: 'IP já existe' ErrIPExist: 'IP já existe'
@@ -310,10 +275,10 @@ xss: 'XSS'
phpExec: 'Execução de script PHP' phpExec: 'Execução de script PHP'
oneWordTrojan: 'Cavalo de Tróia de Uma Palavra' oneWordTrojan: 'Cavalo de Tróia de Uma Palavra'
appFilter: 'Aplicar filtragem de diretório perigosa' appFilter: 'Aplicar filtragem de diretório perigosa'
webshell: 'Webshell' webShell: 'Webshell'
args: 'Regras de parâmetros' args: 'Regras de parâmetros'
protocolFilter: 'Filtragem de protocolo' protocolFilter: 'Filtragem de protocolo'
javaFileter: 'Filtro de arquivo perigoso Java' javaFilter: 'Filtro de arquivo perigoso Java'
scannerFilter: 'Filtro do scanner' scannerFilter: 'Filtro do scanner'
escapeFilter: 'filtro de escape' escapeFilter: 'filtro de escape'
customRule: 'Regra personalizada' customRule: 'Regra personalizada'
@@ -343,10 +308,9 @@ ErrDBNotExist: 'O banco de dados não existe'
allow: 'permitir' allow: 'permitir'
deny: 'negar' deny: 'negar'
OpenrestyNotFound: 'Openresty não está instalado' OpenrestyNotFound: 'Openresty não está instalado'
remoteIpIsNull: "A lista de IP está vazia" remoteIpIsNull: 'A lista de IP está vazia'
OpenrestyVersionErr: "A versão do Openresty é muito baixa, por favor atualize o Openresty para 1.27.1.2-2-2-focal" 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'
#tarefa
TaskStart: '{{ .name }} A tarefa inicia [START]' TaskStart: '{{ .name }} A tarefa inicia [START]'
TaskEnd: '{{ .name }} Tarefa concluída [CONCLUÍDA]' TaskEnd: '{{ .name }} Tarefa concluída [CONCLUÍDA]'
TaskFailed: '{{ .name }} tarefa falhou' TaskFailed: '{{ .name }} tarefa falhou'
@@ -362,18 +326,18 @@ TaskDelete: 'Excluir'
TaskUpgrade: 'Atualizar' TaskUpgrade: 'Atualizar'
TaskUpdate: 'Atualizar' TaskUpdate: 'Atualizar'
TaskRestart: 'Reiniciar' TaskRestart: 'Reiniciar'
TaskProtect: "Proteger" TaskProtect: 'Proteger'
Backup de Tarefa: 'Backup' TaskBackup: 'Backup'
TaskRecover: 'Recuperar' TaskRecover: 'Recuperar'
TaskRollback: 'Reverter' TaskRollback: 'Reverter'
TaskPull: 'Puxar' TaskPull: 'Puxar'
TaskCommit: 'Commit' TaskCommit: 'Commit'
TaskBuild: 'Construir' TaskBuild: 'Construir'
TaskPush: 'Empurrar' TaskPush: 'Empurrar'
TaskClean: "Limpeza" TaskClean: 'Limpeza'
TaskHandle: 'Executar' TaskHandle: 'Executar'
TaskImport: "Importar" TaskImport: 'Importar'
TaskExport: "Exportar" TaskExport: 'Exportar'
Website: 'Site' Website: 'Site'
App: 'Aplicativo' App: 'Aplicativo'
Runtime: 'Ambiente de tempo de execução' Runtime: 'Ambiente de tempo de execução'
@@ -405,18 +369,12 @@ RuntimeExtension: 'Extensão do ambiente de tempo de execução'
TaskIsExecuting: 'A tarefa está em execução' TaskIsExecuting: 'A tarefa está em execução'
CustomAppstore: 'Armazém de aplicativos personalizados' CustomAppstore: 'Armazém de aplicativos personalizados'
TaskExec: 'Executar' TaskExec: 'Executar'
TaskBatch: "Operação em Lote" TaskBatch: 'Operação em Lote'
FileConvert: 'Conversão de Formato de Arquivo' FileConvert: 'Conversão de Formato de Arquivo'
Clamscan: 'Escanear {{ .name }}'
# task - clam TaskScan: 'Escanear'
Clamscan: "Escanear {{ .name }}"
TaskScan: "Escanear"
# tarefa - ai
OllamaModelPull: 'Puxar modelo Ollama {{ .name }}' OllamaModelPull: 'Puxar modelo Ollama {{ .name }}'
OllamaModelSize: 'Obtenha o tamanho do modelo Ollama {{ .name }}' OllamaModelSize: 'Obtenha o tamanho do modelo Ollama {{ .name }}'
# tarefa-instantânea
Snapshot: 'Instantâneo' Snapshot: 'Instantâneo'
SnapDBInfo: 'Escrever informações do banco de dados 1Panel' SnapDBInfo: 'Escrever informações do banco de dados 1Panel'
SnapCopy: 'Copiar arquivos e diretórios {{ .name }}' SnapCopy: 'Copiar arquivos e diretórios {{ .name }}'
@@ -442,7 +400,6 @@ SnapCompressSize: 'Tamanho do arquivo de instantâneo {{ .name }}'
SnapUpload: 'Carregar arquivo de instantâneo' SnapUpload: 'Carregar arquivo de instantâneo'
SnapUploadTo: 'Carregar arquivo de instantâneo para {{ .name }}' SnapUploadTo: 'Carregar arquivo de instantâneo para {{ .name }}'
SnapUploadRes: 'Carregar arquivo de instantâneo para {{ .name }}' SnapUploadRes: 'Carregar arquivo de instantâneo para {{ .name }}'
SnapshotRecover: 'Restauração de instantâneo' SnapshotRecover: 'Restauração de instantâneo'
RecoverDownload: 'Baixar arquivo de instantâneo' RecoverDownload: 'Baixar arquivo de instantâneo'
Download: 'Baixar' Download: 'Baixar'
@@ -450,10 +407,10 @@ RecoverDownloadAccount: 'Obter conta de backup de download de instantâneo {{ .n
RecoverDecompress: 'Descompacte arquivos compactados de instantâneos' RecoverDecompress: 'Descompacte arquivos compactados de instantâneos'
Decompress: 'Descompressão' Decompress: 'Descompressão'
BackupBeforeRecover: 'Fazer backup de dados relacionados ao sistema antes do snapshot' BackupBeforeRecover: 'Fazer backup de dados relacionados ao sistema antes do snapshot'
Readjson: 'Ler o arquivo Json no snapshot' ReadJson: 'Ler o arquivo Json no snapshot'
ReadjsonPath: 'Obtenha o caminho do arquivo Json no snapshot' ReadJsonPath: 'Obtenha o caminho do arquivo Json no snapshot'
ReadjsonContent: 'Ler arquivo Json' ReadJsonContent: 'Ler arquivo Json'
ReadjsonMarshal: 'Processamento de escape JSON' ReadJsonMarshal: 'Processamento de escape JSON'
RecoverApp: 'Restaurar aplicativos instalados' RecoverApp: 'Restaurar aplicativos instalados'
RecoverWebsite: 'Recuperar diretório de sites' RecoverWebsite: 'Recuperar diretório de sites'
RecoverAppImage: 'Restaurar backup de imagem instantânea' RecoverAppImage: 'Restaurar backup de imagem instantânea'
@@ -467,9 +424,6 @@ RecoverDaemonJson: 'Restaurar arquivo daemon.json de configuração do contêine
RecoverDBData: 'Recuperar dados do banco de dados' RecoverDBData: 'Recuperar dados do banco de dados'
RecoverBackups: 'Restaurar diretório de backup local' RecoverBackups: 'Restaurar diretório de backup local'
RecoverPanelData: 'Diretório de dados de recuperação' RecoverPanelData: 'Diretório de dados de recuperação'
# tarefa - contêiner
ContainerNewCliet: 'Inicializar cliente Docker'
ContainerImagePull: 'Puxar imagem do contêiner {{ .name }}' ContainerImagePull: 'Puxar imagem do contêiner {{ .name }}'
ContainerRemoveOld: 'Remover o contêiner original {{ .name }}' ContainerRemoveOld: 'Remover o contêiner original {{ .name }}'
ContainerImageCheck: 'Verifique se a imagem é extraída normalmente' ContainerImageCheck: 'Verifique se a imagem é extraída normalmente'
@@ -478,22 +432,13 @@ ContainerRecreate: 'A atualização do contêiner falhou, agora iniciando a rest
ContainerCreate: 'Criar um novo contêiner {{ .name }}' ContainerCreate: 'Criar um novo contêiner {{ .name }}'
ContainerCreateFailed: 'Falha na criação do contêiner, exclua o contêiner com falha' ContainerCreateFailed: 'Falha na criação do contêiner, exclua o contêiner com falha'
ContainerStartCheck: 'Verifique se o contêiner foi iniciado' ContainerStartCheck: 'Verifique se o contêiner foi iniciado'
# tarefa - imagem
ImageBuild: 'Construção de imagem' ImageBuild: 'Construção de imagem'
ImageBuildStdoutCheck: 'Analisar conteúdo de saída da imagem'
ImageBuildRes: 'Saída da criação da imagem: {{ .name }}'
ImagePull: 'Puxar imagem' ImagePull: 'Puxar imagem'
ImageRepoAuthFromDB: 'Obter informações de autenticação do repositório do banco de dados' ImageRepoAuthFromDB: 'Obter informações de autenticação do repositório do banco de dados'
ImaegPullRes: 'Saída de extração de imagem: {{ .name }}'
ImagePush: 'Enviar imagem' ImagePush: 'Enviar imagem'
ImageRenameTag: 'Modificar tag de imagem' ImageRenameTag: 'Modificar tag de imagem'
ImageNewTag: 'Nova tag de imagem {{ .name }}' ImageNewTag: 'Nova tag de imagem {{ .name }}'
ImaegPushRes: 'Saída de envio de imagem: {{ .name }}'
ComposeCreate: 'Criar uma composição' 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' BackupNginxConfig: 'Fazer backup do arquivo de configuração do OpenResty do site'
CompressFileSuccess: 'Diretório compactado com sucesso, compactado para {{ .name }}' CompressFileSuccess: 'Diretório compactado com sucesso, compactado para {{ .name }}'
CompressDir: 'Diretório de compressão' CompressDir: 'Diretório de compressão'
@@ -504,40 +449,27 @@ websiteDir: 'Diretório de sites'
RecoverFailedStartRollBack: 'Falha na recuperação, iniciar reversão' RecoverFailedStartRollBack: 'Falha na recuperação, iniciar reversão'
AppBackupFileIncomplete: 'O arquivo de backup está incompleto e não contém os arquivos app.json ou app.tar.gz' AppBackupFileIncomplete: 'O arquivo de backup está incompleto e não contém os arquivos app.json ou app.tar.gz'
AppAttributesNotMatch: 'O tipo ou nome do aplicativo não corresponde' AppAttributesNotMatch: 'O tipo ou nome do aplicativo não corresponde'
ErrAlertSync: 'Erro de sincronização de informações de alarme, verifique e'
#alerta ErrInstallExtension: 'Já existe uma tarefa de instalação em andamento, aguarde a conclusão da tarefa'
ErrAlert: 'O formato da mensagem de aviso está incorreto, verifique e tente novamente!' PanelAlertTitle: 'Notificação de Alerta do Painel'
ErrAlertPush: 'Erro ao enviar informações de alerta, verifique e tente novamente!' TestAlertTitle: 'E-mail de Teste - Verificar Conectividade de E-mail'
ErrAlertSave: 'Erro ao salvar as informações do alarme. Verifique e tente novamente!' TestAlert: 'Este é um e-mail de teste para verificar se sua configuração de envio de e-mails está correta.'
ErrAlertSync: 'Erro de sincronização de informações de alarme, verifique e tente novamente!' LicenseExpirationAlert: 'Seu Painel {{ .node }}{{ .ip }}, a licença expirará em {{ .day }} dias. Faça login no painel para obter detalhes.'
ErrAlertRemote: 'Erro remoto na mensagem de alarme, verifique e tente novamente!' 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.'
#task - runtime WebSiteAlert: 'Seu Painel {{ .node }}{{ .ip }}, {{ .num }} sites expirarão em {{ .day }} dias. Faça login no painel para obter detalhes.'
ErrInstallExtension: "Já existe uma tarefa de instalação em andamento, aguarde a conclusão da tarefa" 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.'
# alert mail template 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.'
PanelAlertTitle: "Notificação de Alerta do Painel" 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.'
TestAlertTitle: "E-mail de Teste - Verificar Conectividade de E-mail" PanelPwdExpirationAlert: 'Seu Painel {{ .node }}{{ .ip }}, a senha do painel expirará em {{ .day }} dias. Faça login no painel para obter detalhes.'
TestAlert: "Este é um e-mail de teste para verificar se sua configuração de envio de e-mails está correta." CommonAlert: 'Seu Painel {{ .node }}{{ .ip }}, {{ .msg }}. Faça login no painel para obter detalhes.'
LicenseExpirationAlert: "Seu Painel {{ .node }}{{ .ip }}, a licença expirará em {{ .day }} dias. 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.'
CronJobFailedAlert: "Seu Painel {{ .node }}{{ .ip }}, a execução da tarefa agendada {{ .name }} falhou. 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.'
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." SSHAndPanelLoginAlert: 'Seu Painel {{ .node }}{{ .ip }}, o login {{ .name }} a partir de {{ .loginIp }} é anormal. 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." DeviceNotFound: 'Dispositivo {{ .name }} não encontrado'
SSLAlert: "Seu Painel {{ .node }}{{ .ip }}, {{ .num }} certificados SSL expirarão em {{ .day }} dias. Faça login no painel para obter detalhes." DeviceIsMounted: 'Dispositivo {{ .name }} está montado desmonte primeiro'
DiskUsedAlert: "Seu Painel {{ .node }}{{ .ip }}, o uso do disco {{ .name }} atingiu {{ .used }}. Faça login no painel para obter detalhes." PartitionDiskErr: 'Falha ao particionar, {{ .err }}'
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." FormatDiskErr: 'Falha ao formatar disco, {{ .err }}'
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." MountDiskErr: 'Falha ao montar disco, {{ .err }}'
PanelPwdExpirationAlert: "Seu Painel {{ .node }}{{ .ip }}, a senha do painel expirará em {{ .day }} dias. Faça login no painel para obter detalhes." XfsNotFound: 'Sistema de arquivos xfs não detectado instale xfsprogs primeiro'
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"
+168 -236
View File
@@ -1,34 +1,28 @@
ErrInvalidParams: 'Ошибка параметра запроса: {{ .detail }}' ErrInvalidParams: 'Неверный запрос: {{ .detail }}'
ErrTokenParse: 'Ошибка генерации токена: {{ .detail }}' ErrTokenParse: 'Ошибка токена: {{ .detail }}'
ErrInitialPassword: 'Исходный пароль неверный' ErrInitialPassword: 'Исходный пароль неверен'
ErrInternalServer: 'Внутренняя ошибка сервера: {{ .detail }}' ErrInternalServer: 'Внутренняя ошибка: {{ .detail }}'
ErrRecordExist: 'Запись уже существует' ErrRecordExist: 'Запись уже существует'
ErrRecordNotFound: 'Запись не найдена' ErrRecordNotFound: 'Запись не найдена'
ErrStructTransform: 'Не удалось преобразовать тип: {{ .err }}' ErrStructTransform: 'Ошибка преобразования: {{ .err }}'
ErrNotLogin: 'Пользователь не вошел в систему: {{ .detail }}' ErrNotLogin: 'Не авторизован: {{ .detail }}'
ErrPasswordExpired: 'Срок действия текущего пароля истек: {{ .detail }}' ErrPasswordExpired: 'Пароль истёк: {{ .detail }}'
ErrNotSupportType: 'Система не поддерживает текущий тип: {{ .name }}' ErrNotSupportType: 'Тип не поддерживается: {{ .name }}'
ErrProxy: 'Ошибка запроса, проверьте статус узла: {{ .detail }}' ErrProxy: 'Запрос не удался: {{ .detail }}'
ErrApiConfigStatusInvalid: 'Доступ к интерфейсу API запрещен: {{ .detail }}' ErrApiConfigStatusInvalid: 'API отключено: {{ .detail }}'
ErrApiConfigKeyInvalid: 'Ошибка ключа интерфейса API: {{ .detail }}' ErrApiConfigKeyInvalid: 'Неверный API-ключ: {{ .detail }}'
ErrApiConfigIPInvalid: 'IP-адрес, используемый для вызова интерфейса API, отсутствует в белом списке: {{ .detail }}' ErrApiConfigIPInvalid: 'IP не в списке: {{ .detail }}'
ErrApiConfigDisable: 'Этот интерфейс запрещает использование вызовов интерфейса API: {{ .detail }}' ErrApiConfigDisable: 'Доступ по API запрещён: {{ .detail }}'
ErrApiConfigKeyTimeInvalid: 'Ошибка временной метки интерфейса API: {{ .detail }}' ErrApiConfigKeyTimeInvalid: 'Неверная метка времени: {{ .detail }}'
StartPushSSLToNode: "Начало отправки сертификата на узел" ErrShutDown: 'Команда остановлена вручную'
PushSSLToNodeFailed: "Не удалось отправить сертификат на узел: {{ .err }}" ErrMinQuickJump: 'Добавьте хотя бы одну быструю ссылку'
PushSSLToNodeSuccess: "Сертификат успешно отправлен на узел" ErrMaxQuickJump: 'Не более 4 быстрых ссылок'
ErrShutDown: "Команда завершена вручную!" ErrUsernameIsExist: 'Имя пользователя занято'
ErrNameIsExist: 'Имя уже занято'
ErrMinQuickJump: "Пожалуйста, установите хотя бы одну запись быстрого перехода!" ErrDemoEnvironment: 'Недоступно в демо'
ErrMaxQuickJump: "Можно установить до четырех записей быстрого перехода!" ErrCmdTimeout: 'Команда завершилась по тайм-ауту'
ErrCmdIllegal: 'Команда содержит недопустимые символы'
#общий ErrPortExist: 'Порт {{ .port }} занят {{ .type }} [{{ .name }}]'
ErrUsernameIsExist: 'Имя пользователя уже существует'
ErrNameIsExist: 'Имя уже существует'
ErrDemoEnvironment: 'Демо-сервер, эта операция запрещена!'
ErrCmdTimeout: 'Время выполнения команды истекло!'
ErrCmdIllegal: 'В команде выполнения есть недопустимые символы. Измените ее и повторите попытку!'
ErrPortExist: 'Порт {{ .port }} уже занят {{ .type }} [{{ .name }}]'
TYPE_APP: 'Приложение' TYPE_APP: 'Приложение'
TYPE_RUNTIME: 'Среда выполнения' TYPE_RUNTIME: 'Среда выполнения'
TYPE_DOMAIN: 'Доменное имя' TYPE_DOMAIN: 'Доменное имя'
@@ -39,45 +33,39 @@ Failed: 'Не удалось'
SystemRestart: 'Задача прервана из-за перезапуска системы' SystemRestart: 'Задача прервана из-за перезапуска системы'
ErrGroupIsDefault: 'Группа по умолчанию, не может быть удалена' ErrGroupIsDefault: 'Группа по умолчанию, не может быть удалена'
ErrGroupIsInWebsiteUse: 'Группа используется другим веб-сайтом и не может быть удалена.' ErrGroupIsInWebsiteUse: 'Группа используется другим веб-сайтом и не может быть удалена.'
Decrypt: "Расшифровать" Decrypt: 'Расшифровать'
ErrAgentAccountBound: 'Акаунт привязан к агенту'
#agent ErrAgentAccountUnavailable: 'Связь с аккаунтом недоступна: {{ .err }}'
ErrAgentAccountBound: 'Эта учетная запись привязана к агенту и не может быть удалена. Проверьте и повторите попытку!' ErrAgentProviderNotSupported: 'Провайдер агента не поддерживается'
ErrAgentAccountUnavailable: 'Информация о подключении учетной записи недоступна. Ошибка: {{ .err }}. Проверьте и повторите попытку!' ErrAgentAccountRequired: 'Выберите аккаунт агента'
ErrAgentProviderNotSupported: 'Этот провайдер агента не поддерживается. Проверьте и повторите попытку!' ErrAgentAccountNotVerified: 'Аккаунт не подтверждён'
ErrAgentAccountRequired: 'Выберите учетную запись агента и повторите попытку.' ErrAgentProviderMismatch: 'Провайдер не совпадает'
ErrAgentAccountNotVerified: 'Учетная запись не прошла проверку. Проверьте и повторите попытку!' ErrAgentBaseURLRequired: 'Нужен базовый URL'
ErrAgentProviderMismatch: 'Провайдер учетной записи не совпадает. Проверьте и повторите попытку!' ErrAgentApiKeyRequired: 'Нужен API-ключ'
ErrAgentBaseURLRequired: 'Base URL не может быть пустым. Проверьте и повторите попытку!' ErrAgentComposeRequired: 'Нужен compose'
ErrAgentApiKeyRequired: 'API Key не может быть пустым. Проверьте и повторите попытку!' ErrAgentIDRequired: 'Нужен ID агента'
ErrAgentComposeRequired: 'Пользовательское содержимое compose не может быть пустым. Проверьте и повторите попытку!' ErrAgentAccountIDRequired: 'Нужен ID аккаунта'
ErrAgentIDRequired: 'ID агента не может быть пустым. Проверьте и повторите попытку!'
ErrAgentAccountIDRequired: 'ID учетной записи не может быть пустым. Проверьте и повторите попытку!'
#резервное копирование
Localhost: 'Локальная машина' Localhost: 'Локальная машина'
ErrBackupInUsed: 'Учетная запись резервного копирования использовалась в запланированной задаче и не может быть удалена.' ErrBackupInUsed: 'Аккаунт бэкапа занят задачей'
ErrBackupCheck: 'Проверка подключения к резервной копии учетной записи не удалась {{ .err }}' ErrBackupCheck: 'Проверка подключения не удалась: {{ .err }}'
ErrBackupLocalDelete: 'Удаление учетной записи резервного копирования локального сервера пока не поддерживается' ErrBackupLocalDelete: 'Нельзя удалить локальные бэкапы'
ErrBackupLocalCreate: 'Создание учетных записей резервного копирования локального сервера пока не поддерживается' ErrBackupLocalCreate: 'Нельзя создать локальные бэкапы'
ErrPortInUsed: '{{ .detail }} порт уже занят'
#приложение
ErrPortInUsed: '{{ .detail }} порт уже занят!'
ErrAppLimit: 'Количество установленных приложений превысило лимит' ErrAppLimit: 'Количество установленных приложений превысило лимит'
ErrNotInstall: 'Приложение не установлено' ErrNotInstall: 'Приложение не установлено'
ErrPortInOtherApp: 'Порт {{ .port }} уже занят приложением {{ .apps }}!' ErrPortInOtherApp: 'Порт {{ .port }} уже занят приложением {{ .apps }}'
ErrDbUserNotValid: 'Существующая база данных, имя пользователя и пароль не совпадают!' ErrDbUserNotValid: 'Существующая база данных, имя пользователя и пароль не совпадают'
ErrUpdateBuWebsite: 'Приложение успешно обновлено, но изменение файла конфигурации веб-сайта не удалось. Пожалуйста, проверьте конфигурацию! ' ErrUpdateBuWebsite: 'Приложение успешно обновлено, но изменение файла конфигурации веб-сайта не удалось. Пожалуйста, проверьте конфигурацию'
Err1PanelNetworkFailed: 'Создание сети контейнеров по умолчанию не удалось! {{ .detail }}' Err1PanelNetworkFailed: 'Создание сети контейнеров по умолчанию не удалось {{ .detail }}'
ErrFileParse: 'Ошибка анализа файла docker-compose приложения!' ErrFileParse: 'Ошибка анализа файла docker-compose приложения'
ErrInstallDirNotFound: 'Каталог установки не существует. Если вам необходимо удалить, выберите Принудительное удаление.' ErrInstallDirNotFound: 'Каталог установки не существует. Если вам необходимо удалить, выберите Принудительное удаление.'
AppStoreIsUpToDate: 'В магазине приложений уже установлена последняя версия' AppStoreIsUpToDate: 'В магазине приложений уже установлена последняя версия'
LocalAppVersionNull: 'Приложение {{ .name }} не синхронизировано с версией! Невозможно добавить в список приложений.' LocalAppVersionNull: 'Приложение {{ .name }} не синхронизировано с версией Невозможно добавить в список приложений.'
LocalAppVersionErr: 'Синхронизация версии {{ .version }} {{ .name }} не удалась! {{ .err }}' LocalAppVersionErr: 'Синхронизация версии {{ .version }} {{ .name }} не удалась {{ .err }}'
ErrFileNotFound: 'Файл {{ .name }} не существует' ErrFileNotFound: 'Файл {{ .name }} не существует'
ErrFileParseApp: '{{ .name }} анализ файла не удался {{ .err }}' ErrFileParseApp: '{{ .name }} анализ файла не удался {{ .err }}'
ErrAppDirNull: 'Папка версии не существует' ErrAppDirNull: 'Папка версии не существует'
LocalAppErr: 'Синхронизация приложения {{ .name }} не удалась! {{ .err }}' LocalAppErr: 'Синхронизация приложения {{ .name }} не удалась {{ .err }}'
ErrContainerName: 'Имя контейнера уже существует' ErrContainerName: 'Имя контейнера уже существует'
ErrCreateHttpClient: 'Не удалось создать запрос {{ .err }}' ErrCreateHttpClient: 'Не удалось создать запрос {{ .err }}'
ErrHttpReqTimeOut: 'Истекло время ожидания запроса {{ .err }}' ErrHttpReqTimeOut: 'Истекло время ожидания запроса {{ .err }}'
@@ -90,46 +78,42 @@ ErrAppBackup: '{{ .name }} резервное копирование прило
ErrVersionTooLow: 'Текущая версия 1Panel слишком низкая для обновления App Store. Пожалуйста, обновите версию перед началом работы.' ErrVersionTooLow: 'Текущая версия 1Panel слишком низкая для обновления App Store. Пожалуйста, обновите версию перед началом работы.'
ErrAppNameExist: 'Имя приложения уже существует' ErrAppNameExist: 'Имя приложения уже существует'
AppStoreIsSyncing: 'App Store синхронизируется, повторите попытку позже' AppStoreIsSyncing: 'App Store синхронизируется, повторите попытку позже'
ErrGetCompose: 'Не удалось получить файл docker-compose.yml! {{ .detail }}' ErrGetCompose: 'Не удалось получить файл docker-compose.yml {{ .detail }}'
ErrAppWarn: 'Ненормальное состояние, проверьте журнал' ErrAppWarn: 'Ненормальное состояние, проверьте журнал'
ErrAppParamKey: 'Поле параметра {{ .name }} ненормально' ErrAppParamKey: 'Поле параметра {{ .name }} ненормально'
ErrAppUpgrade: 'Обновление приложения {{ .name }} не удалось {{ .err }}' ErrAppUpgrade: 'Обновление приложения {{ .name }} не удалось {{ .err }}'
AppRecover: 'Откатить приложение {{ .name }}' AppRecover: 'Откатить приложение {{ .name }}'
PullImageStart: 'Начать извлечение изображения [{{ .name }}]' PullImageStart: 'Начать извлечение изображения [{{ .name }}]'
PullImageSuccess: 'Изображение извлечено успешно' PullImageSuccess: 'Изображение извлечено успешно'
AppStoreIsLastVersion: 'В App Store уже установлена последняя версия'
AppStoreSyncSuccess: 'Синхронизация с App Store прошла успешно' AppStoreSyncSuccess: 'Синхронизация с App Store прошла успешно'
SyncAppDetail: 'Синхронизировать конфигурацию приложения' SyncAppDetail: 'Синхронизировать конфигурацию приложения'
AppVersionNotMatch: 'Приложению {{ .name }} требуется более высокая версия 1Panel, синхронизация пропускается' AppVersionNotMatch: 'Приложению {{ .name }} требуется более высокая версия 1Panel, синхронизация пропускается'
MoveSiteDir: "Обнаружено изменение каталога сайта. Необходимо перенести каталог сайта OpenResty в {{ .name }}" MoveSiteDir: 'Обнаружено изменение каталога сайта. Необходимо перенести каталог сайта OpenResty в {{ .name }}'
MoveSiteDirSuccess: 'Успешная миграция каталога веб-сайта' MoveSiteDirSuccess: 'Успешная миграция каталога веб-сайта'
DeleteRuntimePHP: 'Удалить среду выполнения PHP' DeleteRuntimePHP: 'Удалить среду выполнения PHP'
CustomAppStoreFileValid: 'Пакеты магазина приложений должны быть в формате .tar.gz' CustomAppStoreFileValid: 'Пакеты магазина приложений должны быть в формате.tar.gz'
PullImageTimeout: 'Истекло время ожидания извлечения изображения. Попробуйте увеличить ускорение изображения или выбрать другое ускорение изображения' PullImageTimeout: 'Истекло время ожидания извлечения изображения. Попробуйте увеличить ускорение изображения или выбрать другое ускорение изображения'
ErrAppIsDown: '{{ .name }} статус приложения ненормальный, проверьте' ErrAppIsDown: '{{ .name }} статус приложения ненормальный, проверьте'
ErrCustomApps: 'Установлено приложение. Сначала удалите его' ErrCustomApps: 'Установлено приложение. Сначала удалите его'
ErrCustomRuntimes: 'Установлена среда выполнения. Сначала удалите ее' ErrCustomRuntimes: 'Установлена среда выполнения. Сначала удалите ее'
ErrAppVersionDeprecated: "Приложение {{ .name }} несовместимо с текущей версией 1Panel, пропущено" ErrAppVersionDeprecated: 'Приложение {{ .name }} несовместимо с текущей версией 1Panel, пропущено'
ErrDockerFailed: "Состояние Docker аномально, проверьте состояние сервиса" ErrDockerFailed: 'Состояние Docker аномально, проверьте состояние сервиса'
ErrDockerComposeCmdNotFound: "Команда Docker Compose отсутствует, пожалуйста, установите эту команду на хост-машине сначала" ErrDockerComposeCmdNotFound: 'Команда Docker Compose отсутствует, пожалуйста, установите эту команду на хост-машине сначала'
UseExistImage: 'Не удалось загрузить образ, используется существующий образ' UseExistImage: 'Образ уже существует, используется существующий образ'
ErrDatabaseNotFound: 'База данных {{ .name }} не существует'
#ssh ExportIP: 'IP входа'
ExportIP: "IP входа" ExportArea: 'Местоположение'
ExportArea: "Местоположение" ExportPort: 'Порт'
ExportPort: "Порт" ExportAuthMode: 'Способ входа'
ExportAuthMode: "Способ входа" ExportUser: 'Пользователь'
ExportUser: "Пользователь" ExportStatus: 'Статус входа'
ExportStatus: "Статус входа" ExportDate: 'Время'
ExportDate: "Время"
#файл
ErrFileCanNotRead: 'Этот файл не поддерживает предварительный просмотр' ErrFileCanNotRead: 'Этот файл не поддерживает предварительный просмотр'
ErrFileToLarge: 'Файл больше 10 МБ и не может быть открыт' ErrFileToLarge: 'Файл больше 10 МБ и не может быть открыт'
ErrPathNotFound: 'Каталог не существует' ErrPathNotFound: 'Каталог не существует'
ErrMovePathFailed: 'Целевой путь не может содержать исходный путь!' ErrMovePathFailed: 'Целевой путь не может содержать исходный путь'
ErrLinkPathNotFound: 'Целевой путь не существует!' ErrLinkPathNotFound: 'Целевой путь не существует'
ErrFileIsExist: 'Файл или папка уже существует!' ErrFileIsExist: 'Файл или папка уже существует'
ErrFileUpload: '{{ .name }} не удалось загрузить файл {{ .detail }}' ErrFileUpload: '{{ .name }} не удалось загрузить файл {{ .detail }}'
ErrFileDownloadDir: 'Папка загрузки не поддерживается' ErrFileDownloadDir: 'Папка загрузки не поддерживается'
ErrCmdNotFound: 'Команда {{ .name }} не существует, сначала установите эту команду на хосте' ErrCmdNotFound: 'Команда {{ .name }} не существует, сначала установите эту команду на хосте'
@@ -137,17 +121,15 @@ ErrSourcePathNotFound: 'Исходный каталог не существуе
ErrFavoriteExist: 'Этот путь уже добавлен в избранное' ErrFavoriteExist: 'Этот путь уже добавлен в избранное'
ErrInvalidChar: 'Недопустимые символы не допускаются' ErrInvalidChar: 'Недопустимые символы не допускаются'
ErrPathNotDelete: 'Выбранный каталог не может быть удален' ErrPathNotDelete: 'Выбранный каталог не может быть удален'
ErrLogFileToLarge: "Файл журнала превышает 500MB и не может быть открыт" ErrLogFileToLarge: 'Файл журнала превышает 500MB и не может быть открыт'
FileDropFailed: "Не удалось очистить файл {{ .name }}: {{ .err }}" FileDropFailed: 'Не удалось очистить файл {{ .name }}: {{ .err }}'
FileDropSuccess: "Файл {{ .name }} успешно очищен, удалено {{ .count }} файлов, освобождено {{ .size }} дискового пространства" FileDropSuccess: 'Файл {{ .name }} успешно очищен, удалено {{ .count }} файлов, освобождено {{ .size }} дискового пространства'
FileDropSum: "Очистка файлов завершена успешно, всего удалено {{ .count }} файлов, освобождено {{ .size }} дискового пространства" FileDropSum: 'Очистка файлов завершена успешно, всего удалено {{ .count }} файлов, освобождено {{ .size }} дискового пространства'
ErrBadDecrypt: "Ошибка пароля расшифровки сжатого пакета, распаковка не удалась, проверьте и повторите попытку!" ErrBadDecrypt: 'Ошибка пароля расшифровки сжатого пакета, распаковка не удалась, проверьте и повторите попытку'
#веб-сайт
ErrAliasIsExist: 'Псевдоним уже существует' ErrAliasIsExist: 'Псевдоним уже существует'
ErrBackupMatch: 'Файл резервной копии не соответствует некоторым текущим данным веб-сайта {{ .detail }}' ErrBackupMatch: 'Файл резервной копии не соответствует некоторым текущим данным веб-сайта {{ .detail }}'
ErrBackupExist: 'Соответствующая часть исходных данных в файле резервной копии не существует {{ .detail }}' ErrBackupExist: 'Соответствующая часть исходных данных в файле резервной копии не существует {{ .detail }}'
ErrPHPResource: 'Локальная операционная среда не поддерживает переключение!' ErrPHPResource: 'Локальная операционная среда не поддерживает переключение'
ErrPathPermission: 'В каталоге index обнаружена папка с разрешениями, отличными от 1000:1000, что может привести к ошибке Отказано в доступе на веб-сайте. Пожалуйста, нажмите кнопку Сохранить выше.' ErrPathPermission: 'В каталоге index обнаружена папка с разрешениями, отличными от 1000:1000, что может привести к ошибке Отказано в доступе на веб-сайте. Пожалуйста, нажмите кнопку Сохранить выше.'
ErrDomainIsUsed: 'Доменное имя уже используется веб-сайтом [{{ .name }}]' ErrDomainIsUsed: 'Доменное имя уже используется веб-сайтом [{{ .name }}]'
ErrDomainFormat: 'Неверный формат доменного имени {{ .name }}' ErrDomainFormat: 'Неверный формат доменного имени {{ .name }}'
@@ -155,11 +137,11 @@ ErrDefaultAlias: 'по умолчанию зарезервирован код,
ErrParentWebsite: 'Сначала вам необходимо удалить дочерний сайт {{ .name }}' ErrParentWebsite: 'Сначала вам необходимо удалить дочерний сайт {{ .name }}'
ErrBuildDirNotFound: 'Каталог сборки не существует' ErrBuildDirNotFound: 'Каталог сборки не существует'
ErrImageNotExist: 'Образ операционной среды {{ .name }} не существует, пожалуйста, отредактируйте операционную среду заново' ErrImageNotExist: 'Образ операционной среды {{ .name }} не существует, пожалуйста, отредактируйте операционную среду заново'
ErrProxyIsUsed: "Балансировка нагрузки используется обратным прокси, невозможно удалить" ErrProxyIsUsed: 'Балансировка нагрузки используется обратным прокси, невозможно удалить'
ErrSSLValid: 'Файл сертификата аномален, проверьте статус сертификата!' ErrSSLValid: 'Файл сертификата аномален, проверьте статус сертификата'
ErrWebsiteDir: "Пожалуйста, выберите директорию внутри директории сайта." ErrWebsiteDir: 'Пожалуйста, выберите директорию внутри директории сайта.'
ErrComposerFileNotFound: "Файл composer.json не существует" ErrComposerFileNotFound: 'Файл composer.json не существует'
ErrRuntimeNoPort: "Среда выполнения не настроена с портом, сначала отредактируйте среду выполнения." ErrRuntimeNoPort: 'Среда выполнения не настроена с портом, сначала отредактируйте среду выполнения.'
Status: 'Статус' Status: 'Статус'
start: 'Запустить' start: 'Запустить'
stop: 'Остановить' stop: 'Остановить'
@@ -169,14 +151,12 @@ pause: 'Приостановить'
unpause: 'Возобновить' unpause: 'Возобновить'
remove: 'Удалить' remove: 'Удалить'
delete: 'Удалить' delete: 'Удалить'
ErrDefaultWebsite: 'Веб-сайт по умолчанию уже установлен, отмените его перед настройкой!' ErrDefaultWebsite: 'Веб-сайт по умолчанию уже установлен, отмените его перед настройкой'
SSL: 'Сертификат' SSL: 'Сертификат'
Set: 'Настройки' Set: 'Настройки'
#ssl
ErrSSLCannotDelete: 'Сертификат {{ .name }} используется веб-сайтом и не может быть удален' ErrSSLCannotDelete: 'Сертификат {{ .name }} используется веб-сайтом и не может быть удален'
ErrAccountCannotDelete: 'Учетная запись связана с сертификатом и не может быть удалена' ErrAccountCannotDelete: 'Учетная запись связана с сертификатом и не может быть удалена'
ErrSSLApply: 'Обновление сертификата прошло успешно, перезагрузка OpenResty не удалась, проверьте конфигурацию!' ErrSSLApply: 'Обновление сертификата прошло успешно, перезагрузка OpenResty не удалась, проверьте конфигурацию'
ErrEmailIsExist: 'Почтовый ящик уже существует' ErrEmailIsExist: 'Почтовый ящик уже существует'
ErrSSLKeyNotFound: 'Файл закрытого ключа не существует' ErrSSLKeyNotFound: 'Файл закрытого ключа не существует'
ErrSSLCertificateNotFound: 'Файл сертификата не существует' ErrSSLCertificateNotFound: 'Файл сертификата не существует'
@@ -189,7 +169,7 @@ dnsAccount: 'DNS Авто'
dnsManual: 'Руководство по DNS' dnsManual: 'Руководство по DNS'
http: 'HTTP' http: 'HTTP'
ApplySSLFailed: 'Заявка на сертификат [{{ .domain }}] не выполнена, {{ .detail }}' ApplySSLFailed: 'Заявка на сертификат [{{ .domain }}] не выполнена, {{ .detail }}'
ApplySSLSuccess: 'Заявка на сертификат [{{ .domain }}] успешно подана! ' ApplySSLSuccess: 'Заявка на сертификат [{{ .domain }}] успешно подана'
DNSAccountName: 'DNS-аккаунт [{{ .name }}] поставщик [{{ .type }}]' DNSAccountName: 'DNS-аккаунт [{{ .name }}] поставщик [{{ .type }}]'
PushDirLog: 'Сертификат перемещен в каталог [{{ .path }}] {{ .status }}' PushDirLog: 'Сертификат перемещен в каталог [{{ .path }}] {{ .status }}'
ErrDeleteCAWithSSL: 'Текущая организация имеет сертификат, который был выдан и не может быть удален.' ErrDeleteCAWithSSL: 'Текущая организация имеет сертификат, который был выдан и не может быть удален.'
@@ -204,94 +184,79 @@ ExecShellSuccess: 'Скрипт выполнен успешно'
StartUpdateSystemSSL: 'Начать обновление системного сертификата' StartUpdateSystemSSL: 'Начать обновление системного сертификата'
UpdateSystemSSLSuccess: 'Сертификат системы обновлен успешно' UpdateSystemSSLSuccess: 'Сертификат системы обновлен успешно'
ErrWildcardDomain: 'Невозможно подать заявку на получение подстановочного сертификата доменного имени в режиме HTTP' ErrWildcardDomain: 'Невозможно подать заявку на получение подстановочного сертификата доменного имени в режиме HTTP'
ErrApplySSLCanNotDelete: "Нельзя удалить сертификат {{.name}}, который находится в процессе выпуска. Пожалуйста, попробуйте позже." ErrApplySSLCanNotDelete: 'Нельзя удалить сертификат {{ .name }}, который находится в процессе выпуска. Пожалуйста, попробуйте позже.'
StartPushSSLToNode: 'Начало отправки сертификата на узел'
#mysql PushSSLToNodeFailed: 'Не удалось отправить сертификат на узел: {{ .err }}'
PushSSLToNodeSuccess: 'Сертификат успешно отправлен на узел'
ErrUserIsExist: 'Текущий пользователь уже существует, пожалуйста, введите еще раз' ErrUserIsExist: 'Текущий пользователь уже существует, пожалуйста, введите еще раз'
ErrDatabaseIsExist: 'Текущая база данных уже существует, пожалуйста, введите ее повторно' ErrDatabaseIsExist: 'Текущая база данных уже существует, пожалуйста, введите ее повторно'
ErrExecTimeOut: 'Время выполнения SQL истекло, проверьте базу данных' ErrExecTimeOut: 'Время выполнения SQL истекло, проверьте базу данных'
ErrRemoteExist: 'Удаленная база данных с таким именем уже существует. Измените его и повторите попытку' ErrRemoteExist: 'Удаленная база данных с таким именем уже существует. Измените его и повторите попытку'
ErrLocalExist: 'Имя уже существует в локальной базе данных, измените его и повторите попытку' ErrLocalExist: 'Имя уже существует в локальной базе данных, измените его и повторите попытку'
RemoteBackup: "Для резервного копирования удаленной базы данных необходимо сначала запустить службу базы данных локального контейнера с помощью образа {{ .name }}, пожалуйста, подождите..." RemoteBackup: 'Для резервного копирования удаленной базы данных необходимо сначала запустить службу базы данных локального контейнера с помощью образа {{ .name }}, пожалуйста, подождите...'
RemoteRecover: "Для восстановления удаленной базы данных необходимо сначала запустить службу базы данных локального контейнера с помощью образа {{ .name }}, пожалуйста, подождите..." RemoteRecover: 'Для восстановления удаленной базы данных необходимо сначала запустить службу базы данных локального контейнера с помощью образа {{ .name }}, пожалуйста, подождите...'
Arg: "Аргумент" Arg: 'Аргумент'
#редис
ErrTypeOfRedis: 'Тип файла восстановления не соответствует текущему методу сохранения. Измените его и повторите попытку' ErrTypeOfRedis: 'Тип файла восстановления не соответствует текущему методу сохранения. Измените его и повторите попытку'
ErrInUsed: '{{ .detail }} используется и не может быть удалено'
#контейнер ErrObjectInUsed: 'Этот объект используется и не может быть удален'
ErrInUsed: "{{ .detail }} используется и не может быть удалено!" ErrObjectBeDependent: 'Этот образ зависит от других образов и не может быть удален'
ErrObjectInUsed: "Этот объект используется и не может быть удален!" ErrPortRules: 'Номер порта не совпадает, введите заново'
ErrObjectBeDependent: "Этот образ зависит от других образов и не может быть удален!"
ErrPortRules: 'Номер порта не совпадает, введите заново!'
ErrPgImagePull: 'Время извлечения изображения истекло. Настройте ускорение изображения или вручную извлеките изображение {{ .name }} и повторите попытку' ErrPgImagePull: 'Время извлечения изображения истекло. Настройте ускорение изображения или вручную извлеките изображение {{ .name }} и повторите попытку'
PruneHelper: "Эта очистка {{ .name }} освободила дисковое пространство {{ .size }}" PruneHelper: 'Эта очистка {{ .name }} освободила дисковое пространство {{ .size }}'
ImageRemoveHelper: "Удалён образ {{ .name }}, освобождено {{ .size }} дискового пространства" ImageRemoveHelper: 'Удалён образ {{ .name }}, освобождено {{ .size }} дискового пространства'
BuildCache: "Кэш сборки" BuildCache: 'Кэш сборки'
Volume: "Том хранилища" Volume: 'Том хранилища'
Network: "Сеть" Network: 'Сеть'
PruneStart: "Очистка выполняется, пожалуйста, подождите..." PruneStart: 'Очистка выполняется, пожалуйста, подождите...'
ErrFileNotExist: 'Файл {{ .detail }} не существует Проверьте целостность исходного файла'
#время выполнения
ErrFileNotExist: 'Файл {{ .detail }} не существует! Проверьте целостность исходного файла!'
ErrImageBuildErr: 'Сборка образа не удалась' ErrImageBuildErr: 'Сборка образа не удалась'
ErrImageExist: "Изображение уже существует! Пожалуйста, измените имя изображения." ErrImageExist: 'Изображение уже существует Пожалуйста, измените имя изображения.'
ErrDelWithWebsite: 'Операционная среда уже связана с веб-сайтом и не может быть удалена' ErrDelWithWebsite: 'Операционная среда уже связана с веб-сайтом и не может быть удалена'
ErrRuntimeStart: 'Запуск не удался' ErrRuntimeStart: 'Запуск не удался'
ErrPackageJsonNotFound: 'файл package.json не существует' ErrPackageJsonNotFound: 'файл package.json не существует'
ErrScriptsNotFound: 'Элемент конфигурации скриптов не найден в package.json' ErrScriptsNotFound: 'Элемент конфигурации скриптов не найден в package.json'
ErrContainerNameNotFound: 'Не удалось получить имя контейнера, проверьте файл .env' ErrContainerNameNotFound: 'Не удалось получить имя контейнера, проверьте файл.env'
ErrNodeModulesNotFound: 'Папка node_modules не существует! Измените среду выполнения или дождитесь ее успешного запуска' ErrNodeModulesNotFound: 'Папка node_modules не существует Измените среду выполнения или дождитесь ее успешного запуска'
ErrContainerNameIsNull: 'Имя контейнера не существует' ErrContainerNameIsNull: 'Имя контейнера не существует'
ErrPHPPortIsDefault: "A porta 9000 é a porta padrão, 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" ErrPHPRuntimePortFailed: 'A porta {{ .name }} já está sendo usada pelo ambiente de tempo de execução atual, por favor, modifique e tente novamente'
#инструмент
ErrConfigNotFound: 'Файл конфигурации не существует' ErrConfigNotFound: 'Файл конфигурации не существует'
ErrConfigParse: 'Неверный формат файла конфигурации' ErrConfigParse: 'Неверный формат файла конфигурации'
ErrConfigIsNull: 'Файл конфигурации не может быть пустым' ErrConfigIsNull: 'Файл конфигурации не может быть пустым'
ErrConfigDirNotFound: 'Рабочий каталог не существует' ErrConfigDirNotFound: 'Рабочий каталог не существует'
ErrConfigAlreadyExist: 'Файл конфигурации с таким именем уже существует' ErrConfigAlreadyExist: 'Файл конфигурации с таким именем уже существует'
ErrUserFindErr: 'Поиск пользователя {{ .name }} не удался {{ .err }}' ErrUserFindErr: 'Поиск пользователя {{ .name }} не удался {{ .err }}'
#cronjob
CutWebsiteLogSuccess: 'Журнал веб-сайта {{ .name }} успешно вырезан, путь к резервной копии {{ .path }}' CutWebsiteLogSuccess: 'Журнал веб-сайта {{ .name }} успешно вырезан, путь к резервной копии {{ .path }}'
HandleShell: 'Выполнить скрипт {{ .name }}' HandleShell: 'Выполнить скрипт {{ .name }}'
HandleCurl: "Доступ к URL {{ .name }}" HandleCurl: 'Доступ к URL {{ .name }}'
HandleNtpSync: 'Синхронизация системного времени' HandleNtpSync: 'Синхронизация системного времени'
HandleSystemClean: 'Очистка системного кэша' HandleSystemClean: 'Очистка системного кэша'
SystemLog: 'Системный лог' SystemLog: 'Системный лог'
CutWebsiteLog: 'Ротация логов сайта' CutWebsiteLog: 'Ротация логов сайта'
FileOrDir: 'Каталог / Файл' FileOrDir: 'Каталог / Файл'
UploadFile: 'Загрузка файла резервной копии {{ .file }} в {{ .backup }}' UploadFile: 'Загрузка файла резервной копии {{ .file }} в {{ .backup }}'
Upload: "Загрузить" Upload: 'Загрузить'
IgnoreBackupErr: "Ошибка резервного копирования: {{ .detail }}, игнорируем эту ошибку..." IgnoreBackupErr: 'Ошибка резервного копирования: {{ .detail }}, игнорируем эту ошибку...'
IgnoreUploadErr: "Ошибка загрузки: {{ .detail }}, игнорируем эту ошибку..." IgnoreUploadErr: 'Ошибка загрузки: {{ .detail }}, игнорируем эту ошибку...'
LoadBackupFailed: "Не удалось получить подключение к учетной записи резервной копии, ошибка: {{ .detail }}" LoadBackupFailed: 'Не удалось получить подключение к учетной записи резервной копии, ошибка: {{ .detail }}'
InExecuting: "Текущая задача выполняется, не повторяйте выполнение!" InExecuting: 'Текущая задача выполняется, не повторяйте выполнение'
NoSuchResource: "В базе данных не найдено содержимое резервной копии, пропускаем..." NoSuchResource: 'В базе данных не найдено содержимое резервной копии, пропускаем...'
CleanLog: "Очистить журнал" CleanLog: 'Очистить журнал'
CleanLogByName: "Очистить журнал {{.name}}" CleanLogByName: 'Очистить журнал {{ .name }}'
WafIpGroupNotFound: "Группа IP WAF не найдена. Пожалуйста, перейдите в [Расширенные функции - WAF - Черный/Белый список - Группа IP], чтобы добавить группу IP с помощью метода удаленной загрузки." WafIpGroupNotFound: 'Группа IP WAF не найдена. Пожалуйста, перейдите в [Расширенные функции - WAF - Черный/Белый список - Группа IP], чтобы добавить группу IP с помощью метода удаленной загрузки.'
ErrNotExistUser: 'Текущий пользователь не существует, измените его и повторите попытку'
#ящик для инструментов ErrBanAction: 'Настройка не удалась. Текущая служба {{ .name }} недоступна. Проверьте и повторите попытку'
ErrNotExistUser: 'Текущий пользователь не существует, измените его и повторите попытку!' ErrClamdscanNotFound: 'Команда clamdscan не обнаружена, обратитесь к документации, чтобы установить ее'
ErrBanAction: 'Настройка не удалась. Текущая служба {{ .name }} недоступна. Проверьте и повторите попытку!' TaskSwapSet: 'Настройка Swap'
ErrClamdscanNotFound: 'Команда clamdscan не обнаружена, обратитесь к документации, чтобы установить ее!' SetSwap: 'Настроить Swap {{ .path }} - {{ .size }}'
TaskSwapSet: "Настройка Swap" CreateSwap: 'Создать Файл Swap'
SetSwap: "Настроить Swap {{ .path }} - {{ .size }}" FormatSwap: 'Форматировать Файл Swap'
CreateSwap: "Создать Файл Swap" EnableSwap: 'Включить Swap'
FormatSwap: "Форматировать Файл Swap" CleanTamperSetting: 'Очистить исторические настройки защиты'
EnableSwap: "Включить Swap" SetTamperWithRules: 'Запустить защиту каталога согласно правилам'
ProtectDir: 'Защитить каталог {{ .name }}'
#tamper IgnoreFile: 'Защитить файл {{ .name }}'
CleanTamperSetting: "Очистить исторические настройки защиты" TamperSetSuccessful: 'Настройки защиты завершены, начинаю мониторинг следующих каталогов:'
SetTamperWithRules: "Запустить защиту каталога согласно правилам"
ProtectDir: "Защитить каталог {{ .name }}"
IgnoreFile: "Защитить файл {{ .name }}"
TamperSetSuccessful: "Настройки защиты завершены, начинаю мониторинг следующих каталогов:"
#ваф
ErrScope: 'Изменение этой конфигурации не поддерживается' ErrScope: 'Изменение этой конфигурации не поддерживается'
ErrStateChange: 'He удалось изменить состояние' ErrStateChange: 'He удалось изменить состояние'
ErrRuleExist: 'Правило уже существует' ErrRuleExist: 'Правило уже существует'
@@ -299,7 +264,7 @@ ErrRuleNotExist: 'Правило не существует'
ErrParseIP: 'Неправильный формат IP' ErrParseIP: 'Неправильный формат IP'
ErrDefaultIP: 'по умолчанию это зарезервированное имя, пожалуйста, измените его на другое имя' ErrDefaultIP: 'по умолчанию это зарезервированное имя, пожалуйста, измените его на другое имя'
ErrGroupInUse: 'IP-группа используется черным/белым списком и не может быть удалена' ErrGroupInUse: 'IP-группа используется черным/белым списком и не может быть удалена'
ErrIPGroupAclUse: "Группа IP используется пользовательскими правилами сайта {{ .name }}, невозможно удалить" ErrIPGroupAclUse: 'Группа IP используется пользовательскими правилами сайта {{ .name }}, невозможно удалить'
ErrGroupExist: 'Имя группы IP уже существует' ErrGroupExist: 'Имя группы IP уже существует'
ErrIPRange: 'Неверный диапазон IP-адресов' ErrIPRange: 'Неверный диапазон IP-адресов'
ErrIPExist: 'IP-адрес уже существует' ErrIPExist: 'IP-адрес уже существует'
@@ -310,10 +275,10 @@ xss: 'XSS'
phpExec: 'Выполнение PHP-скрипта' phpExec: 'Выполнение PHP-скрипта'
oneWordTrojan: 'Троян из одного слова' oneWordTrojan: 'Троян из одного слова'
appFilter: 'Применить фильтрацию опасных каталогов' appFilter: 'Применить фильтрацию опасных каталогов'
webshell: 'Be6-оболочка' webShell: 'Be6-оболочка'
args: 'Правила параметров' args: 'Правила параметров'
protocolFilter: 'Фильтрация протоколов' protocolFilter: 'Фильтрация протоколов'
javaFileter: 'Фильтр опасных файлов Java' javaFilter: 'Фильтр опасных файлов Java'
scannerFilter: 'Фильтр сканера' scannerFilter: 'Фильтр сканера'
escapeFilter: 'фильтр побега' escapeFilter: 'фильтр побега'
customRule: 'Пользовательское правило' customRule: 'Пользовательское правило'
@@ -343,10 +308,9 @@ ErrDBNotExist: 'База данных не существует'
allow: 'разрешить' allow: 'разрешить'
deny: 'отрицать' deny: 'отрицать'
OpenrestyNotFound: 'Openresty не установлен' OpenrestyNotFound: 'Openresty не установлен'
remoteIpIsNull: "Список IP пуст" remoteIpIsNull: 'Список IP пуст'
OpenrestyVersionErr: "Версия Openresty слишком низкая, пожалуйста, обновите Openresty до 1.27.1.2-2-2-focal" OpenrestyVersionErr: 'Версия Openresty слишком низкая, пожалуйста, обновите Openresty до 1.27.1.2-2-2-focal'
ErrFileTooLarge: 'File is larger than 1 MB and cannot be uploaded'
#задача
TaskStart: '{{ .name }} Задача начинается [START]' TaskStart: '{{ .name }} Задача начинается [START]'
TaskEnd: '{{ .name }} Задача выполнена [ЗАВЕРШЕНО]' TaskEnd: '{{ .name }} Задача выполнена [ЗАВЕРШЕНО]'
TaskFailed: 'Задача {{ .name }} не выполнена' TaskFailed: 'Задача {{ .name }} не выполнена'
@@ -362,18 +326,18 @@ TaskDelete: 'Удалить'
TaskUpgrade: 'Обновить' TaskUpgrade: 'Обновить'
TaskUpdate: 'Обновить' TaskUpdate: 'Обновить'
TaskRestart: 'Перезапуск' TaskRestart: 'Перезапуск'
TaskProtect: "Защита" TaskProtect: 'Защита'
TaskBackup: 'Резервное копирование' TaskBackup: 'Резервное копирование'
TaskRecover: 'Восстановить' TaskRecover: 'Восстановить'
TaskRollback: 'Откат' TaskRollback: 'Откат'
TaskPull: 'Вытянуть' TaskPull: 'Вытянуть'
TaskCommit: 'Kоммит' TaskCommit: 'Kоммит'
ЗадачаСборка: 'Сборка' TaskBuild: 'Сборка'
TaskPush: 'Push' TaskPush: 'Push'
TaskClean: "Очистка" TaskClean: 'Очистка'
TaskHandle: 'Выполнить' TaskHandle: 'Выполнить'
TaskImport: "Импорт" TaskImport: 'Импорт'
TaskExport: "Экспорт" TaskExport: 'Экспорт'
Website: 'Be6-сайт' Website: 'Be6-сайт'
App: 'Приложение' App: 'Приложение'
Runtime: 'Среда выполнения' Runtime: 'Среда выполнения'
@@ -405,18 +369,12 @@ RuntimeExtension: 'Расширение среды выполнения'
TaskIsExecuting: 'Задача выполняется' TaskIsExecuting: 'Задача выполняется'
CustomAppstore: 'Хранилище пользовательских приложений' CustomAppstore: 'Хранилище пользовательских приложений'
TaskExec: 'Выполнить' TaskExec: 'Выполнить'
TaskBatch: "Пакетная операция" TaskBatch: 'Пакетная операция'
FileConvert: 'Преобразование формата файла' FileConvert: 'Преобразование формата файла'
Clamscan: 'Сканировать {{ .name }}'
# task - clam TaskScan: 'Сканировать'
Clamscan: "Сканировать {{ .name }}"
TaskScan: "Сканировать"
# задача - ай
OllamaModelPull: 'Вытянуть модель Ollama {{ .name }}' OllamaModelPull: 'Вытянуть модель Ollama {{ .name }}'
OllamaModelSize: 'Получить размер модели Ollama {{ .name }}' OllamaModelSize: 'Получить размер модели Ollama {{ .name }}'
# снимок задачи
Snapshot: 'Снимок' Snapshot: 'Снимок'
SnapDBInfo: 'Запись информации о базе данных 1Panel' SnapDBInfo: 'Запись информации о базе данных 1Panel'
SnapCopy: 'Копировать файлы и каталоги {{ .name }}' SnapCopy: 'Копировать файлы и каталоги {{ .name }}'
@@ -442,7 +400,6 @@ SnapCompressSize: 'Размер файла снимка {{ .name }}'
SnapUpload: 'Загрузить файл снимка' SnapUpload: 'Загрузить файл снимка'
SnapUploadTo: 'Загрузить файл снимка в {{ .name }}' SnapUploadTo: 'Загрузить файл снимка в {{ .name }}'
SnapUploadRes: 'Загрузить файл снимка в {{ .name }}' SnapUploadRes: 'Загрузить файл снимка в {{ .name }}'
SnapshotRecover: 'Восстановление моментального снимка' SnapshotRecover: 'Восстановление моментального снимка'
RecoverDownload: 'Загрузить файл снимка' RecoverDownload: 'Загрузить файл снимка'
Download: 'Скачать' Download: 'Скачать'
@@ -450,10 +407,10 @@ RecoverDownloadAccount: 'Получить резервную копию учет
RecoverDecompress: 'Распаковка сжатых файлов моментальных снимков' RecoverDecompress: 'Распаковка сжатых файлов моментальных снимков'
Decompress: 'Декомпрессия' Decompress: 'Декомпрессия'
BackupBeforeRecover: 'Резервное копирование системных данных перед созданием снимка' BackupBeforeRecover: 'Резервное копирование системных данных перед созданием снимка'
Readjson: 'Прочитать файл JSON в снимке' ReadJson: 'Прочитать файл JSON в снимке'
ReadjsonPath: 'Получить путь к файлу JSON в снимке' ReadJsonPath: 'Получить путь к файлу JSON в снимке'
ReadjsonContent: 'Прочитать файл Json' ReadJsonContent: 'Прочитать файл Json'
ReadjsonMarshal: 'Обработка Json escape' ReadJsonMarshal: 'Обработка Json escape'
RecoverApp: 'Восстановить установленные приложения' RecoverApp: 'Восстановить установленные приложения'
RecoverWebsite: 'Восстановить каталог веб-сайта' RecoverWebsite: 'Восстановить каталог веб-сайта'
RecoverAppImage: 'Восстановить резервную копию образа снимка' RecoverAppImage: 'Восстановить резервную копию образа снимка'
@@ -467,9 +424,6 @@ RecoverDaemonJson: 'Восстановить файл конфигурации
RecoverDBData: 'Восстановить данные базы данных' RecoverDBData: 'Восстановить данные базы данных'
RecoverBackups: 'Восстановить локальный каталог резервных копий' RecoverBackups: 'Восстановить локальный каталог резервных копий'
RecoverPanelData: 'Каталог данных восстановления' RecoverPanelData: 'Каталог данных восстановления'
# задача - контейнер
ContainerNewCliet: 'Инициализировать Docker-клиент'
ContainerImagePull: 'Извлечь изображение контейнера {{ .name }}' ContainerImagePull: 'Извлечь изображение контейнера {{ .name }}'
ContainerRemoveOld: 'Удалить исходный контейнер {{ .name }}' ContainerRemoveOld: 'Удалить исходный контейнер {{ .name }}'
ContainerImageCheck: 'Проверьте, нормально ли извлекается изображение' ContainerImageCheck: 'Проверьте, нормально ли извлекается изображение'
@@ -478,22 +432,13 @@ ContainerRecreate: 'Обновление контейнера не удалос
ContainerCreate: 'Создать новый контейнер {{ .name }}' ContainerCreate: 'Создать новый контейнер {{ .name }}'
ContainerCreateFailed: 'Создание контейнера не удалось, удалите неудавшийся контейнер' ContainerCreateFailed: 'Создание контейнера не удалось, удалите неудавшийся контейнер'
ContainerStartCheck: 'Проверить, запущен ли контейнер' ContainerStartCheck: 'Проверить, запущен ли контейнер'
# задача - изображение
ImageBuild: 'Создание изображения' ImageBuild: 'Создание изображения'
ImageBuildStdoutCheck: 'Анализ содержимого выходного изображения'
ImageBuildRes: 'Выходные данные сборки образа: {{ .name }}'
ImagePull: 'Вытащить изображение' ImagePull: 'Вытащить изображение'
ImageRepoAuthFromDB: 'Получить информацию об аутентификации репозитория из базы данных' ImageRepoAuthFromDB: 'Получить информацию об аутентификации репозитория из базы данных'
ImaegPullRes: 'Выход извлечения изображения: {{ .name }}'
ImagePush: 'Отправить изображение' ImagePush: 'Отправить изображение'
ImageRenameTag: 'Изменить тег изображения' ImageRenameTag: 'Изменить тег изображения'
ImageNewTag: 'Новый тег изображения {{ .name }}' ImageNewTag: 'Новый тег изображения {{ .name }}'
ImaegPushRes: 'Вывод push-изображения: {{ .name }}'
ComposeCreate: 'Создать композицию' ComposeCreate: 'Создать композицию'
ComposeCreateRes: 'Составить вывод создания: {{ .name }}'
# задача - веб-сайт
BackupNginxConfig: 'Резервное копирование файла конфигурации OpenResty веб-сайта' BackupNginxConfig: 'Резервное копирование файла конфигурации OpenResty веб-сайта'
CompressFileSuccess: 'Каталог успешно сжат, сжат в {{ .name }}' CompressFileSuccess: 'Каталог успешно сжат, сжат в {{ .name }}'
CompressDir: 'Каталог сжатия' CompressDir: 'Каталог сжатия'
@@ -504,40 +449,27 @@ websiteDir: 'Каталог веб-сайтов'
RecoverFailedStartRollBack: 'Восстановление не удалось, начать откат' RecoverFailedStartRollBack: 'Восстановление не удалось, начать откат'
AppBackupFileIncomplete: 'Файл резервной копии неполный и в нем отсутствуют файлы app.json или app.tar.gz' AppBackupFileIncomplete: 'Файл резервной копии неполный и в нем отсутствуют файлы app.json или app.tar.gz'
AppAttributesNotMatch: 'Тип или имя приложения не совпадают' AppAttributesNotMatch: 'Тип или имя приложения не совпадают'
ErrAlertSync: 'Ошибка синхронизации информации о тревоге, проверьте и повторите попытку'
#тревога ErrInstallExtension: 'Уже выполняется задача установки, подождите, пока задача завершится'
ErrAlert: 'Формат предупреждающего сообщения неверен, проверьте и повторите попытку!' PanelAlertTitle: 'Уведомление панели'
ErrAlertPush: 'Ошибка при отправке оповещения. Проверьте и повторите попытку!' TestAlertTitle: 'Тестовое письмо - проверка подключения'
ErrAlertSave: 'Ошибка сохранения информации о тревоге, проверьте и повторите попытку!' TestAlert: 'Это тестовое письмо для проверки правильности настройки отправки писем.'
ErrAlertSync: 'Ошибка синхронизации информации о тревоге, проверьте и повторите попытку!' LicenseExpirationAlert: 'Ваш панель {{ .node }}{{ .ip }}, лицензия истечет через {{ .day }} дней. Войдите в панель для получения деталей.'
ErrAlertRemote: 'Ошибка удаленного сообщения об ошибке, проверьте и повторите попытку!' CronJobFailedAlert: 'Ваш панель {{ .node }}{{ .ip }}, выполнение запланированной задачи {{ .name }} не удалось. Войдите в панель для получения деталей.'
ClamAlert: 'Ваш панель {{ .node }}{{ .ip }}, задача сканирования на вирусы обнаружила {{ .num }} зараженных файлов. Войдите в панель для получения деталей.'
#task - runtime WebSiteAlert: 'Ваш панель {{ .node }}{{ .ip }}, {{ .num }} веб-сайтов истечут через {{ .day }} дней. Войдите в панель для получения деталей.'
ErrInstallExtension: "Уже выполняется задача установки, подождите, пока задача завершится" SSLAlert: 'Ваш панель {{ .node }}{{ .ip }}, {{ .num }} сертификатов SSL истечут через {{ .day }} дней. Войдите в панель для получения деталей.'
DiskUsedAlert: 'Ваш панель {{ .node }}{{ .ip }}, использование диска {{ .name }} достигло {{ .used }}. Войдите в панель для получения деталей.'
# alert mail template ResourceAlert: 'Ваш панель {{ .node }}{{ .ip }}, средний уровень использования {{ .name }} за {{ .time }} минут составляет {{ .used }}. Войдите в панель для получения деталей.'
PanelAlertTitle: "Уведомление панели" PanelVersionAlert: 'Ваш панель {{ .node }}{{ .ip }}, доступна последняя версия панели для обновления. Войдите в панель для получения деталей.'
TestAlertTitle: "Тестовое письмо - проверка подключения" PanelPwdExpirationAlert: 'Ваш панель {{ .node }}{{ .ip }}, пароль панели истечет через {{ .day }} дней. Войдите в панель для получения деталей.'
TestAlert: "Это тестовое письмо для проверки правильности настройки отправки писем." CommonAlert: 'Ваш панель {{ .node }}{{ .ip }}, {{ .msg }}. Войдите в панель для получения деталей.'
LicenseExpirationAlert: "Ваш панель {{ .node }}{{ .ip }}, лицензия истечет через {{ .day }} дней. Войдите в панель для получения деталей." NodeExceptionAlert: 'Ваш панель {{ .node }}{{ .ip }}, {{ .num }} узлов работают с ошибками. Войдите в панель для получения деталей.'
CronJobFailedAlert: "Ваш панель {{ .node }}{{ .ip }}, выполнение запланированной задачи {{ .name }} не удалось. Войдите в панель для получения деталей." LicenseExceptionAlert: 'Ваш панель {{ .node }}{{ .ip }}, {{ .num }} лицензий имеют ошибки. Войдите в панель для получения деталей.'
ClamAlert: "Ваш панель {{ .node }}{{ .ip }}, задача сканирования на вирусы обнаружила {{ .num }} зараженных файлов. Войдите в панель для получения деталей." SSHAndPanelLoginAlert: 'Ваш панель {{ .node }}{{ .ip }}, вход {{ .name }} с адреса {{ .loginIp }} является аномальным. Войдите в панель для получения деталей.'
WebSiteAlert: "Ваш панель {{ .node }}{{ .ip }}, {{ .num }} веб-сайтов истечут через {{ .day }} дней. Войдите в панель для получения деталей." DeviceNotFound: 'Устройство {{ .name }} не найдено'
SSLAlert: "Ваш панель {{ .node }}{{ .ip }}, {{ .num }} сертификатов SSL истечут через {{ .day }} дней. Войдите в панель для получения деталей." DeviceIsMounted: 'Устройство {{ .name }} подключено, сначала отключите'
DiskUsedAlert: "Ваш панель {{ .node }}{{ .ip }}, использование диска {{ .name }} достигло {{ .used }}. Войдите в панель для получения деталей." PartitionDiskErr: 'Не удалось разделить, {{ .err }}'
ResourceAlert: "Ваш панель {{ .node }}{{ .ip }}, средний уровень использования {{ .name }} за {{ .time }} минут составляет {{ .used }}. Войдите в панель для получения деталей." FormatDiskErr: 'Не удалось отформатировать диск, {{ .err }}'
PanelVersionAlert: "Ваш панель {{ .node }}{{ .ip }}, доступна последняя версия панели для обновления. Войдите в панель для получения деталей." MountDiskErr: 'Не удалось подключить диск, {{ .err }}'
PanelPwdExpirationAlert: "Ваш панель {{ .node }}{{ .ip }}, пароль панели истечет через {{ .day }} дней. Войдите в панель для получения деталей." XfsNotFound: 'Файловая система xfs не обнаружена, сначала установите xfsprogs'
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"
+170 -239
View File
@@ -1,34 +1,28 @@
ErrInvalidParams: 'İstek parametre hatası: {{ .detail }}' ErrInvalidParams: 'İstek geçersiz: {{ .detail }}'
ErrTokenParse: 'Token oluşturma hatası: {{ .detail }}' ErrTokenParse: 'Token hatası: {{ .detail }}'
ErrInitialPassword: 'Orijinal şifre yanlış' ErrInitialPassword: 'Orijinal şifre yanlış'
ErrInternalServer: 'Dahili sunucu hatası: {{ .detail }}' ErrInternalServer: 'Sunucu hatası: {{ .detail }}'
ErrRecordExist: 'Kayıt zaten mevcut' ErrRecordExist: 'Kayıt zaten var'
ErrRecordNotFound: 'Kayıt bulunamadı' ErrRecordNotFound: 'Kayıt bulunamadı'
ErrStructTransform: 'Tür dönüştürme başarısız: {{ .err }}' ErrStructTransform: 'Dönüşüm hatası: {{ .err }}'
ErrNotLogin: 'Kullanıcı giriş yapmamış: {{ .detail }}' ErrNotLogin: 'Oturum açılmamış: {{ .detail }}'
ErrPasswordExpired: 'Mevcut şifrenin süresi dolmuş: {{ .detail }}' ErrPasswordExpired: 'Şifre süresi doldu: {{ .detail }}'
ErrNotSupportType: 'Sistem mevcut türü desteklemiyor: {{ .name }}' ErrNotSupportType: 'Bu tür desteklenmiyor: {{ .name }}'
ErrProxy: 'İstek hatası, lütfen düğüm durumunu kontrol edin: {{ .detail }}' ErrProxy: 'İstek başarısız: {{ .detail }}'
ErrApiConfigStatusInvalid: 'API arayüzüne erişim yasak: {{ .detail }}' ErrApiConfigStatusInvalid: 'API kapalı: {{ .detail }}'
ErrApiConfigKeyInvalid: 'API arayüz anahtarı hatası: {{ .detail }}' ErrApiConfigKeyInvalid: 'Geçersiz API anahtarı: {{ .detail }}'
ErrApiConfigIPInvalid: 'API arayüzünü çağırmak için kullanılan IP beyaz listede değil: {{ .detail }}' ErrApiConfigIPInvalid: 'IP izinli değil: {{ .detail }}'
ErrApiConfigDisable: 'Bu arayüz API arayüz çağrılarının kullanımını yasaklıyor: {{ .detail }}' ErrApiConfigDisable: 'API erişimi kapalı: {{ .detail }}'
ErrApiConfigKeyTimeInvalid: 'API arayüz zaman damgası hatası: {{ .detail }}' ErrApiConfigKeyTimeInvalid: 'Zaman damgası hatalı: {{ .detail }}'
StartPushSSLToNode: "Sertifika düğüme gönderilmeye başlandı" ErrShutDown: 'Komut manuel durduruldu'
PushSSLToNodeFailed: "Sertifika düğüme gönderilemedi: {{ .err }}" ErrMinQuickJump: 'En az bir hızlı erişim ekle'
PushSSLToNodeSuccess: "Sertifika düğüme başarıyla gönderildi" ErrMaxQuickJump: '4 hızlı erişim hakkı var'
ErrShutDown: "Komut manuel olarak sonlandırıldı!" ErrUsernameIsExist: 'Kullanıcı adı mevcut'
ErrNameIsExist: 'İsim mevcut'
ErrMinQuickJump: "Lütfen en az bir hızlı atlama girişi ayarlayın!" ErrDemoEnvironment: 'Demo modunda yok'
ErrMaxQuickJump: "En fazla dört hızlı atlama girişi ayarlayabilirsiniz!" ErrCmdTimeout: 'Komut zaman aşımına uğradı'
ErrCmdIllegal: 'Komut geçersiz karakter içeriyor'
#common ErrPortExist: '{{ .port }} portu {{ .type }} [{{ .name }}] tarafından kullanılıyor'
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'
TYPE_APP: 'Uygulama' TYPE_APP: 'Uygulama'
TYPE_RUNTIME: 'Çalışma ortamı' TYPE_RUNTIME: 'Çalışma ortamı'
TYPE_DOMAIN: 'Alan Adı' TYPE_DOMAIN: 'Alan Adı'
@@ -39,45 +33,39 @@ Failed: 'Başarısız'
SystemRestart: 'Sistem yeniden başlatması nedeniyle görev kesildi' SystemRestart: 'Sistem yeniden başlatması nedeniyle görev kesildi'
ErrGroupIsDefault: 'Varsayılan grup, silinemez' ErrGroupIsDefault: 'Varsayılan grup, silinemez'
ErrGroupIsInWebsiteUse: 'Grup başka bir web sitesi tarafından kullanılıyor ve silinemez.' ErrGroupIsInWebsiteUse: 'Grup başka bir web sitesi tarafından kullanılıyor ve silinemez.'
Decrypt: "Şifre Çöz" Decrypt: 'Şifre Çöz'
ErrAgentAccountBound: 'Hesap bir ajana bağlı'
#agent ErrAgentAccountUnavailable: 'Hesap bağlantısı yok: {{ .err }}'
ErrAgentAccountBound: 'Bu hesap bir ajana bağlı ve silinemez. Kontrol edip tekrar deneyin!' ErrAgentProviderNotSupported: 'Ajans sağlayıcısı desteklenmiyor'
ErrAgentAccountUnavailable: 'Hesap bağlantı bilgileri kullanılamıyor. Hata: {{ .err }}. Kontrol edip tekrar deneyin!' ErrAgentAccountRequired: 'Önce bir ajans hesabı seçin'
ErrAgentProviderNotSupported: 'Bu ajan sağlayıcısı desteklenmiyor. Kontrol edip tekrar deneyin!' ErrAgentAccountNotVerified: 'Ajans hesabı doğrulanmadı'
ErrAgentAccountRequired: 'Lütfen bir ajan hesabı seçip tekrar deneyin.' ErrAgentProviderMismatch: 'Ajans sağlayıcısı eşleşmiyor'
ErrAgentAccountNotVerified: 'Hesap doğrulanmadı. Kontrol edip tekrar deneyin!' ErrAgentBaseURLRequired: 'Temel URL gerekli'
ErrAgentProviderMismatch: 'Hesap sağlayıcısı eşleşmiyor. Kontrol edip tekrar deneyin!' ErrAgentApiKeyRequired: 'API anahtarı gerekli'
ErrAgentBaseURLRequired: 'Base URL boş olamaz. Kontrol edip tekrar deneyin!' ErrAgentComposeRequired: 'Compose içeriği gerekli'
ErrAgentApiKeyRequired: 'API Key boş olamaz. Kontrol edip tekrar deneyin!' ErrAgentIDRequired: 'Ajans ID gerekli'
ErrAgentComposeRequired: 'Özel compose içeriği boş olamaz. Kontrol edip tekrar deneyin!' ErrAgentAccountIDRequired: 'Hesap ID gerekli'
ErrAgentIDRequired: 'Ajan ID boş olamaz. Kontrol edip tekrar deneyin!'
ErrAgentAccountIDRequired: 'Hesap ID boş olamaz. Kontrol edip tekrar deneyin!'
#backup
Localhost: 'Yerel Makine' Localhost: 'Yerel Makine'
ErrBackupInUsed: 'Yedekleme hesabı zamanlanmış görevde kullanıldı ve silinemez.' ErrBackupInUsed: 'Yedek hesabı görevde kullanılıyor'
ErrBackupCheck: 'Yedekleme hesabı test bağlantısı başarısız {{ .err }}' ErrBackupCheck: 'Bağlantı testi başarısız: {{ .err }}'
ErrBackupLocalDelete: 'Yerel sunucu yedekleme hesabını silme henüz desteklenmiyor' ErrBackupLocalDelete: 'Yerel yedek silme yok'
ErrBackupLocalCreate: 'Yerel sunucu yedekleme hesapları oluşturma henüz desteklenmiyor' ErrBackupLocalCreate: 'Yerel yedek oluşturma yok'
ErrPortInUsed: '{{ .detail }} portu zaten kullanılıyor'
#app
ErrPortInUsed: '{{ .detail }} portu zaten kullanılıyor!'
ErrAppLimit: 'Yüklenen uygulama sayısı sınırı aştı' ErrAppLimit: 'Yüklenen uygulama sayısı sınırı aştı'
ErrNotInstall: 'Uygulama yüklenmedi' ErrNotInstall: 'Uygulama yüklenmedi'
ErrPortInOtherApp: '{{ .port }} portu zaten {{ .apps }} uygulaması tarafından kullanılıyor!' ErrPortInOtherApp: '{{ .port }} portu zaten {{ .apps }} uygulaması tarafından kullanılıyor'
ErrDbUserNotValid: 'Mevcut veritabanı, kullanıcı adı ve şifre eşleşmiyor!' 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! ' 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 }}' Err1PanelNetworkFailed: 'Varsayılan konteyner ağ oluşturma başarısız {{ .detail }}'
ErrFileParse: 'Uygulama docker-compose dosya ayrıştırma başarısız!' 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' 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' AppStoreIsUpToDate: 'Uygulama mağazası zaten en son sürüm'
LocalAppVersionNull: '{{ .name }} uygulaması sürüme senkronize edilmedi! Uygulama listesine eklenemez' LocalAppVersionNull: '{{ .name }} uygulaması sürüme senkronize edilmedi Uygulama listesine eklenemez'
LocalAppVersionErr: '{{ .name }} senkronizasyon sürümü {{ .version }} başarısız! {{ .err }}' LocalAppVersionErr: '{{ .name }} senkronizasyon sürümü {{ .version }} başarısız {{ .err }}'
ErrFileNotFound: '{{ .name }} dosyası mevcut değil' ErrFileNotFound: '{{ .name }} dosyası mevcut değil'
ErrFileParseApp: '{{ .name }} dosya ayrıştırma başarısız {{ .err }}' ErrFileParseApp: '{{ .name }} dosya ayrıştırma başarısız {{ .err }}'
ErrAppDirNull: 'Sürüm klasörü mevcut değil' ErrAppDirNull: 'Sürüm klasörü mevcut değil'
LocalAppErr: 'Uygulama {{ .name }} senkronizasyonu başarısız! {{ .err }}' LocalAppErr: 'Uygulama {{ .name }} senkronizasyonu başarısız {{ .err }}'
ErrContainerName: 'Konteyner adı zaten mevcut' ErrContainerName: 'Konteyner adı zaten mevcut'
ErrCreateHttpClient: 'İstek oluşturma başarısız {{ .err }}' ErrCreateHttpClient: 'İstek oluşturma başarısız {{ .err }}'
ErrHttpReqTimeOut: 'İstek zaman aşımı {{ .err }}' ErrHttpReqTimeOut: 'İstek zaman aşımı {{ .err }}'
@@ -90,65 +78,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.' ErrVersionTooLow: 'Mevcut 1Panel sürümü Uygulama Mağazasını güncellemek için çok düşük. Lütfen işlemden önce sürümü yükseltin.'
ErrAppNameExist: 'Uygulama adı zaten mevcut' ErrAppNameExist: 'Uygulama adı zaten mevcut'
AppStoreIsSyncing: 'Uygulama Mağazası senkronize ediliyor, lütfen daha sonra tekrar deneyin' AppStoreIsSyncing: 'Uygulama Mağazası senkronize ediliyor, lütfen daha sonra tekrar deneyin'
ErrGetCompose: 'docker-compose.yml dosyası alınamadı! {{ .detail }}' ErrGetCompose: 'docker-compose.yml dosyası alınamadı {{ .detail }}'
ErrAppWarn: 'Anormal durum, lütfen günlüğü kontrol edin' ErrAppWarn: 'Anormal durum, lütfen günlüğü kontrol edin'
ErrAppParamKey: 'Parametre {{ .name }} alanı anormal' ErrAppParamKey: 'Parametre {{ .name }} alanı anormal'
ErrAppUpgrade: 'Uygulama {{ .name }} yükseltmesi başarısız {{ .err }}' ErrAppUpgrade: 'Uygulama {{ .name }} yükseltmesi başarısız {{ .err }}'
AppRecover: 'Uygulama {{ .name }} geri alma' AppRecover: 'Uygulama {{ .name }} geri alma'
PullImageStart: 'Image [{{ .name }}] çekmeye başla' PullImageStart: 'Image [{{ .name }}] çekmeye başla'
PullImageSuccess: 'Image çekme başarılı' PullImageSuccess: 'Image çekme başarılı'
AppStoreIsLastVersion: 'Uygulama Mağazası zaten en son sürüm'
AppStoreSyncSuccess: 'Uygulama Mağazası senkronizasyonu başarılı' AppStoreSyncSuccess: 'Uygulama Mağazası senkronizasyonu başarılı'
SyncAppDetail: 'Uygulama yapılandırmasını senkronize et' SyncAppDetail: 'Uygulama yapılandırmasını senkronize et'
AppVersionNotMatch: '{{ .name }} uygulaması daha yüksek 1Panel sürümü gerektiriyor, senkronizasyon atlanıyor' 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ı' MoveSiteDirSuccess: 'Web sitesi dizini taşıma başarılı'
DeleteRuntimePHP: 'PHP çalışma zamanını sil' 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' 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' ErrAppIsDown: '{{ .name }} uygulama durumu anormal, lütfen kontrol edin'
ErrCustomApps: 'Yüklü bir uygulama var, lütfen önce kaldırın' ErrCustomApps: 'Yüklü bir uygulama var, lütfen önce kaldırın'
ErrCustomRuntimes: 'Yüklü bir çalışma ortamı var, lütfen önce silin' 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ı" ErrAppVersionDeprecated: '{{ .name }} uygulaması mevcut 1Panel sürümü ile uyumlu değil, atlandı'
ErrDockerFailed: "Docker durumu anormal, lütfen servis durumunu kontrol edin" ErrDockerFailed: 'Docker durumu anormal, lütfen servis durumunu kontrol edin'
ErrDockerComposeCmdNotFound: "Docker Compose komutu mevcut değil, lütfen önce bu komutu host makinesine yükleyin" ErrDockerComposeCmdNotFound: 'Docker Compose komutu mevcut değil, lütfen önce bu komutu host makinesine yükleyin'
UseExistImage: 'Görüntü çekme başarısız, mevcut görüntü kullanılıyor' UseExistImage: 'Görüntü zaten mevcut, mevcut görüntü kullanılıyor'
ErrDatabaseNotFound: '{{ .name }} veritabanı mevcut değil'
#ssh ExportIP: 'Giriş IP'
ExportIP: "Giriş IP" ExportArea: 'Konum'
ExportArea: "Konum" ExportPort: 'Port'
ExportPort: "Port" ExportAuthMode: 'Giriş Yöntemi'
ExportAuthMode: "Giriş Yöntemi" ExportUser: 'Kullanıcı'
ExportUser: "Kullanıcı" ExportStatus: 'Giriş Durumu'
ExportStatus: "Giriş Durumu" ExportDate: 'Zaman'
ExportDate: "Zaman"
#file
ErrFileCanNotRead: 'Bu dosya önizlemeyi desteklemiyor' ErrFileCanNotRead: 'Bu dosya önizlemeyi desteklemiyor'
ErrFileToLarge: 'Dosya 10M dan büyük ve açılamıyor' ErrFileToLarge: 'Dosya 10M dan büyük ve açılamıyor'
ErrPathNotFound: 'Dizin mevcut değil' ErrPathNotFound: 'Dizin mevcut değil'
ErrMovePathFailed: 'Hedef yol orijinal yolu içeremez!' ErrMovePathFailed: 'Hedef yol orijinal yolu içeremez'
ErrLinkPathNotFound: 'Hedef yol mevcut değil!' ErrLinkPathNotFound: 'Hedef yol mevcut değil'
ErrFileIsExist: 'Dosya veya klasör zaten mevcut!' ErrFileIsExist: 'Dosya veya klasör zaten mevcut'
ErrFileUpload: '{{ .name }} dosya yükleme başarısız {{ .detail }}' ErrFileUpload: '{{ .name }} dosya yükleme başarısız {{ .detail }}'
ErrFileDownloadDir: 'Klasör indirme desteklenmiyor' 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' ErrSourcePathNotFound: 'Kaynak dizin mevcut değil'
ErrFavoriteExist: 'Bu yol zaten favorilere eklendi' ErrFavoriteExist: 'Bu yol zaten favorilere eklendi'
ErrInvalidChar: 'Yasak karakterlere izin verilmiyor' ErrInvalidChar: 'Yasak karakterlere izin verilmiyor'
ErrPathNotDelete: 'Seçilen dizin silinemez' ErrPathNotDelete: 'Seçilen dizin silinemez'
ErrLogFileToLarge: "Günlük dosyası 500MB'ı aşıyor ve açılamıyor" ErrLogFileToLarge: 'Günlük dosyası 500MB''ı aşıyor ve açılamıyor'
FileDropFailed: "{{ .name }} dosyası temizlenemedi: {{ .err }}" FileDropFailed: '{{ .name }} dosyası temizlenemedi: {{ .err }}'
FileDropSuccess: "{{ .name }} dosyası başarıyla temizlendi, {{ .count }} dosya silindi, {{ .size }} disk alanı boşaltıldı" FileDropSuccess: '{{ .name }} dosyası başarıyla temizlendi, {{ .count }} dosya silindi, {{ .size }} disk alanı boşaltıldı'
FileDropSum: "Dosya temizleme tamamlandı, toplam {{ .count }} dosya silindi, toplam {{ .size }} disk alanı boşaltıldı" FileDropSum: 'Dosya temizleme tamamlandı, toplam {{ .count }} dosya silindi, toplam {{ .size }} disk alanı boşaltıldı'
ErrBadDecrypt: "Sıkıştırılmış paket şifre çözme parolası hatalı, açma başarısız, lütfen kontrol edip tekrar deneyin!" ErrBadDecrypt: 'Sıkıştırılmış paket şifre çözme parolası hatalı, açma başarısız, lütfen kontrol edip tekrar deneyin'
#website
ErrAliasIsExist: 'Takma ad zaten mevcut' ErrAliasIsExist: 'Takma ad zaten mevcut'
ErrBackupMatch: 'Yedekleme dosyası mevcut web sitesi verilerinin bir kısmıyla eşleşmiyor {{ .detail }}' ErrBackupMatch: 'Yedekleme dosyası mevcut web sitesi verilerinin bir kısmıyla eşleşmiyor {{ .detail }}'
ErrBackupExist: 'Yedekleme dosyasındaki kaynak verilerin karşılık gelen kısmı mevcut değil {{ .detail }}' ErrBackupExist: 'Yedekleme dosyasındaki kaynak verilerin karşılık gelen kısmı mevcut değil {{ .detail }}'
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' 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' ErrDomainIsUsed: 'Alan adı zaten [{{ .name }}] web sitesi tarafından kullanılıyor'
ErrDomainFormat: '{{ .name }} alan adı formatı yanlış' ErrDomainFormat: '{{ .name }} alan adı formatı yanlış'
@@ -156,11 +137,11 @@ ErrDefaultAlias: 'default ayrılmış bir kod, lütfen başka bir kod kullanın'
ErrParentWebsite: 'Önce {{ .name }} alt sitesini silmeniz gerekiyor' ErrParentWebsite: 'Önce {{ .name }} alt sitesini silmeniz gerekiyor'
ErrBuildDirNotFound: 'Yapı dizini mevcut değil' ErrBuildDirNotFound: 'Yapı dizini mevcut değil'
ErrImageNotExist: 'İşletim ortamı {{ .name }} image mevcut değil, lütfen işletim ortamını yeniden düzenleyin' 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" ErrProxyIsUsed: 'Yük dengeleme ters proxy tarafından kullanıldı, silinemez'
ErrSSLValid: 'Sertifika dosyası anormal, lütfen sertifika durumunu kontrol edin!' ErrSSLValid: 'Sertifika dosyası anormal, lütfen sertifika durumunu kontrol edin'
ErrWebsiteDir: "Lütfen web sitesi dizini içindeki bir dizin seçin." ErrWebsiteDir: 'Lütfen web sitesi dizini içindeki bir dizin seçin.'
ErrComposerFileNotFound: "composer.json dosyası mevcut değil" 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." ErrRuntimeNoPort: 'Çalışma zamanı ortamı bir porta sahip değil, lütfen önce çalışma zamanı ortamını düzenleyin.'
Status: 'Durum' Status: 'Durum'
start: 'Başlat' start: 'Başlat'
stop: 'Durdur' stop: 'Durdur'
@@ -170,14 +151,12 @@ pause: 'Duraklat'
unpause: 'Devam Et' unpause: 'Devam Et'
remove: 'Sil' remove: 'Sil'
delete: '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' SSL: 'Sertifika'
Set: 'Ayarlar' Set: 'Ayarlar'
#ssl
ErrSSLCannotDelete: '{{ .name }} sertifikası bir web sitesi tarafından kullanılıyor ve silinemez' ErrSSLCannotDelete: '{{ .name }} sertifikası bir web sitesi tarafından kullanılıyor ve silinemez'
ErrAccountCannotDelete: 'Hesap bir sertifikayla ilişkili ve silinemez' ErrAccountCannotDelete: 'Hesap bir sertifikayla ilişkili ve silinemez'
ErrSSLApply: 'Sertifika yenileme başarılı, openresty yeniden yükleme başarısız, lütfen yapılandırmayı kontrol edin!' ErrSSLApply: 'Sertifika yenileme başarılı, openresty yeniden yükleme başarısız, lütfen yapılandırmayı kontrol edin'
ErrEmailIsExist: 'Posta kutusu zaten mevcut' ErrEmailIsExist: 'Posta kutusu zaten mevcut'
ErrSSLKeyNotFound: 'Özel anahtar dosyası mevcut değil' ErrSSLKeyNotFound: 'Özel anahtar dosyası mevcut değil'
ErrSSLCertificateNotFound: 'Sertifika dosyası mevcut değil' ErrSSLCertificateNotFound: 'Sertifika dosyası mevcut değil'
@@ -185,12 +164,12 @@ ErrSSLKeyFormat: 'Özel anahtar dosyası doğrulama başarısız'
ErrSSLCertificateFormat: 'Sertifika dosyası formatı yanlış, lütfen pem formatını kullanın' ErrSSLCertificateFormat: 'Sertifika dosyası formatı yanlış, lütfen pem formatını kullanın'
ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid veya EabHmacKey boş olamaz' ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid veya EabHmacKey boş olamaz'
ErrOpenrestyNotFound: 'Http modu önce Openresty yüklenmesini gerektiriyor' 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' dnsAccount: 'DNS Otomatik'
dnsManual: 'DNS Manuel' dnsManual: 'DNS Manuel'
http: 'HTTP' http: 'HTTP'
ApplySSLFailed: '[{{ .domain }}] sertifika başvurusu başarısız, {{ .detail }} ' ApplySSLFailed: '[{{ .domain }}] sertifika başvurusu başarısız, {{ .detail }}'
ApplySSLSuccess: '[{{ .domain }}] sertifika başvurusu başarılı! !' ApplySSLSuccess: '[{{ .domain }}] sertifika başvurusu başarılı'
DNSAccountName: 'DNS hesabı [{{ .name }}] sağlayıcı [{{ .type }}]' DNSAccountName: 'DNS hesabı [{{ .name }}] sağlayıcı [{{ .type }}]'
PushDirLog: 'Sertifika [{{ .path }}] dizinine gönderildi {{ .status }}' PushDirLog: 'Sertifika [{{ .path }}] dizinine gönderildi {{ .status }}'
ErrDeleteCAWithSSL: 'Mevcut kuruluşun verilmiş bir sertifikası var ve silinemez.' ErrDeleteCAWithSSL: 'Mevcut kuruluşun verilmiş bir sertifikası var ve silinemez.'
@@ -205,94 +184,79 @@ ExecShellSuccess: 'Betik yürütme başarılı'
StartUpdateSystemSSL: 'Sistem sertifikası güncellemeyi başlat' StartUpdateSystemSSL: 'Sistem sertifikası güncellemeyi başlat'
UpdateSystemSSLSuccess: 'Sistem sertifikası güncelleme başarılı' UpdateSystemSSLSuccess: 'Sistem sertifikası güncelleme başarılı'
ErrWildcardDomain: 'HTTP modunda joker alan adı sertifikası başvurusu yapılamıyor' ErrWildcardDomain: 'HTTP modunda joker alan adı sertifikası başvurusu yapılamıyor'
ErrApplySSLCanNotDelete: "İşlemde olan sertifika {{.name}} silinemez, lütfen daha sonra tekrar deneyin." ErrApplySSLCanNotDelete: 'İşlemde olan sertifika {{ .name }} silinemez, lütfen daha sonra tekrar deneyin.'
StartPushSSLToNode: 'Sertifika düğüme gönderilmeye başlandı'
#mysql 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' ErrUserIsExist: 'Mevcut kullanıcı zaten mevcut, lütfen yeniden girin'
ErrDatabaseIsExist: 'Mevcut veritabanı zaten mevcut, lütfen yeniden girin' ErrDatabaseIsExist: 'Mevcut veritabanı zaten mevcut, lütfen yeniden girin'
ErrExecTimeOut: 'SQL yürütme zaman aşımı, lütfen veritabanını kontrol edin' ErrExecTimeOut: 'SQL yürütme zaman aşımı, lütfen veritabanını kontrol edin'
ErrRemoteExist: 'Uzak veritabanında bu adla zaten mevcut, lütfen değiştirin ve tekrar deneyin' 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' 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..." RemoteBackup: 'Uzak veritabanını yedeklemek için önce {{ .name }} görüntüsü kullanılarak yerel konteyner veritabanı hizmetinin başlatılması gerekiyor, lütfen bekleyin...'
RemoteRecover: "Uzak veritabanını geri yüklemek için önce {{ .name }} görüntüsü kullanılarak yerel konteyner veritabanı hizmetinin başlatılması gerekiyor, lütfen bekleyin..." RemoteRecover: 'Uzak veritabanını geri yüklemek için önce {{ .name }} görüntüsü kullanılarak yerel konteyner veritabanı hizmetinin başlatılması gerekiyor, lütfen bekleyin...'
Arg: "Argüman" Arg: 'Argüman'
#redis
ErrTypeOfRedis: 'Kurtarma dosyası türü mevcut kalıcılık yöntemiyle eşleşmiyor, lütfen değiştirin ve tekrar deneyin' ErrTypeOfRedis: 'Kurtarma dosyası türü mevcut kalıcılık yöntemiyle eşleşmiyor, lütfen değiştirin ve tekrar deneyin'
ErrInUsed: '{{ .detail }} kullanımda ve silinemez'
#container ErrObjectInUsed: 'Bu nesne kullanımda ve silinemez'
ErrInUsed: "{{ .detail }} kullanımda ve silinemez!" ErrObjectBeDependent: 'Bu görüntü diğer görüntüler tarafından bağımlıdır ve silinemez'
ErrObjectInUsed: "Bu nesne kullanımda ve silinemez!" ErrPortRules: 'Port numarası eşleşmiyor, lütfen yeniden girin'
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' 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ı" PruneHelper: 'Bu temizlik {{ .name }} disk alanı {{ .size }} boşalttı'
ImageRemoveHelper: "{{ .name }} imajı silindi, {{ .size }} disk alanı boşalttı" ImageRemoveHelper: '{{ .name }} imajı silindi, {{ .size }} disk alanı boşalttı'
BuildCache: "Derleme önbelleği" BuildCache: 'Derleme önbelleği'
Volume: "Depolama hacmi" Volume: 'Depolama hacmi'
Network: "Ağ" Network: 'Ağ'
PruneStart: "Temizlik devam ediyor, lütfen bekleyin..." PruneStart: 'Temizlik devam ediyor, lütfen bekleyin...'
ErrFileNotExist: '{{ .detail }} dosyası mevcut değil Lütfen kaynak dosyanın bütünlüğünü kontrol edin'
#runtime
ErrFileNotExist: '{{ .detail }} dosyası mevcut değil! Lütfen kaynak dosyanın bütünlüğünü kontrol edin!'
ErrImageBuildErr: 'Image yapı başarısız' ErrImageBuildErr: 'Image yapı başarısız'
ErrImageExist: "Görüntü zaten var! Lütfen görüntü adını değiştirin." ErrImageExist: 'Görüntü zaten var Lütfen görüntü adını değiştirin.'
ErrDelWithWebsite: 'İşletim ortamı zaten bir web sitesiyle ilişkili ve silinemez' ErrDelWithWebsite: 'İşletim ortamı zaten bir web sitesiyle ilişkili ve silinemez'
ErrRuntimeStart: 'Başlatma başarısız' ErrRuntimeStart: 'Başlatma başarısız'
ErrPackageJsonNotFound: 'package.json dosyası mevcut değil' ErrPackageJsonNotFound: 'package.json dosyası mevcut değil'
ErrScriptsNotFound: 'package.json içinde scripts yapılandırma öğesi bulunamadı' ErrScriptsNotFound: 'package.json içinde scripts yapılandırma öğesi bulunamadı'
ErrContainerNameNotFound: 'Konteyner adı alınamıyor, lütfen .env dosyasını kontrol edin' 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' 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' ErrContainerNameIsNull: 'Konteyner adı mevcut değil'
ErrPHPPortIsDefault: "9000 portu varsayılan port, lütfen değiştirin ve tekrar deneyin" ErrPHPPortIsDefault: '9000 portu varsayılan port, lütfen değiştirin ve tekrar deneyin'
ErrPHPRuntimePortFailed: "{{ .name }} portu mevcut çalışma ortamı tarafından zaten kullanılıyor, lütfen değiştirin ve tekrar deneyin" ErrPHPRuntimePortFailed: '{{ .name }} portu mevcut çalışma ortamı tarafından zaten kullanılıyor, lütfen değiştirin ve tekrar deneyin'
#tool
ErrConfigNotFound: 'Yapılandırma dosyası mevcut değil' ErrConfigNotFound: 'Yapılandırma dosyası mevcut değil'
ErrConfigParse: 'Yapılandırma dosyası formatı yanlış' ErrConfigParse: 'Yapılandırma dosyası formatı yanlış'
ErrConfigIsNull: 'Yapılandırma dosyası boş olamaz' ErrConfigIsNull: 'Yapılandırma dosyası boş olamaz'
ErrConfigDirNotFound: 'Çalışma dizini mevcut değil' ErrConfigDirNotFound: 'Çalışma dizini mevcut değil'
ErrConfigAlreadyExist: 'Aynı ada sahip bir yapılandırma dosyası zaten mevcut' ErrConfigAlreadyExist: 'Aynı ada sahip bir yapılandırma dosyası zaten mevcut'
ErrUserFindErr: 'Kullanıcı {{ .name }} arama başarısız {{ .err }}' ErrUserFindErr: 'Kullanıcı {{ .name }} arama başarısız {{ .err }}'
#cronjob
CutWebsiteLogSuccess: '{{ .name }} web sitesi günlüğü başarıyla kesildi, yedekleme yolu {{ .path }}' CutWebsiteLogSuccess: '{{ .name }} web sitesi günlüğü başarıyla kesildi, yedekleme yolu {{ .path }}'
HandleShell: 'Betik {{ .name }} yürüt' HandleShell: 'Betik {{ .name }} yürüt'
HandleCurl: "URL'ye Eriş {{ .name }}" HandleCurl: 'URL''ye Eriş {{ .name }}'
HandleNtpSync: 'Sistem zaman senkronizasyonu' HandleNtpSync: 'Sistem zaman senkronizasyonu'
HandleSystemClean: 'Sistem önbellek temizliği' HandleSystemClean: 'Sistem önbellek temizliği'
SystemLog: 'Sistem Günlüğü' SystemLog: 'Sistem Günlüğü'
CutWebsiteLog: 'Web Sitesi Günlüğünü Döndür' CutWebsiteLog: 'Web Sitesi Günlüğünü Döndür'
FileOrDir: 'Dizin / Dosya' FileOrDir: 'Dizin / Dosya'
UploadFile: 'Yedekleme dosyası {{ .file }} {{ .backup }} konumuna yükleniyor' UploadFile: 'Yedekleme dosyası {{ .file }} {{ .backup }} konumuna yükleniyor'
Upload: "Yükle" Upload: 'Yükle'
IgnoreBackupErr: "Yedekleme başarısız, hata: {{ .detail }}, bu hata yoksayılıyor..." 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..." IgnoreUploadErr: 'Yükleme başarısız, hata: {{ .detail }}, bu hata yoksayılıyor...'
LoadBackupFailed: "Yedek hesap bağlantısı alınamadı, hata: {{ .detail }}" 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!" 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..." NoSuchResource: 'Veritabanında yedek içeriği bulunamadı, atlanıyor...'
CleanLog: "Günlüğü temizle" CleanLog: 'Günlüğü temizle'
CleanLogByName: "{{.name}} günlüğünü temizle" CleanLogByName: '{{ .name }} günlüğünü temizle'
WafIpGroupNotFound: "WAF IP grubu bulunamadı. Lütfen [Gelişmiş Özellikler - WAF - Kara/Beyaz Liste - IP Grubu] bölümüne giderek uzaktan indirme yöntemiyle bir IP grubu ekleyin." WafIpGroupNotFound: 'WAF IP grubu bulunamadı. Lütfen [Gelişmiş Özellikler - WAF - Kara/Beyaz Liste - IP Grubu] bölümüne giderek uzaktan indirme yöntemiyle bir IP grubu ekleyin.'
ErrNotExistUser: 'Mevcut kullanıcı mevcut değil, lütfen değiştirin ve tekrar deneyin'
#toolbox ErrBanAction: 'Ayarlama başarısız. Mevcut {{ .name }} servisi kullanılamıyor. Lütfen kontrol edin ve tekrar deneyin'
ErrNotExistUser: 'Mevcut kullanıcı mevcut değil, lütfen değiştirin ve tekrar deneyin!' ErrClamdscanNotFound: 'clamdscan komutu tespit edilmedi, lütfen yüklemek için belgeleri inceleyin'
ErrBanAction: 'Ayarlama başarısız. Mevcut {{ .name }} servisi kullanılamıyor. Lütfen kontrol edin ve tekrar deneyin!' TaskSwapSet: 'Swap Ayarla'
ErrClamdscanNotFound: 'clamdscan komutu tespit edilmedi, lütfen yüklemek için belgeleri inceleyin!' SetSwap: 'Swap Ayarla {{ .path }} - {{ .size }}'
TaskSwapSet: "Swap Ayarla" CreateSwap: 'Swap Dosyası Oluştur'
SetSwap: "Swap Ayarla {{ .path }} - {{ .size }}" FormatSwap: 'Swap Dosyasını Biçimlendir'
CreateSwap: "Swap Dosyası Oluştur" EnableSwap: 'Swap Etkinleştir'
FormatSwap: "Swap Dosyasını Biçimlendir" CleanTamperSetting: 'Geçmiş koruma ayarlarını temizle'
EnableSwap: "Swap Etkinleştir" SetTamperWithRules: 'Kurallara göre dizin korumasını başlat'
ProtectDir: 'Dizini koru {{ .name }}'
#tamper IgnoreFile: 'Dosyayı koru {{ .name }}'
CleanTamperSetting: "Geçmiş koruma ayarlarını temizle" TamperSetSuccessful: 'Koruma ayarları tamamlandı, aşağıdaki dizinler izlenmeye başlanıyor:'
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
ErrScope: 'Bu yapılandırmayı değiştirme desteklenmiyor' ErrScope: 'Bu yapılandırmayı değiştirme desteklenmiyor'
ErrStateChange: 'Durum değiştirme başarısız' ErrStateChange: 'Durum değiştirme başarısız'
ErrRuleExist: 'Kural zaten mevcut' ErrRuleExist: 'Kural zaten mevcut'
@@ -300,7 +264,7 @@ ErrRuleNotExist: 'Kural mevcut değil'
ErrParseIP: 'Yanlış IP formatı' ErrParseIP: 'Yanlış IP formatı'
ErrDefaultIP: 'default ayrılmış bir isim, lütfen başka bir isme değiştirin' 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' 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' ErrGroupExist: 'IP grup adı zaten mevcut'
ErrIPRange: 'Yanlış IP aralığı' ErrIPRange: 'Yanlış IP aralığı'
ErrIPExist: 'IP zaten mevcut' ErrIPExist: 'IP zaten mevcut'
@@ -311,10 +275,10 @@ xss: 'XSS'
phpExec: 'PHP betik yürütme' phpExec: 'PHP betik yürütme'
oneWordTrojan: 'Tek Kelime Truva Atı' oneWordTrojan: 'Tek Kelime Truva Atı'
appFilter: 'Tehlikeli dizin filtreleme uygula' appFilter: 'Tehlikeli dizin filtreleme uygula'
webshell: 'Webshell' webShell: 'Webshell'
args: 'Parametre kuralları' args: 'Parametre kuralları'
protocolFilter: 'Protokol filtreleme' protocolFilter: 'Protokol filtreleme'
javaFileter: 'Java tehlikeli dosya filtresi' javaFilter: 'Java tehlikeli dosya filtresi'
scannerFilter: 'Tarayıcı filtresi' scannerFilter: 'Tarayıcı filtresi'
escapeFilter: 'kaçış filtresi' escapeFilter: 'kaçış filtresi'
customRule: 'Özel kural' customRule: 'Özel kural'
@@ -344,10 +308,9 @@ ErrDBNotExist: 'Veritabanı mevcut değil'
allow: 'izin ver' allow: 'izin ver'
deny: 'reddet' deny: 'reddet'
OpenrestyNotFound: 'Openresty yüklü değil' OpenrestyNotFound: 'Openresty yüklü değil'
remoteIpIsNull: "IP listesi boş" 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" 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'
#task
TaskStart: '{{ .name }} görevi başlıyor [BAŞLAT]' TaskStart: '{{ .name }} görevi başlıyor [BAŞLAT]'
TaskEnd: '{{ .name }} Görev tamamlandı [TAMAMLANDI]' TaskEnd: '{{ .name }} Görev tamamlandı [TAMAMLANDI]'
TaskFailed: '{{ .name }} görev başarısız' TaskFailed: '{{ .name }} görev başarısız'
@@ -363,7 +326,7 @@ TaskDelete: 'Sil'
TaskUpgrade: 'Yükselt' TaskUpgrade: 'Yükselt'
TaskUpdate: 'Güncelle' TaskUpdate: 'Güncelle'
TaskRestart: 'Yeniden Başlat' TaskRestart: 'Yeniden Başlat'
TaskProtect: "Koru" TaskProtect: 'Koru'
TaskBackup: 'Yedekle' TaskBackup: 'Yedekle'
TaskRecover: 'Kurtar' TaskRecover: 'Kurtar'
TaskRollback: 'Geri Al' TaskRollback: 'Geri Al'
@@ -371,10 +334,10 @@ TaskPull: 'Çek'
TaskCommit: 'işleme' TaskCommit: 'işleme'
TaskBuild: 'Yapı' TaskBuild: 'Yapı'
TaskPush: 'Gönder' TaskPush: 'Gönder'
TaskClean: "Temizleme" TaskClean: 'Temizleme'
TaskHandle: 'Yürüt' TaskHandle: 'Yürüt'
TaskImport: "İçe Aktar" TaskImport: 'İçe Aktar'
TaskExport: "Dışa Aktar" TaskExport: 'Dışa Aktar'
Website: 'Web Sitesi' Website: 'Web Sitesi'
App: 'Uygulama' App: 'Uygulama'
Runtime: 'Çalışma ortamı' Runtime: 'Çalışma ortamı'
@@ -406,18 +369,12 @@ RuntimeExtension: 'Çalışma Ortamı Uzantısı'
TaskIsExecuting: 'Görev çalışıyor' TaskIsExecuting: 'Görev çalışıyor'
CustomAppstore: 'Özel uygulama deposu' CustomAppstore: 'Özel uygulama deposu'
TaskExec: 'Çalıştır' TaskExec: 'Çalıştır'
TaskBatch: "Toplu İşlem" TaskBatch: 'Toplu İşlem'
FileConvert: 'Dosya Formatı Dönüştürme' FileConvert: 'Dosya Formatı Dönüştürme'
Clamscan: '{{ .name }} Tara'
# task - clam TaskScan: 'Tara'
Clamscan: "{{ .name }} Tara"
TaskScan: "Tara"
# task - ai
OllamaModelPull: 'Ollama modeli {{ .name }} çek' OllamaModelPull: 'Ollama modeli {{ .name }} çek'
OllamaModelSize: 'Ollama modeli {{ .name }} boyutunu al' OllamaModelSize: 'Ollama modeli {{ .name }} boyutunu al'
# task-snapshot
Snapshot: 'Anlık Görüntü' Snapshot: 'Anlık Görüntü'
SnapDBInfo: '1Panel veritabanı bilgilerini yaz' SnapDBInfo: '1Panel veritabanı bilgilerini yaz'
SnapCopy: 'Dosya ve dizinleri {{ .name }} kopyala' SnapCopy: 'Dosya ve dizinleri {{ .name }} kopyala'
@@ -443,7 +400,6 @@ SnapCompressSize: 'Anlık görüntü dosya boyutu {{ .name }}'
SnapUpload: 'Anlık görüntü dosyasını yükle' SnapUpload: 'Anlık görüntü dosyasını yükle'
SnapUploadTo: 'Anlık görüntü dosyasını {{ .name }} konumuna 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' SnapUploadRes: 'Anlık görüntü dosyasını {{ .name }} konumuna yükle'
SnapshotRecover: 'Anlık Görüntü Geri Yükleme' SnapshotRecover: 'Anlık Görüntü Geri Yükleme'
RecoverDownload: 'Anlık görüntü dosyasını indir' RecoverDownload: 'Anlık görüntü dosyasını indir'
Download: 'İndir' Download: 'İndir'
@@ -451,10 +407,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' RecoverDecompress: 'Anlık görüntü sıkıştırılmış dosyalarını açma'
Decompress: 'Açma' Decompress: 'Açma'
BackupBeforeRecover: 'Anlık görüntü öncesi sistem ilgili verileri yedekleme' BackupBeforeRecover: 'Anlık görüntü öncesi sistem ilgili verileri yedekleme'
Readjson: 'Anlık görüntüdeki Json dosyasını oku' ReadJson: 'Anlık görüntüdeki Json dosyasını oku'
ReadjsonPath: 'Anlık görüntüdeki Json dosya yolunu al' ReadJsonPath: 'Anlık görüntüdeki Json dosya yolunu al'
ReadjsonContent: 'Json dosyasını oku' ReadJsonContent: 'Json dosyasını oku'
ReadjsonMarshal: 'Json kaçış işlemesi' ReadJsonMarshal: 'Json kaçış işlemesi'
RecoverApp: 'Yüklü uygulamaları geri yükle' RecoverApp: 'Yüklü uygulamaları geri yükle'
RecoverWebsite: 'Web sitesi dizinini kurtar' RecoverWebsite: 'Web sitesi dizinini kurtar'
RecoverAppImage: 'Anlık görüntü imaj yedeklemesini geri yükle' RecoverAppImage: 'Anlık görüntü imaj yedeklemesini geri yükle'
@@ -468,9 +424,6 @@ RecoverDaemonJson: 'Konteyner yapılandırma daemon.json dosyasını geri yükle
RecoverDBData: 'Veritabanı verilerini kurtar' RecoverDBData: 'Veritabanı verilerini kurtar'
RecoverBackups: 'Yerel yedekleme dizinini geri yükle' RecoverBackups: 'Yerel yedekleme dizinini geri yükle'
RecoverPanelData: 'Veri dizinini kurtar' RecoverPanelData: 'Veri dizinini kurtar'
# task - container
ContainerNewCliet: 'Docker İstemcisini Başlat'
ContainerImagePull: 'Konteyner imajını çek {{ .name }}' ContainerImagePull: 'Konteyner imajını çek {{ .name }}'
ContainerRemoveOld: 'Orijinal konteyneri kaldır {{ .name }}' ContainerRemoveOld: 'Orijinal konteyneri kaldır {{ .name }}'
ContainerImageCheck: 'İmajın normal çekilip çekilmediğini kontrol et' ContainerImageCheck: 'İmajın normal çekilip çekilmediğini kontrol et'
@@ -479,22 +432,13 @@ ContainerRecreate: 'Konteyner güncellemesi başarısız, şimdi orijinal kontey
ContainerCreate: 'Yeni konteyner oluştur {{ .name }}' ContainerCreate: 'Yeni konteyner oluştur {{ .name }}'
ContainerCreateFailed: 'Konteyner oluşturma başarısız, başarısız konteyneri sil' ContainerCreateFailed: 'Konteyner oluşturma başarısız, başarısız konteyneri sil'
ContainerStartCheck: 'Konteynerin başlatılıp başlatılmadığını kontrol et' ContainerStartCheck: 'Konteynerin başlatılıp başlatılmadığını kontrol et'
# task - image
ImageBuild: 'İmaj Oluşturma' ImageBuild: 'İmaj Oluşturma'
ImageBuildStdoutCheck: 'İmaj çıktı içeriğini ayrıştır'
ImageBuildRes: 'İmaj oluşturma çıktısı: {{ .name }}'
ImagePull: 'İmaj çek' ImagePull: 'İmaj çek'
ImageRepoAuthFromDB: 'Veritabanından depo kimlik doğrulama bilgilerini al' ImageRepoAuthFromDB: 'Veritabanından depo kimlik doğrulama bilgilerini al'
ImaegPullRes: 'İmaj çekme çıktısı: {{ .name }}'
ImagePush: 'İmaj gönder' ImagePush: 'İmaj gönder'
ImageRenameTag: 'İmaj etiketini değiştir' ImageRenameTag: 'İmaj etiketini değiştir'
ImageNewTag: 'Yeni imaj etiketi {{ .name }}' ImageNewTag: 'Yeni imaj etiketi {{ .name }}'
ImaegPushRes: 'İmaj gönderme çıktısı: {{ .name }}'
ComposeCreate: 'Kompozisyon oluştur' ComposeCreate: 'Kompozisyon oluştur'
ComposeCreateRes: 'Compose oluşturma çıktısı: {{ .name }}'
# task - website
BackupNginxConfig: 'Web sitesi OpenResty yapılandırma dosyasını yedekle' BackupNginxConfig: 'Web sitesi OpenResty yapılandırma dosyasını yedekle'
CompressFileSuccess: 'Dizin başarıyla sıkıştırıldı, şuraya sıkıştırıldı {{ .name }}' CompressFileSuccess: 'Dizin başarıyla sıkıştırıldı, şuraya sıkıştırıldı {{ .name }}'
CompressDir: 'Sıkıştırma dizini' CompressDir: 'Sıkıştırma dizini'
@@ -505,40 +449,27 @@ websiteDir: 'Web Sitesi Dizini'
RecoverFailedStartRollBack: 'Kurtarma başarısız, geri almayı başlat' RecoverFailedStartRollBack: 'Kurtarma başarısız, geri almayı başlat'
AppBackupFileIncomplete: 'Yedekleme dosyası eksik ve app.json veya app.tar.gz dosyalarından yoksun' AppBackupFileIncomplete: 'Yedekleme dosyası eksik ve app.json veya app.tar.gz dosyalarından yoksun'
AppAttributesNotMatch: 'Uygulama türü veya adı eşleşmiyor' AppAttributesNotMatch: 'Uygulama türü veya adı eşleşmiyor'
ErrAlertSync: 'Alarm bilgisi senkronizasyon hatası, lütfen kontrol edin ve tekrar deneyin'
#alert ErrInstallExtension: 'Zaten devam eden bir kurulum görevi var, görevin bitmesini bekleyin'
ErrAlert: 'Uyarı mesajının formatı yanlış, lütfen kontrol edin ve tekrar deneyin!' PanelAlertTitle: 'Panel Uyarı Bildirimi'
ErrAlertPush: 'Uyarı bilgisi gönderiminde hata, lütfen kontrol edin ve tekrar deneyin!' TestAlertTitle: 'Test E-postası - E-posta Bağlantısını Doğrula'
ErrAlertSave: 'Alarm bilgisini kaydetmede hata, lütfen kontrol edin ve tekrar deneyin!' 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.'
ErrAlertSync: 'Alarm bilgisi senkronizasyon hatası, lütfen kontrol edin ve tekrar deneyin!' LicenseExpirationAlert: 'Paneliniz {{ .node }}{{ .ip }}, lisans {{ .day }} gün içinde süresi dolacak. Detaylar için paneline giriş yapın.'
ErrAlertRemote: 'Alarm mesajı uzak hata, lütfen kontrol edin ve tekrar deneyin!' 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.'
#task - runtime WebSiteAlert: 'Paneliniz {{ .node }}{{ .ip }}, {{ .num }} web sitesi {{ .day }} gün içinde süresi dolacak. Detaylar için paneline giriş yapın.'
ErrInstallExtension: "Zaten devam eden bir kurulum görevi var, görevin bitmesini bekleyin" 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.'
# alert mail template ResourceAlert: 'Paneliniz {{ .node }}{{ .ip }}, son {{ .time }} dakika içindeki ortalama {{ .name }} kullanım oranı {{ .used }}''dır. Detaylar için paneline giriş yapın.'
PanelAlertTitle: "Panel Uyarı Bildirimi" PanelVersionAlert: 'Paneliniz {{ .node }}{{ .ip }}, en son panel sürümü yükseltme için mevcut. Detaylar için paneline giriş yapın.'
TestAlertTitle: "Test E-postası - E-posta Bağlantısını Doğrula" PanelPwdExpirationAlert: 'Paneliniz {{ .node }}{{ .ip }}, panel şifresi {{ .day }} gün içinde süresi dolacak. Detaylar için paneline giriş yapın.'
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." CommonAlert: 'Paneliniz {{ .node }}{{ .ip }}, {{ .msg }}. Detaylar için paneline giriş yapın.'
LicenseExpirationAlert: "Paneliniz {{ .node }}{{ .ip }}, lisans {{ .day }} gün içinde süresi dolacak. Detaylar için paneline giriş yapın." NodeExceptionAlert: 'Paneliniz {{ .node }}{{ .ip }}, {{ .num }} düğüm anormal durumda. 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." LicenseExceptionAlert: 'Paneliniz {{ .node }}{{ .ip }}, {{ .num }} lisans anormal durumda. 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." SSHAndPanelLoginAlert: 'Paneliniz {{ .node }}{{ .ip }}, {{ .loginIp }} adresinden {{ .name }} girişi anormal. 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." DeviceNotFound: 'Cihaz {{ .name }} bulunamadı'
SSLAlert: "Paneliniz {{ .node }}{{ .ip }}, {{ .num }} SSL sertifikası {{ .day }} gün içinde süresi dolacak. Detaylar için paneline giriş yapın." DeviceIsMounted: 'Cihaz {{ .name }} bağlandı, önce çıkarın'
DiskUsedAlert: "Paneliniz {{ .node }}{{ .ip }}, {{ .name }} diski kullanımı {{ .used }}'a ulaştı. Detaylar için paneline giriş yapın." PartitionDiskErr: 'Bölümleme başarısız, {{ .err }}'
ResourceAlert: "Paneliniz {{ .node }}{{ .ip }}, son {{ .time }} dakika içindeki ortalama {{ .name }} kullanım oranı {{ .used }}'dır. Detaylar için paneline giriş yapın." FormatDiskErr: 'Disk biçimlendirme başarısız, {{ .err }}'
PanelVersionAlert: "Paneliniz {{ .node }}{{ .ip }}, en son panel sürümü yükseltme için mevcut. Detaylar için paneline giriş yapın." MountDiskErr: 'Disk bağlama başarısız, {{ .err }}'
PanelPwdExpirationAlert: "Paneliniz {{ .node }}{{ .ip }}, panel şifresi {{ .day }} gün içinde süresi dolacak. Detaylar için paneline giriş yapın." XfsNotFound: 'XFS dosya sistemi algılanmadı, lütfen önce xfsprogs''i yükleyin'
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"
+170 -237
View File
@@ -14,12 +14,9 @@ ErrApiConfigKeyInvalid: 'API 介面金鑰錯誤: {{ .detail }}'
ErrApiConfigIPInvalid: '呼叫 API 介面 IP 不在白名單: {{ .detail }}' ErrApiConfigIPInvalid: '呼叫 API 介面 IP 不在白名單: {{ .detail }}'
ErrApiConfigDisable: '此介面禁止使用 API 介面呼叫: {{ .detail }}' ErrApiConfigDisable: '此介面禁止使用 API 介面呼叫: {{ .detail }}'
ErrApiConfigKeyTimeInvalid: 'API 介面時間戳記錯誤: {{ .detail }}' ErrApiConfigKeyTimeInvalid: 'API 介面時間戳記錯誤: {{ .detail }}'
ErrShutDown: "指令被手動結束!" ErrShutDown: '指令被手動結束!'
ErrMinQuickJump: '請至少設定一個快速跳轉入口!'
ErrMinQuickJump: "請至少設定一個快速跳轉入口!" ErrMaxQuickJump: '最多可設定四個快速跳轉入口!'
ErrMaxQuickJump: "最多可設定四個快速跳轉入口!"
#common
ErrUsernameIsExist: '使用者名稱已存在' ErrUsernameIsExist: '使用者名稱已存在'
ErrNameIsExist: '名稱已存在' ErrNameIsExist: '名稱已存在'
ErrDemoEnvironment: '示範伺服器,禁止此操作!' ErrDemoEnvironment: '示範伺服器,禁止此操作!'
@@ -36,37 +33,31 @@ Failed: '失敗'
SystemRestart: '系統重新啟動導致任務中斷' SystemRestart: '系統重新啟動導致任務中斷'
ErrGroupIsDefault: '預設分組,無法刪除' ErrGroupIsDefault: '預設分組,無法刪除'
ErrGroupIsInWebsiteUse: '分組正在被其他網站使用,無法刪除' ErrGroupIsInWebsiteUse: '分組正在被其他網站使用,無法刪除'
Decrypt: "解密" Decrypt: '解密'
ErrAgentAccountBound: '該帳號已綁定到智能體,無法刪除,請重試。'
#agent ErrAgentAccountUnavailable: '帳號連線資訊不可用,錯誤:{{ .err }},請重試'
ErrAgentAccountBound: '該帳號已綁定到智能體,無法刪除,請檢查後重試!!' ErrAgentProviderNotSupported: '暫不支援該智能體提供商,請重試'
ErrAgentAccountUnavailable: '帳號連線資訊不可用,錯誤:{{ .err }},請檢查後重試!'
ErrAgentProviderNotSupported: '暫不支援該智能體提供商,請檢查後重試!'
ErrAgentAccountRequired: '請選擇智能體帳號後重試' ErrAgentAccountRequired: '請選擇智能體帳號後重試'
ErrAgentAccountNotVerified: '帳號未驗證通過,請檢查後重試!' ErrAgentAccountNotVerified: '帳號未驗證通過,請重試'
ErrAgentProviderMismatch: '帳號提供商不匹配,請檢查後重試!' ErrAgentProviderMismatch: '帳號提供商不符,請重試'
ErrAgentBaseURLRequired: 'Base URL 不能為空,請檢查後重試!' ErrAgentBaseURLRequired: 'Base URL 不可為空,請重試'
ErrAgentApiKeyRequired: 'API Key 不能為空,請檢查後重試!' ErrAgentApiKeyRequired: 'API Key 不可為空,請重試'
ErrAgentComposeRequired: '自訂編排內容不能為空,請檢查後重試!' ErrAgentComposeRequired: '自訂編排內容不可為空,請重試'
ErrAgentIDRequired: '智能體 ID 不能為空,請檢查後重試!' ErrAgentIDRequired: '智能體 ID 不可為空,請重試'
ErrAgentAccountIDRequired: '帳號 ID 不能為空,請檢查後重試!' ErrAgentAccountIDRequired: '帳號 ID 不可為空,請重試'
#backup
Localhost: '本機' Localhost: '本機'
ErrBackupInUsed: '此備份帳號已在排程任務中使用,無法刪除' ErrBackupInUsed: '此備份帳號已在排程任務中使用,無法刪除'
ErrBackupCheck: '備份帳號測試連線失敗{{ .err }}' ErrBackupCheck: '備份帳號測試連線失敗{{ .err }}'
ErrBackupLocalDelete: '暫時不支援刪除本機伺服器備份帳號' ErrBackupLocalDelete: '暫時不支援刪除本機伺服器備份帳號'
ErrBackupLocalCreate: '暫時不支援建立本機伺服器備份帳號' ErrBackupLocalCreate: '暫時不支援建立本機伺服器備份帳號'
#app
ErrPortInUsed: '{{ .detail }} 連接埠已被佔用!' ErrPortInUsed: '{{ .detail }} 連接埠已被佔用!'
ErrAppLimit: '應用程式超出安裝數量限制' ErrAppLimit: '應用程式超出安裝數量限制'
ErrNotInstall: '應用程式未安裝' ErrNotInstall: '應用程式未安裝'
ErrPortInOtherApp: '{{ .port }} 連接埠已被應用程式{{ .apps }} 佔用!' ErrPortInOtherApp: '{{ .port }} 連接埠已被應用程式{{ .apps }} 佔用!'
ErrDbUserNotValid: '存量資料庫,使用者名稱密碼不符!' ErrDbUserNotValid: '存量資料庫,使用者名稱密碼不符!'
ErrUpdateBuWebsite: '應用程式更新成功,但網站設定檔修改失敗,請檢查設定! ' ErrUpdateBuWebsite: '應用程式更新成功,但網站設定檔修改失敗,請檢查設定!'
Err1PanelNetworkFailed: '預設容器網路建立失敗! {{ .detail }}' Err1PanelNetworkFailed: '預設容器網路建立失敗! {{ .detail }}'
ErrFileParse: '應用docker-compose 檔案解析失敗!' ErrFileParse: '應用docker-compose 檔解析失敗!'
ErrInstallDirNotFound: '安裝目錄不存在,如需移除,請選擇強制移除' ErrInstallDirNotFound: '安裝目錄不存在,如需移除,請選擇強制移除'
AppStoreIsUpToDate: '應用程式商店已經是最新版本' AppStoreIsUpToDate: '應用程式商店已經是最新版本'
LocalAppVersionNull: '{{ .name }} 應用程式未同步到版本!無法加入到應用程式列表' LocalAppVersionNull: '{{ .name }} 應用程式未同步到版本!無法加入到應用程式列表'
@@ -82,115 +73,108 @@ ErrHttpReqFailed: '請求失敗{{ .err }}'
ErrNoSuchHost: '無法找到請求的伺服器{{ .err }}' ErrNoSuchHost: '無法找到請求的伺服器{{ .err }}'
ErrHttpReqNotFound: '無法找到要求的資源{{ .err }}' ErrHttpReqNotFound: '無法找到要求的資源{{ .err }}'
ErrContainerNotFound: '{{ .name }} 容器不存在' ErrContainerNotFound: '{{ .name }} 容器不存在'
ErrContainerMsg: '{{ .name }} 容器異常,請在容器頁面上查看日誌' ErrContainerMsg: '{{ .name }} 容器異常,請在容器頁面上檢視日誌'
ErrAppBackup: '{{ .name }} 應用備份失敗 {{ .err }}' ErrAppBackup: '{{ .name }} 應用備份失敗 {{ .err }}'
ErrVersionTooLow: '目前1Panel 版本過低,無法更新應用程式商店,請升級版本之後操作' ErrVersionTooLow: '目前 1Panel 版本過低,無法更新應用程式商店,請升級版本之後操作'
ErrAppNameExist: '應用程式名稱已存在' ErrAppNameExist: '應用程式名稱已存在'
AppStoreIsSyncing: '應用程式商店正在同步中,請稍後再試' AppStoreIsSyncing: '應用程式商店正在同步中,請稍後重試'
ErrGetCompose: 'docker-compose.yml 檔案取得失敗!{{ .detail }}' ErrGetCompose: 'docker-compose.yml 檔案取得失敗!{{ .detail }}'
ErrAppWarn: '狀態異常,請檢視日誌' ErrAppWarn: '狀態異常,請檢視日誌'
ErrAppParamKey: '參數{{ .name }} 欄位異常' ErrAppParamKey: '參數{{ .name }} 欄位異常'
ErrAppUpgrade: '應用程式{{ .name }} 升級失敗{{ .err }}' ErrAppUpgrade: '應用程式{{ .name }} 升級失敗{{ .err }}'
AppRecover: '應用程式{{ .name }} 回滾' AppRecover: '應用程式{{ .name }} 回滾'
PullImageStart: '開始拉取鏡像 [{{ .name }}]' PullImageStart: '開始拉取映像 [{{ .name }}]'
PullImageSuccess: '鏡像拉取成功' PullImageSuccess: '映像拉取成功'
AppStoreSyncSuccess: '應用程式商店同步成功' AppStoreSyncSuccess: '應用程式商店同步成功'
SyncAppDetail: '同步應用程式設定' SyncAppDetail: '同步應用程式設定'
AppVersionNotMatch: '{{ .name }} 應用程式需要更高的 1Panel 版本,跳過同步' AppVersionNotMatch: '{{ .name }} 應用程式需要更高的 1Panel 版本,跳過同步'
MoveSiteDir: "檢測到網站目錄變更 需要遷移 OpenResty 網站目錄到 {{ .name }}" MoveSiteDir: '偵測到網站目錄變更 需要遷移 OpenResty 網站目錄到 {{ .name }}'
MoveSiteDirSuccess: '遷移網站目錄成功' MoveSiteDirSuccess: '遷移網站目錄成功'
DeleteRuntimePHP: '刪除PHP 執行環境' DeleteRuntimePHP: '刪除PHP 執行環境'
CustomAppStoreFileValid: '應用程式商店包需要 .tar.gz 格式' CustomAppStoreFileValid: '應用程式商店包需要.tar.gz 格式'
PullImageTimeout: '拉取鏡像逾時,請嘗試增加鏡像加速或更換其他鏡像加速' PullImageTimeout: '拉取映像逾時,請嘗試增加映像加速或更換其他映像加速'
ErrAppIsDown: '{{ .name }} 應用程式狀態異常,請檢查' ErrAppIsDown: '{{ .name }} 應用程式狀態異常,請檢查'
ErrCustomApps: '存在已安裝的應用程式,請先解除安裝' ErrCustomApps: '存在已安裝的應用程式,請先解除安裝'
ErrCustomRuntimes: '存在已安裝的運作環境,請先刪除' ErrCustomRuntimes: '存在已安裝的運作環境,請先刪除'
ErrAppVersionDeprecated: "{{ .name }} 應用不適配目前 1Panel 版本,跳過" ErrAppVersionDeprecated: '{{ .name }} 應用不適配目前 1Panel 版本,跳過'
ErrDockerFailed: "Docker 狀態異常,請檢查服務狀態" ErrDockerFailed: 'Docker 狀態異常,請檢查服務狀態'
ErrDockerComposeCmdNotFound: "Docker Compose 指令不存在,請先在宿主機安裝此指令" ErrDockerComposeCmdNotFound: 'Docker Compose 指令不存在,請先在宿主機安裝此指令'
UseExistImage: '拉取映像失敗,使用存量映像' UseExistImage: '映像已存在,使用現有映像'
ErrDatabaseNotFound: '資料庫 {{ .name }} 不存在'
#ssh ExportIP: '登入IP'
ExportIP: "登入IP" ExportArea: '歸屬地'
ExportArea: "歸屬地" ExportPort: '埠'
ExportPort: "埠" ExportAuthMode: '登入方式'
ExportAuthMode: "登入方式" ExportUser: '使用者'
ExportUser: "使用者" ExportStatus: '登入狀態'
ExportStatus: "登入狀態" ExportDate: '時間'
ExportDate: "時間"
#file
ErrFileCanNotRead: '此檔案不支援預覽' ErrFileCanNotRead: '此檔案不支援預覽'
ErrFileToLarge: '檔案超過10M,無法開啟' ErrFileToLarge: '檔案超過10M,無法開啟'
ErrPathNotFound: '目錄不存在' ErrPathNotFound: '目錄不存在'
ErrMovePathFailed: '目標路徑不能包含原路徑!' ErrMovePathFailed: '目標路徑不可包含原路徑!'
ErrLinkPathNotFound: '目標路徑不存在!' ErrLinkPathNotFound: '目標路徑不存在!'
ErrFileIsExist: '檔案或資料夾已存在!' ErrFileIsExist: '檔案或資料夾已存在!'
ErrFileUpload: '{{ .name }} 上傳檔案失敗{{ .detail }}' ErrFileUpload: '{{ .name }} 上傳檔案失敗{{ .detail }}'
ErrFileDownloadDir: '不支援下載資料夾' ErrFileDownloadDir: '不支援下載資料夾'
ErrCmdNotFound: '{{ .name}} 指令不存在,請先在宿主機安裝此指令' ErrCmdNotFound: '{{ .name }} 指令不存在,請先在宿主機安裝此指令'
ErrSourcePathNotFound: '來源目錄不存在' ErrSourcePathNotFound: '來源目錄不存在'
ErrFavoriteExist: '已收藏此路徑' ErrFavoriteExist: '已收藏此路徑'
ErrInvalidChar: '禁止使用無效字元' ErrInvalidChar: '禁止使用無效字元'
ErrPathNotDelete: '所選目錄不可刪除' ErrPathNotDelete: '所選目錄不可刪除'
ErrLogFileToLarge: "日誌檔案超過 500M,無法打開" ErrLogFileToLarge: '日誌檔案超過 500M,無法開啟'
FileDropFailed: "清理文件 {{ .name }} 失敗: {{ .err }}" FileDropFailed: '清理檔案 {{ .name }} 失敗: {{ .err }}'
FileDropSuccess: "清理文件 {{ .name }} 成功,清理 {{ .count }} 個文件,釋放 {{ .size }} 磁碟空間" FileDropSuccess: '清理檔案 {{ .name }} 成功,清理 {{ .count }} 個檔案,釋放 {{ .size }} 磁碟空間'
FileDropSum: "文件清理完成,共清理 {{ .count }} 個文件,共釋放 {{ .size }} 磁碟空間" FileDropSum: '檔案清理完成,共清理 {{ .count }} 個檔案,共釋放 {{ .size }} 磁碟空間'
ErrBadDecrypt: "壓縮檔解壓密碼錯誤,解壓失敗,請檢查後重試!!" ErrBadDecrypt: '壓縮檔解壓密碼錯誤,解壓失敗,請重試。'
#website
ErrAliasIsExist: '代號已存在' ErrAliasIsExist: '代號已存在'
ErrBackupMatch: '該備份檔案與目前網站部分資料不符{{ .detail }}' ErrBackupMatch: '該備份檔案與目前網站部分資料不符{{ .detail }}'
ErrBackupExist: '該備份檔案對應部分來源資料不存在{{ .detail }}' ErrBackupExist: '該備份檔案對應部分來源資料不存在{{ .detail }}'
ErrPHPResource: '本機執行環境不支援切換! ' ErrPHPResource: '本機執行環境不支援切換!'
ErrPathPermission: 'index 目錄下偵測到非 1000:1000 權限資料夾,可能導致網站存取 Access denied 錯誤,請點擊上方儲存按鈕' ErrPathPermission: 'index 目錄下偵測到非 1000:1000 權限資料夾,可能導致網站存取 Access denied 錯誤,請點選上方儲存按鈕'
ErrDomainIsUsed: '網域名稱已被網站【{{ .name }}】使用' ErrDomainIsUsed: '網域名稱已被網站【{{ .name }}】使用'
ErrDomainFormat: '{{ .name }} 網域格式不正確' ErrDomainFormat: '{{ .name }} 網域格式不正確'
ErrDefaultAlias: 'default 為保留代號,請使用其他代號' ErrDefaultAlias: 'default 為保留代號,請使用其他代號'
ErrParentWebsite: '需要先移除子網站{{ .name }}' ErrParentWebsite: '需要先移除子網站{{ .name }}'
ErrBuildDirNotFound: '建置目錄不存在' ErrBuildDirNotFound: '建置目錄不存在'
ErrImageNotExist: '執行環境{{ .name }} 映像不存在,請重新編輯執行環境' ErrImageNotExist: '執行環境{{ .name }} 映像不存在,請重新編輯執行環境'
ErrProxyIsUsed: "負載均衡已被反向代理使用,無法刪除" ErrProxyIsUsed: '負載均衡已被反向代理使用,無法刪除'
ErrSSLValid: '證書文件異常,請檢查證書狀態!' ErrSSLValid: '憑證檔案異常,請檢查憑證狀態!'
ErrWebsiteDir: "請選擇網站目錄下的目錄" ErrWebsiteDir: '請選擇網站目錄下的目錄'
ErrComposerFileNotFound: "composer.json 文件不存在" ErrComposerFileNotFound: 'composer.json 檔案不存在'
ErrRuntimeNoPort: "執行環境未設定埠,請先編輯執行環境" ErrRuntimeNoPort: '執行環境未設定埠,請先編輯執行環境'
Status: '狀態' Status: '狀態'
start: '開啟' start: '開啟'
stop: '關閉' stop: '關閉'
restart: '重啟' restart: '重新啟動'
kill: '強制停止' kill: '強制停止'
pause: '暫停' pause: '暫停'
unpause: '恢復' unpause: '恢復'
remove: '刪除' remove: '刪除'
delete: '刪除' delete: '刪除'
ErrDefaultWebsite: '已經設置默認網站,請取消後再設置!' ErrDefaultWebsite: '已經設定預設網站,請取消後再設定!'
SSL: '憑證' SSL: '憑證'
Set: '設定' Set: '設定'
#ssl
ErrSSLCannotDelete: '{{ .name }} 憑證正在被網站使用,無法刪除' ErrSSLCannotDelete: '{{ .name }} 憑證正在被網站使用,無法刪除'
ErrAccountCannotDelete: '帳號關聯證書,無法刪除' ErrAccountCannotDelete: '帳號關聯憑證,無法刪除'
ErrSSLApply: '憑證續簽成功,openresty reload 失敗,請檢查設定!' ErrSSLApply: '憑證續簽成功,openresty reload 失敗,請檢查設定!'
ErrEmailIsExist: '信箱已存在' ErrEmailIsExist: '信箱已存在'
ErrSSLKeyNotFound: '私鑰檔案不存在' ErrSSLKeyNotFound: '私鑰檔案不存在'
ErrSSLCertificateNotFound: '憑證檔案不存在' ErrSSLCertificateNotFound: '憑證檔案不存在'
ErrSSLKeyFormat: '私鑰檔案校驗失敗' ErrSSLKeyFormat: '私鑰檔案驗證失敗'
ErrSSLCertificateFormat: '憑證檔案格式錯誤,請使用 pem 格式' ErrSSLCertificateFormat: '憑證檔案格式錯誤,請使用 pem 格式'
ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid 或 EabHmacKey 不能為空' ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid 或 EabHmacKey 不可為空'
ErrOpenrestyNotFound: 'Http 模式需要先安裝Openresty' ErrOpenrestyNotFound: 'Http 模式需要先安裝OpenResty'
ApplySSLStart: '開始申請證書,網域名稱[{{ .domain }}] 申請方式[{{ .type }}] ' ApplySSLStart: '開始申請憑證,網域名稱[{{ .domain }}] 申請方式[{{ .type }}]'
dnsAccount: 'DNS 自動' dnsAccount: 'DNS 自動'
dnsManual: 'DNS 手排' dnsManual: 'DNS 手排'
http: 'HTTP' http: 'HTTP'
ApplySSLFailed: '申請[{{ .domain }}] 憑證失敗, {{ .detail }} ' ApplySSLFailed: '申請[{{ .domain }}] 憑證失敗, {{ .detail }}'
ApplySSLSuccess: '申請[{{ .domain }}] 憑證成功! ! ' ApplySSLSuccess: '申請[{{ .domain }}] 憑證成功!'
DNSAccountName: 'DNS 帳號[{{ .name }}] 廠商[{{ .type }}]' DNSAccountName: 'DNS 帳號[{{ .name }}] 廠商[{{ .type }}]'
PushDirLog: '憑證推送到目錄[{{ .path }}] {{ .status }}' PushDirLog: '憑證推送到目錄[{{ .path }}] {{ .status }}'
ErrDeleteCAWithSSL: '目前機構下存在已簽發證書,無法刪除' ErrDeleteCAWithSSL: '目前機構下存在已簽發憑證,無法刪除'
ErrDeleteWithPanelSSL: '面板SSL 配置使用此證書,無法刪除' ErrDeleteWithPanelSSL: '面板SSL 設定使用此憑證,無法刪除'
ErrDefaultCA: '預設機構不能刪除' ErrDefaultCA: '預設機構不可刪除'
ApplyWebSiteSSLLog: '開始更新{{ .name }} 網站憑證' ApplyWebSiteSSLLog: '開始更新{{ .name }} 網站憑證'
ErrUpdateWebsiteSSL: '{{ .name }} 網站更新憑證失敗: {{ .err }}' ErrUpdateWebsiteSSL: '{{ .name }} 網站更新憑證失敗: {{ .err }}'
ApplyWebSiteSSLSuccess: '更新網站憑證成功' ApplyWebSiteSSLSuccess: '更新網站憑證成功'
@@ -200,105 +184,87 @@ ExecShellSuccess: '腳本執行成功'
StartUpdateSystemSSL: '開始更新系統憑證' StartUpdateSystemSSL: '開始更新系統憑證'
UpdateSystemSSLSuccess: '更新系統憑證成功' UpdateSystemSSLSuccess: '更新系統憑證成功'
ErrWildcardDomain: 'HTTP 模式無法申請泛網域憑證' ErrWildcardDomain: 'HTTP 模式無法申請泛網域憑證'
ErrApplySSLCanNotDelete: "正在申請的證書 {{.name}} 無法刪除,請稍後再試" ErrApplySSLCanNotDelete: '正在申請的憑證 {{ .name }} 無法刪除,請稍後重試'
StartPushSSLToNode: "開始推送證書到節點" StartPushSSLToNode: '開始推送憑證到節點'
PushSSLToNodeFailed: "推送證書到節點失敗: {{ .err }}" PushSSLToNodeFailed: '推送憑證到節點失敗: {{ .err }}'
PushSSLToNodeSuccess: "推送證書到節點成功" PushSSLToNodeSuccess: '推送憑證到節點成功'
#mysql
ErrUserIsExist: '目前使用者已存在,請重新輸入' ErrUserIsExist: '目前使用者已存在,請重新輸入'
ErrDatabaseIsExist: '目前資料庫已存在,請重新輸入' ErrDatabaseIsExist: '目前資料庫已存在,請重新輸入'
ErrExecTimeOut: 'SQL 執行逾時,請檢查資料庫' ErrExecTimeOut: 'SQL 執行逾時,請檢查資料庫'
ErrRemoteExist: '遠端資料庫已存在該名稱,請修改後重試' ErrRemoteExist: '遠端資料庫已存在該名稱,請修改後重試'
ErrLocalExist: '本機資料庫已存在該名稱,請修改後重試' ErrLocalExist: '本機資料庫已存在該名稱,請修改後重試'
RemoteBackup: "備份遠端資料庫需要先使用映像 {{ .name }} 啟動本機容器資料庫服務,請稍候..." RemoteBackup: '備份遠端資料庫需要先使用映像 {{ .name }} 啟動本機容器資料庫服務,請稍候...'
RemoteRecover: "恢復遠端資料庫需要先使用映像 {{ .name }} 啟動本機容器資料庫服務,請稍候..." RemoteRecover: '復原遠端資料庫需要先使用映像 {{ .name }} 啟動本機容器資料庫服務,請稍候...'
Arg: "參數" Arg: '參數'
#redis
ErrTypeOfRedis: '復原檔案類型與目前持久化方式不符,請修改後重試' ErrTypeOfRedis: '復原檔案類型與目前持久化方式不符,請修改後重試'
ErrInUsed: '{{ .detail }} 正被使用,無法刪除!'
#container ErrObjectInUsed: '該對象正被使用,無法刪除!'
ErrInUsed: "{{ .detail }} 正被使用,無法刪除!" ErrObjectBeDependent: '該映像正被其他映像所依賴,無法刪除!'
ErrObjectInUsed: "該對象正被使用,無法刪除!" ErrPortRules: '連接埠數目不符,請重新輸入!'
ErrObjectBeDependent: "該映像正被其他映像所依賴,無法刪除!" ErrPgImagePull: '映像拉取逾時,請設定映像加速或手動拉取{{ .name }} 映像後重試'
ErrPortRules: '連接埠數目不匹配,請重新輸入!' PruneHelper: '本次清理 {{ .name }} 釋放磁碟空間 {{ .size }}'
ErrPgImagePull: '鏡像拉取逾時,請配置鏡像加速或手動拉取{{ .name }} 鏡像後重試' ImageRemoveHelper: '刪除映像 {{ .name }} ,釋放磁碟空間 {{ .size }}'
PruneHelper: "本次清理 {{ .name }} 釋放磁碟空間 {{ .size }}" BuildCache: '構建快取'
ImageRemoveHelper: "刪除鏡像 {{ .name }} ,釋放磁碟空間 {{ .size }}" Volume: '磁碟區'
BuildCache: "構建快取" Network: '網路'
Volume: "磁碟區" PruneStart: '清理中,請稍候...'
Network: "網路"
PruneStart: "清理中,請稍候..."
#runtime
ErrFileNotExist: '{{ .detail }} 檔案不存在!請檢查來源檔案完整性!' ErrFileNotExist: '{{ .detail }} 檔案不存在!請檢查來源檔案完整性!'
ErrImageBuildErr: '鏡像build 失敗' ErrImageBuildErr: '映像build 失敗'
ErrImageExist: "鏡像已存在!請修改鏡像名稱。" ErrImageExist: '映像已存在!請修改映像名稱。'
ErrDelWithWebsite: '執行環境已經關聯網站,無法刪除' ErrDelWithWebsite: '執行環境已經關聯網站,無法刪除'
ErrRuntimeStart: '啟動失敗' ErrRuntimeStart: '啟動失敗'
ErrPackageJsonNotFound: 'package.json 檔案不存在' ErrPackageJsonNotFound: 'package.json 檔案不存在'
ErrScriptsNotFound: '沒有在 package.json 中找到 scripts 設定項' ErrScriptsNotFound: '沒有在 package.json 中找到 scripts 設定項'
ErrContainerNameNotFound: '無法取得容器名稱,請檢查 .env 檔案' ErrContainerNameNotFound: '無法取得容器名稱,請檢查.env 檔案'
ErrNodeModulesNotFound: 'node_modules 資料夾不存在!請編輯執行環境或等待執行環境啟動成功' ErrNodeModulesNotFound: 'node_modules 資料夾不存在!請編輯執行環境或等待執行環境啟動成功'
ErrContainerNameIsNull: '容器名稱不存在' ErrContainerNameIsNull: '容器名稱不存在'
ErrPHPPortIsDefault: "9000 埠為預設埠,請修改後重試" ErrPHPPortIsDefault: '9000 埠為預設埠,請修改後重試'
ErrPHPRuntimePortFailed: "{{ .name }} 埠已被目前執行環境使用,請修改後重試" ErrPHPRuntimePortFailed: '{{ .name }} 埠已被目前執行環境使用,請修改後重試'
#tool
ErrConfigNotFound: '設定檔不存在' ErrConfigNotFound: '設定檔不存在'
ErrConfigParse: '設定檔格式有誤' ErrConfigParse: '設定檔格式有誤'
ErrConfigIsNull: '設定檔不允許為空' ErrConfigIsNull: '設定檔不允許為空'
ErrConfigDirNotFound: '執行目錄不存在' ErrConfigDirNotFound: '執行目錄不存在'
ErrConfigAlreadyExist: '已存在同名設定檔' ErrConfigAlreadyExist: '已存在同名設定檔'
ErrUserFindErr: '使用者{{ .name }} 尋找失敗{{ .err }}' ErrUserFindErr: '使用者{{ .name }} 尋找失敗{{ .err }}'
#cronjob
CutWebsiteLogSuccess: '{{ .name }} 網站日誌切割成功,備份路徑{{ .path }}' CutWebsiteLogSuccess: '{{ .name }} 網站日誌切割成功,備份路徑{{ .path }}'
HandleShell: '執行腳本{{ .name }}' HandleShell: '執行腳本{{ .name }}'
HandleCurl: "存取 URL {{ .name }}" HandleCurl: '存取 URL {{ .name }}'
HandleNtpSync: '系統時間同步' HandleNtpSync: '系統時間同步'
HandleSystemClean: '系統快取清理' HandleSystemClean: '系統快取清理'
SystemLog: '系統日誌' SystemLog: '系統日誌'
CutWebsiteLog: '切割網站日誌' CutWebsiteLog: '切割網站日誌'
FileOrDir: '目錄 / 檔案' FileOrDir: '目錄 / 檔案'
UploadFile: '上傳備份文件 {{ .file }} 到 {{ .backup }}' UploadFile: '上傳備份檔案 {{ .file }} 到 {{ .backup }}'
Upload: "上傳" Upload: '上傳'
IgnoreBackupErr: "備份失敗,錯誤:{{ .detail }},忽略本次錯誤..." IgnoreBackupErr: '備份失敗,錯誤:{{ .detail }},忽略本次錯誤...'
IgnoreUploadErr: "上傳失敗,錯誤:{{ .detail }},忽略本次錯誤..." IgnoreUploadErr: '上傳失敗,錯誤:{{ .detail }},忽略本次錯誤...'
LoadBackupFailed: "取得備份帳號連線失敗,錯誤:{{ .detail }}" LoadBackupFailed: '取得備份帳號連線失敗,錯誤:{{ .detail }}'
InExecuting: "目前任務正在執行中,請勿重複執行!" InExecuting: '目前任務正在執行中,請勿重複執行!'
NoSuchResource: "資料庫中未能查詢到備份內容,跳過..." NoSuchResource: '資料庫中未能查詢到備份內容,跳過...'
CleanLog: "清理日誌" CleanLog: '清理日誌'
CleanLogByName: "清理 {{.name}} 日誌" CleanLogByName: '清理 {{ .name }} 日誌'
WafIpGroupNotFound: "WAF IP 群組未找到,請先到【進階功能-WAF-黑白名單-IP群組】添加遠端下載方式的IP群組" WafIpGroupNotFound: 'WAF IP 群組未找到,請先到【進階功能-WAF-黑白名單-IP群組】添加遠端下載方式的IP群組'
#toolbox
ErrNotExistUser: '目前使用者不存在,請修改後重試!' ErrNotExistUser: '目前使用者不存在,請修改後重試!'
ErrBanAction: '設定失敗,目前{{ .name }} 服務不可用,請檢查後再試一次!' ErrBanAction: '設定失敗,目前{{ .name }} 服務不可用,請重試'
ErrClamdscanNotFound: '未偵測到clamdscan 指令,請參考文件安裝!' ErrClamdscanNotFound: '未偵測到clamdscan 指令,請參考檔案安裝!'
TaskSwapSet: "設定 Swap" TaskSwapSet: '設定 Swap'
SetSwap: "設定 Swap {{ .path }} - {{ .size }}" SetSwap: '設定 Swap {{ .path }} - {{ .size }}'
CreateSwap: "建立 Swap 檔案" CreateSwap: '建立 Swap 檔案'
FormatSwap: "格式化 Swap 檔案" FormatSwap: '格式化 Swap 檔案'
EnableSwap: "啟用 Swap" EnableSwap: '啟用 Swap'
CleanTamperSetting: '清理歷史防護設定'
#tamper SetTamperWithRules: '根據規則啟動目錄防護'
CleanTamperSetting: "清理歷史防護設定" ProtectDir: '防護目錄 {{ .name }}'
SetTamperWithRules: "根據規則啟動目錄防護" IgnoreFile: '保護檔案 {{ .name }}'
ProtectDir: "防護目錄 {{ .name }}" TamperSetSuccessful: '防護設定完成,開始監聽以下目錄:'
IgnoreFile: "保護文件 {{ .name }}" ErrScope: '不支援修改此設定'
TamperSetSuccessful: "防護設定完成,開始監聽以下目錄:"
#waf
ErrScope: '不支援修改此配置'
ErrStateChange: '狀態修改失敗' ErrStateChange: '狀態修改失敗'
ErrRuleExist: '規則已存在' ErrRuleExist: '規則已存在'
ErrRuleNotExist: '規則不存在' ErrRuleNotExist: '規則不存在'
ErrParseIP: 'IP 格式錯誤' ErrParseIP: 'IP 格式錯誤'
ErrDefaultIP: 'default 為保留名稱,請更換其他名稱' ErrDefaultIP: 'default 為保留名稱,請更換其他名稱'
ErrGroupInUse: 'IP 群組被黑/白名單使用,無法刪除' ErrGroupInUse: 'IP 群組被黑/白名單使用,無法刪除'
ErrIPGroupAclUse: "IP 群組被網站 {{ .name }} 自訂規則使用,無法刪除" ErrIPGroupAclUse: 'IP 群組被網站 {{ .name }} 自訂規則使用,無法刪除'
ErrGroupExist: 'IP 群組名稱已存在' ErrGroupExist: 'IP 群組名稱已存在'
ErrIPRange: 'IP 範圍錯誤' ErrIPRange: 'IP 範圍錯誤'
ErrIPExist: 'IP 已存在' ErrIPExist: 'IP 已存在'
@@ -309,10 +275,10 @@ xss: 'XSS'
phpExec: 'PHP 腳本執行' phpExec: 'PHP 腳本執行'
oneWordTrojan: '一句話木馬' oneWordTrojan: '一句話木馬'
appFilter: '套用危險目錄過濾' appFilter: '套用危險目錄過濾'
webshell: 'Webshell' webShell: 'WebShell'
args: '參數規則' args: '參數規則'
protocolFilter: '協定過濾' protocolFilter: '協定過濾'
javaFileter: 'Java 危險檔案過濾' javaFilter: 'Java 危險檔案過濾'
scannerFilter: '掃描器過濾' scannerFilter: '掃描器過濾'
escapeFilter: '轉義過濾' escapeFilter: '轉義過濾'
customRule: '自訂規則' customRule: '自訂規則'
@@ -341,11 +307,10 @@ sqlInject: 'SQL 注入'
ErrDBNotExist: '資料庫不存在' ErrDBNotExist: '資料庫不存在'
allow: '允許' allow: '允許'
deny: '禁止' deny: '禁止'
OpenrestyNotFound: 'Openresty 未安裝' OpenrestyNotFound: 'OpenResty 未安裝'
remoteIpIsNull: "IP 列表為空" remoteIpIsNull: 'IP 列表為空'
OpenrestyVersionErr: "Openresty 版本過低,請升級 Openresty 至 1.27.1.2-2-2-focal" OpenrestyVersionErr: 'OpenResty 版本過低,請升級 OpenResty 至 1.27.1.2-2-2-focal'
ErrFileTooLarge: '檔案超過 1MB,無法上傳'
#task
TaskStart: '{{ .name }} 任務開始[START]' TaskStart: '{{ .name }} 任務開始[START]'
TaskEnd: '{{ .name }} 任務結束[COMPLETED]' TaskEnd: '{{ .name }} 任務結束[COMPLETED]'
TaskFailed: '{{ .name }} 任務失敗' TaskFailed: '{{ .name }} 任務失敗'
@@ -360,8 +325,8 @@ TaskCreate: '建立'
TaskDelete: '刪除' TaskDelete: '刪除'
TaskUpgrade: '升級' TaskUpgrade: '升級'
TaskUpdate: '更新' TaskUpdate: '更新'
TaskRestart: '重啟' TaskRestart: '重新啟動'
TaskProtect: "防護" TaskProtect: '防護'
TaskBackup: '備份' TaskBackup: '備份'
TaskRecover: '復原' TaskRecover: '復原'
TaskRollback: '回滾' TaskRollback: '回滾'
@@ -369,16 +334,16 @@ TaskPull: '拉取'
TaskCommit: '製作' TaskCommit: '製作'
TaskBuild: '建置' TaskBuild: '建置'
TaskPush: '推送' TaskPush: '推送'
TaskClean: "清理" TaskClean: '清理'
TaskHandle: '執行' TaskHandle: '執行'
TaskImport: "導入" TaskImport: '匯入'
TaskExport: "導出" TaskExport: '匯出'
Website: '網站' Website: '網站'
App: '應用程式' App: '應用程式'
Runtime: '運作環境' Runtime: '運作環境'
Database: '資料庫' Database: '資料庫'
ConfigFTP: '建立FTP 使用者{{ .name }}' ConfigFTP: '建立FTP 使用者{{ .name }}'
ConfigOpenresty: '建立Openresty 設定檔' ConfigOpenresty: '建立OpenResty 設定檔'
InstallAppSuccess: '應用程式{{ .name }} 安裝成功' InstallAppSuccess: '應用程式{{ .name }} 安裝成功'
ConfigRuntime: '設定執行環境' ConfigRuntime: '設定執行環境'
ConfigApp: '設定應用程式' ConfigApp: '設定應用程式'
@@ -387,11 +352,11 @@ FailedStatus: '{{ .name }} 失敗{{ .err }}'
HandleLink: '處理應用程式關聯' HandleLink: '處理應用程式關聯'
HandleDatabaseApp: '處理應用程式參數' HandleDatabaseApp: '處理應用程式參數'
ExecShell: '執行{{ .name }} 腳本' ExecShell: '執行{{ .name }} 腳本'
PullImage: '拉取鏡像' PullImage: '拉取映像'
Start: '開始' Start: '開始'
Run: '啟動' Run: '啟動'
Stop: '停止' Stop: '停止'
Image: '鏡像' Image: '映像'
Compose: '編排' Compose: '編排'
Container: '容器' Container: '容器'
AppLink: '關聯應用程式' AppLink: '關聯應用程式'
@@ -404,28 +369,22 @@ RuntimeExtension: '執行環境擴充'
TaskIsExecuting: '任務正在運作' TaskIsExecuting: '任務正在運作'
CustomAppstore: '自訂應用程式倉庫' CustomAppstore: '自訂應用程式倉庫'
TaskExec: '執行' TaskExec: '執行'
TaskBatch: "批次操作" TaskBatch: '批次操作'
FileConvert: '檔案格式轉換' FileConvert: '檔案格式轉換'
Clamscan: '掃描 {{ .name }}'
# task - clam TaskScan: '掃描'
Clamscan: "掃描 {{ .name }}" OllamaModelPull: '拉取 Ollama 模型{{ .name }}'
TaskScan: "掃描"
# task - ai
OllamaModelPull: '拉取 Ollama 模型{{ .name }} '
OllamaModelSize: '取得 Ollama 模型{{ .name }} 大小' OllamaModelSize: '取得 Ollama 模型{{ .name }} 大小'
# task - snapshot
Snapshot: '快照' Snapshot: '快照'
SnapDBInfo: '寫入1Panel 資料庫資訊' SnapDBInfo: '寫入1Panel 資料庫資訊'
SnapCopy: '複製檔案&目錄{{ .name }} ' SnapCopy: '複製檔案&目錄{{ .name }}'
SnapNewDB: '初始化資料庫{{ .name }} 連線' SnapNewDB: '初始化資料庫{{ .name }} 連線'
SnapDeleteOperationLog: '刪除操作日誌' SnapDeleteOperationLog: '刪除操作日誌'
SnapDeleteLoginLog: '刪除存取日誌' SnapDeleteLoginLog: '刪除存取日誌'
SnapDeleteMonitor: '刪除監控資料' SnapDeleteMonitor: '刪除監控資料'
SnapRemoveSystemIP: '移除系統IP' SnapRemoveSystemIP: '移除系統IP'
SnapBaseInfo: '寫入1Panel 基本資料' SnapBaseInfo: '寫入1Panel 基本資料'
SnapInstallAppImageEmpty: '目前未勾選應用鏡像,跳過...' SnapInstallAppImageEmpty: '目前未勾選應用映像,跳過...'
SnapInstallApp: '備份 1Panel 已安裝應用' SnapInstallApp: '備份 1Panel 已安裝應用'
SnapDockerSave: '壓縮已安裝應用' SnapDockerSave: '壓縮已安裝應用'
SnapLocalBackup: '備份1Panel 本機備份目錄' SnapLocalBackup: '備份1Panel 本機備份目錄'
@@ -441,7 +400,6 @@ SnapCompressSize: '快照檔案大小{{ .name }}'
SnapUpload: '上傳快照檔案' SnapUpload: '上傳快照檔案'
SnapUploadTo: '上傳快照檔案到{{ .name }}' SnapUploadTo: '上傳快照檔案到{{ .name }}'
SnapUploadRes: '上傳快照檔案到{{ .name }}' SnapUploadRes: '上傳快照檔案到{{ .name }}'
SnapshotRecover: '快照復原' SnapshotRecover: '快照復原'
RecoverDownload: '下載快照檔案' RecoverDownload: '下載快照檔案'
Download: '下載' Download: '下載'
@@ -449,94 +407,69 @@ RecoverDownloadAccount: '取得快照下載備份帳號{{ .name }}'
RecoverDecompress: '解壓縮快照壓縮檔' RecoverDecompress: '解壓縮快照壓縮檔'
Decompress: '解壓縮' Decompress: '解壓縮'
BackupBeforeRecover: '快照前備份系統相關資料' BackupBeforeRecover: '快照前備份系統相關資料'
Readjson: '讀取快照內Json 檔案' ReadJson: '讀取快照內JSON 檔案'
ReadjsonPath: '取得快照內Json 檔案路徑' ReadJsonPath: '取得快照內JSON 檔案路徑'
ReadjsonContent: '讀取Json 檔案' ReadJsonContent: '讀取JSON 檔案'
ReadjsonMarshal: 'Json 轉義處理' ReadJsonMarshal: 'JSON 轉義處理'
RecoverApp: '復原已安裝應用程式' RecoverApp: '復原已安裝應用程式'
RecoverWebsite: '復原網站目錄' RecoverWebsite: '復原網站目錄'
RecoverAppImage: '復原快照鏡像備份' RecoverAppImage: '復原快照映像備份'
RecoverCompose: '復原其他編排內容' RecoverCompose: '復原其他編排內容'
RecoverComposeList: '取得所有待復原編排' RecoverComposeList: '取得所有待復原編排'
RecoverComposeItem: '復原編排{{ .name }}' RecoverComposeItem: '復原編排{{ .name }}'
RecoverAppEmpty: '快照檔案中未發現應用程式鏡像備份' RecoverAppEmpty: '快照檔案中未發現應用程式映像備份'
RecoverBaseData: '復原基礎資料及檔案' RecoverBaseData: '復原基礎資料及檔案'
RecoverDaemonJsonEmpty: '快照檔案及目前機器都不存在容器配置daemon.json 檔案' RecoverDaemonJsonEmpty: '快照檔案及目前機器都不存在容器設定daemon.json 檔'
RecoverDaemonJson: '復原容器配置daemon.json 檔案' RecoverDaemonJson: '復原容器設定daemon.json 檔'
RecoverDBData: '復原資料庫資料' RecoverDBData: '復原資料庫資料'
RecoverBackups: '還原本機備份目錄' RecoverBackups: '還原本機備份目錄'
RecoverPanelData: '復原資料目錄' RecoverPanelData: '復原資料目錄'
ContainerImagePull: '拉取容器映像{{ .name }}'
# task - container
ContainerNewCliet: '初始化Docker Client'
ContainerImagePull: '拉取容器鏡像{{ .name }}'
ContainerRemoveOld: '刪除原容器{{ .name }}' ContainerRemoveOld: '刪除原容器{{ .name }}'
ContainerImageCheck: '檢查鏡像是否正常拉取' ContainerImageCheck: '檢查映像是否正常拉取'
ContainerLoadInfo: '取得容器基本資訊' ContainerLoadInfo: '取得容器基本資訊'
ContainerRecreate: '容器更新失敗,現在開始復原原容器' ContainerRecreate: '容器更新失敗,現在開始復原原容器'
ContainerCreate: '建立新容器{{ .name }}' ContainerCreate: '建立新容器{{ .name }}'
ContainerCreateFailed: '容器建立失敗,刪除失敗容器' ContainerCreateFailed: '容器建立失敗,刪除失敗容器'
ContainerStartCheck: '檢查容器是否已啟動' ContainerStartCheck: '檢查容器是否已啟動'
ImageBuild: '映像建置'
# task - image ImagePull: '拉取映像'
ImageBuild: '鏡像建置'
ImageBuildStdoutCheck: '解析鏡像輸出內容'
ImageBuildRes: '鏡像建置輸出:{{ .name }}'
ImagePull: '拉取鏡像'
ImageRepoAuthFromDB: '從資料庫取得倉庫認證資訊' ImageRepoAuthFromDB: '從資料庫取得倉庫認證資訊'
ImaegPullRes: '鏡像拉取輸出:{{ .name }}' ImagePush: '推播映像'
ImagePush: '推播鏡像' ImageRenameTag: '修改映像Tag'
ImageRenameTag: '修改鏡像Tag' ImageNewTag: '新映像Tag {{ .name }}'
ImageNewTag: '新鏡像Tag {{ .name }}'
ImaegPushRes: '鏡像推播輸出:{{ .name }}'
ComposeCreate: '建立編排' ComposeCreate: '建立編排'
ComposeCreateRes: '編排建立輸出:{{ .name }}'
# task - website
BackupNginxConfig: '備份網站OpenResty 設定檔' BackupNginxConfig: '備份網站OpenResty 設定檔'
CompressFileSuccess: '壓縮目錄成功,壓縮為{{ .name }}' CompressFileSuccess: '壓縮目錄成功,壓縮為{{ .name }}'
CompressDir: '壓縮目錄' CompressDir: '壓縮目錄'
DeCompressFile: '解壓縮檔案{{ .name }}' DeCompressFile: '解壓縮檔案{{ .name }}'
ErrCheckValid: '校驗備份檔失敗,{{ .name }}' ErrCheckValid: '驗證備份檔失敗,{{ .name }}'
Rollback: '回滾' Rollback: '回滾'
websiteDir: '網站目錄' websiteDir: '網站目錄'
RecoverFailedStartRollBack: '復原失敗,開始回溯' RecoverFailedStartRollBack: '復原失敗,開始回溯'
AppBackupFileIncomplete: '備份檔案不完整缺少 app.json 或 app.tar.gz 檔案' AppBackupFileIncomplete: '備份檔案不完整缺少 app.json 或 app.tar.gz 檔案'
AppAttributesNotMatch: '應用程式類型或名稱不一致' AppAttributesNotMatch: '應用程式類型或名稱不一致'
ErrAlertSync: '警告訊息同步錯誤,請重試。'
#alert ErrInstallExtension: '已有安裝任務正在進行,請等待任務結束'
ErrAlert: '警告訊息格式錯誤,請檢查後重試!!' PanelAlertTitle: '面板警示通知'
ErrAlertPush: '警告訊息推送錯誤,請檢查後重試!!' TestAlertTitle: '測試郵件 - 驗證信箱連通性'
ErrAlertSave: '警告訊息儲存錯誤,請檢查後重試!!' TestAlert: '這是一封測試郵件,用於確認您的郵件發送設定是否正確。'
ErrAlertSync: '警告訊息同步錯誤,請檢查後重試!!' LicenseExpirationAlert: '您的 {{ .node }}{{ .ip }} 面板,授權將於 {{ .day }} 天後到期,詳情請登入面板檢視。'
ErrAlertRemote: '警告訊息遠端錯誤,請檢查後重試!!' CronJobFailedAlert: '您的 {{ .node }}{{ .ip }} 面板,排程任務{{ .name }}執行失敗,詳情請登入面板檢視。'
ClamAlert: '您的 {{ .node }}{{ .ip }} 面板,病毒掃描任務偵測到 {{ .num }} 個感染檔案,詳情請登入面板檢視。'
#task - runtime WebSiteAlert: '您的 {{ .node }}{{ .ip }} 面板,{{ .num }} 個網站將於 {{ .day }} 天後到期,詳情請登入面板檢視。'
ErrInstallExtension: "已有安裝任務正在進行,請等待任務結束" SSLAlert: '您的 {{ .node }}{{ .ip }} 面板,{{ .num }} 張SSL憑證將於 {{ .day }} 天後到期,詳情請登入面板檢視。'
DiskUsedAlert: '您的 {{ .node }}{{ .ip }} 面板,磁碟 {{ .name }} 使用率已達 {{ .used }},詳情請登入面板檢視。'
# alert mail template ResourceAlert: '您的 {{ .node }}{{ .ip }} 面板,過去 {{ .time }} 分鐘內 {{ .name }} 平均使用率為 {{ .used }},詳情請登入面板檢視。'
PanelAlertTitle: "面板警示通知" PanelVersionAlert: '您的 {{ .node }}{{ .ip }} 面板,已有最新版本可供升級,詳情請登入面板檢視。'
TestAlertTitle: "測試郵件 - 驗證信箱連通性" PanelPwdExpirationAlert: '您的 {{ .node }}{{ .ip }} 面板,面板密碼將於 {{ .day }} 天後到期,詳情請登入面板檢視。'
TestAlert: "這是一封測試郵件,用於確認您的郵件發送設定是否正確。" CommonAlert: '您的 {{ .node }}{{ .ip }} 面板,{{ .msg }},詳情請登入面板檢視。'
LicenseExpirationAlert: "您的 {{ .node }}{{ .ip }} 面板,授權將於 {{ .day }} 天後到期,詳情請登入面板查看。" NodeExceptionAlert: '您的 {{ .node }}{{ .ip }} 面板,{{ .num }} 個節點出現異常,詳情請登入面板檢視。'
CronJobFailedAlert: "您的 {{ .node }}{{ .ip }} 面板,排程任務{{ .name }}執行失敗,詳情請登入面板查看。" LicenseExceptionAlert: '您的 {{ .node }}{{ .ip }} 面板,{{ .num }} 個授權出現異常,詳情請登入面板檢視。'
ClamAlert: "您的 {{ .node }}{{ .ip }} 面板,病毒掃描任務偵測到 {{ .num }} 個感染檔案,詳情請登入面板查看。" SSHAndPanelLoginAlert: '您的 {{ .node }}{{ .ip }} 面板,來自 {{ .loginIp }} 的 {{ .name }} 登入出現異常,詳情請登入面板檢視。'
WebSiteAlert: "您的 {{ .node }}{{ .ip }} 面板,{{ .num }} 個網站將於 {{ .day }} 天後到期,詳情請登入面板查看。" DeviceNotFound: '裝置 {{ .name }} 未找到'
SSLAlert: "您的 {{ .node }}{{ .ip }} 面板,{{ .num }} 張SSL憑證將於 {{ .day }} 天後到期,詳情請登入面板查看。" DeviceIsMounted: '裝置 {{ .name }} 已掛載,請先移除'
DiskUsedAlert: "您的 {{ .node }}{{ .ip }} 面板,磁碟 {{ .name }} 使用率已達 {{ .used }},詳情請登入面板查看。" PartitionDiskErr: '分區失敗,{{ .err }}'
ResourceAlert: "您的 {{ .node }}{{ .ip }} 面板,過去 {{ .time }} 分鐘內 {{ .name }} 平均使用率為 {{ .used }},詳情請登入面板查看。" FormatDiskErr: '格式化磁碟失敗,{{ .err }}'
PanelVersionAlert: "您的 {{ .node }}{{ .ip }} 面板,已有最新版本可供升級,詳情請登入面板查看。" MountDiskErr: '掛載磁碟失敗,{{ .err }}'
PanelPwdExpirationAlert: "您的 {{ .node }}{{ .ip }} 面板,面板密碼將於 {{ .day }} 天後到期,詳情請登入面板查看。" XfsNotFound: '未偵測到 xfs 檔案系統,請先安裝 xfsprogs'
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"
+99 -110
View File
@@ -1,30 +1,30 @@
ErrInvalidParams: "请求参数错误: {{ .detail }}" ErrInvalidParams: "参数错误: {{ .detail }}"
ErrTokenParse: "Token 生成错误: {{ .detail }}" ErrTokenParse: "Token 错误: {{ .detail }}"
ErrInitialPassword: "原密码错误" ErrInitialPassword: "原密码错误"
ErrInternalServer: "服务内部错误: {{ .detail }}" ErrInternalServer: "服务错误: {{ .detail }}"
ErrRecordExist: "记录已存在" ErrRecordExist: "记录已存在"
ErrRecordNotFound: "记录未能找到" ErrRecordNotFound: "记录不存在"
ErrStructTransform: "类型转换失败: {{ .err }}" ErrStructTransform: "类型转换失败: {{ .err }}"
ErrNotLogin: "用户未登录: {{ .detail }}" ErrNotLogin: "用户未登录: {{ .detail }}"
ErrPasswordExpired: "当前密码已过期: {{ .detail }}" ErrPasswordExpired: "当前密码已过期: {{ .detail }}"
ErrNotSupportType: "系统暂不支持当前类型: {{ .name }}" ErrNotSupportType: "不支持当前类型: {{ .name }}"
ErrProxy: "请求错误,请检查该节点状态: {{ .detail }}" ErrProxy: "请求失败,请检查节点状态: {{ .detail }}"
ErrApiConfigStatusInvalid: "API 接口禁止访问: {{ .detail }}" ErrApiConfigStatusInvalid: "API 禁止访问: {{ .detail }}"
ErrApiConfigKeyInvalid: "API 接口密钥错误: {{ .detail }}" ErrApiConfigKeyInvalid: "API 接口密钥错误: {{ .detail }}"
ErrApiConfigIPInvalid: "调用 API 接口 IP 不在白名单: {{ .detail }}" ErrApiConfigIPInvalid: "调用 API 接口 IP 不在白名单: {{ .detail }}"
ErrApiConfigDisable: "此接口禁止使用 API 接口调用: {{ .detail }}" ErrApiConfigDisable: "此接口禁止 API 调用: {{ .detail }}"
ErrApiConfigKeyTimeInvalid: "API 接口时间戳错误: {{ .detail }}" ErrApiConfigKeyTimeInvalid: "API 时间戳错误: {{ .detail }}"
ErrShutDown: "命令被手动结束!" ErrShutDown: "命令已手动终止"
ErrMinQuickJump: "请至少设置一个快速跳转入口!" ErrMinQuickJump: "至少设置 1 个快速跳转入口"
ErrMaxQuickJump: "最多可设置四个快速跳转入口!" ErrMaxQuickJump: "最多设置 4 个快速跳转入口"
#common #common
ErrUsernameIsExist: "用户名已存在" ErrUsernameIsExist: "用户名已存在"
ErrNameIsExist: "名称已存在" ErrNameIsExist: "名称已存在"
ErrDemoEnvironment: "演示服务器,禁止此操作!" ErrDemoEnvironment: "演示环境,禁止操作"
ErrCmdTimeout: "命令执行超时!" ErrCmdTimeout: "命令超时"
ErrCmdIllegal: "执行命令中存在不合法字符,请修改后重试!" ErrCmdIllegal: "命令含非法字符,请修改后重试"
ErrPortExist: '{{ .port }} 端口已被 {{ .type }} [{{ .name }}] 占用' ErrPortExist: '{{ .port }} 端口已被 {{ .type }} [{{ .name }}] 占用'
TYPE_APP: "应用" TYPE_APP: "应用"
TYPE_RUNTIME: "运行环境" TYPE_RUNTIME: "运行环境"
@@ -33,23 +33,23 @@ ErrTypePort: '端口 {{ .name }} 格式错误'
ErrTypePortRange: '端口范围需要在 1-65535 之间' ErrTypePortRange: '端口范围需要在 1-65535 之间'
Success: "成功" Success: "成功"
Failed: "失败" Failed: "失败"
SystemRestart: "系统重启导致任务中断" SystemRestart: "系统重启,任务中断"
ErrGroupIsDefault: "默认分组,无法删除" ErrGroupIsDefault: "默认分组不可删除"
ErrGroupIsInWebsiteUse: "分组正在被其他网站使用,无法删除" ErrGroupIsInWebsiteUse: "分组正在被其他网站使用,无法删除"
Decrypt: "解密" Decrypt: "解密"
#agent #agent
ErrAgentAccountBound: "该账号已经绑定到智能体,无法删除,请检查后重试!!" ErrAgentAccountBound: "该账号已绑定智能体,无法删除"
ErrAgentAccountUnavailable: "账号连接信息不可用,错误:{{ .err }},请检查后重试!" ErrAgentAccountUnavailable: "账号连接信息不可用: {{ .err }}"
ErrAgentProviderNotSupported: "暂不支持该智能体提供商,请检查后重试!" ErrAgentProviderNotSupported: "不支持该智能体提供商"
ErrAgentAccountRequired: "请选择智能体账号后重试" ErrAgentAccountRequired: "请选择智能体账号后重试"
ErrAgentAccountNotVerified: "账号未验证通过,请检查后重试!" ErrAgentAccountNotVerified: "账号未通过验证"
ErrAgentProviderMismatch: "账号提供商不匹配,请检查后重试!" ErrAgentProviderMismatch: "账号提供商不匹配"
ErrAgentBaseURLRequired: "Base URL 不能为空,请检查后重试!" ErrAgentBaseURLRequired: "Base URL 不能为空"
ErrAgentApiKeyRequired: "API Key 不能为空,请检查后重试!" ErrAgentApiKeyRequired: "API Key 不能为空"
ErrAgentComposeRequired: "自定义编排内容不能为空,请检查后重试!" ErrAgentComposeRequired: "自定义编排内容不能为空"
ErrAgentIDRequired: "智能体 ID 不能为空,请检查后重试!" ErrAgentIDRequired: "智能体 ID 不能为空"
ErrAgentAccountIDRequired: "账号 ID 不能为空,请检查后重试!" ErrAgentAccountIDRequired: "账号 ID 不能为空"
#backup #backup
Localhost: '本机' Localhost: '本机'
@@ -60,15 +60,15 @@ ErrBackupLocalCreate: "暂不支持创建本地服务器备份账号"
#app #app
ErrPortInUsed: "{{ .detail }} 端口已被占用!" ErrPortInUsed: "{{ .detail }} 端口已被占用!"
ErrAppLimit: "应用超出安装数量限制" ErrAppLimit: "应用安装数量超限"
ErrNotInstall: "应用未安装" ErrNotInstall: "应用未安装"
ErrPortInOtherApp: "{{ .port }} 端口已被应用 {{ .apps }} 占用!" ErrPortInOtherApp: "{{ .port }} 端口已被应用 {{ .apps }} 占用!"
ErrDbUserNotValid: "存量数据库,用户名密码不匹配!" ErrDbUserNotValid: "存量数据库用户名或密码不匹配"
ErrUpdateBuWebsite: '应用更新成功,但是网站配置文件修改失败,请检查配置!' ErrUpdateBuWebsite: '应用更新成功,但网站配置文件修改失败,请检查配置'
Err1PanelNetworkFailed: '默认容器网络创建失败!{{ .detail }}' Err1PanelNetworkFailed: '默认容器网络创建失败!{{ .detail }}'
ErrFileParse: '应用 docker-compose 文件解析失败!' ErrFileParse: '应用 docker-compose 解析失败'
ErrInstallDirNotFound: '安装目录不存在,如需卸载,请选择强制卸载' ErrInstallDirNotFound: '安装目录不存在,如需卸载请选强制卸载'
AppStoreIsUpToDate: '应用商店已经是最新版本' AppStoreIsUpToDate: '应用商店已是最新版本'
LocalAppVersionNull: '{{ .name }} 应用未同步到版本!无法添加到应用列表' LocalAppVersionNull: '{{ .name }} 应用未同步到版本!无法添加到应用列表'
LocalAppVersionErr: '{{ .name }} 同步版本 {{ .version }} 失败!{{ .err }}' LocalAppVersionErr: '{{ .name }} 同步版本 {{ .version }} 失败!{{ .err }}'
ErrFileNotFound: '{{ .name }} 文件不存在' ErrFileNotFound: '{{ .name }} 文件不存在'
@@ -86,29 +86,29 @@ ErrContainerMsg: '{{ .name }} 容器异常,具体请在容器页面查看日
ErrAppBackup: '{{ .name }} 应用备份失败 {{ .err }}' ErrAppBackup: '{{ .name }} 应用备份失败 {{ .err }}'
ErrVersionTooLow: '当前 1Panel 版本过低,无法更新应用商店,请升级版本之后操作' ErrVersionTooLow: '当前 1Panel 版本过低,无法更新应用商店,请升级版本之后操作'
ErrAppNameExist: '应用名称已存在' ErrAppNameExist: '应用名称已存在'
AppStoreIsSyncing: '应用商店正在同步中,请稍后再试' AppStoreIsSyncing: '应用商店同步中,请稍后重试'
ErrGetCompose: "docker-compose.yml 文件获取失败!{{ .detail }}" ErrGetCompose: "docker-compose.yml 文件获取失败!{{ .detail }}"
ErrAppWarn: "状态异常,请查看日志" ErrAppWarn: "状态异常,请查看日志"
ErrAppParamKey: "参数 {{ .name }} 字段异常" ErrAppParamKey: "参数 {{ .name }} 字段异常"
ErrAppUpgrade: "应用 {{ .name }} 升级失败 {{ .err }}" ErrAppUpgrade: "应用 {{ .name }} 升级失败 {{ .err }}"
AppRecover: "应用 {{ .name }} 回滚 " AppRecover: "应用 {{ .name }} 回滚"
PullImageStart: "开始拉取镜像 [{{ .name }}]" PullImageStart: "开始拉取镜像 [{{ .name }}]"
PullImageSuccess: "镜像拉取成功" PullImageSuccess: "镜像拉取成功"
AppStoreSyncSuccess: "应用商店同步成功" AppStoreSyncSuccess: "应用商店同步成功"
SyncAppDetail: "同步应用配置" SyncAppDetail: "同步应用配置"
AppVersionNotMatch: "{{ .name }} 应用需要更高的 1Panel 版本,跳过" AppVersionNotMatch: "{{ .name }} 应用需要更高的 1Panel 版本,跳过"
MoveSiteDir: "检测到网站目录变更 需要迁移 OpenResty 网站目录到 {{ .name }}" MoveSiteDir: "检测到网站目录变更,需迁移 OpenResty 网站目录到 {{ .name }}"
MoveSiteDirSuccess: "迁移网站目录成功" MoveSiteDirSuccess: "迁移网站目录成功"
DeleteRuntimePHP: "删除 PHP 运行环境" DeleteRuntimePHP: "删除 PHP 运行环境"
CustomAppStoreFileValid: "应用商店包需要 .tar.gz 格式" CustomAppStoreFileValid: "应用商店包需要 .tar.gz 格式"
PullImageTimeout: "拉取镜像超时,请尝试增加镜像加速或者更换其他镜像加速" PullImageTimeout: "拉取镜像超时,请调整镜像加速配置"
ErrAppIsDown: "{{ .name }} 应用状态异常,请检查" ErrAppIsDown: "{{ .name }} 应用状态异常,请检查"
ErrCustomApps: "存在已经安装的应用,请先卸载" ErrCustomApps: "存在已安装应用,请先卸载"
ErrCustomRuntimes: "存在已经安装的运行环境,请先删除" ErrCustomRuntimes: "存在已安装运行环境,请先删除"
ErrAppVersionDeprecated: " {{ .name }} 应用不适配当前 1Panel 版本,跳过" ErrAppVersionDeprecated: "{{ .name }} 应用不适配当前 1Panel 版本,跳过"
ErrDockerFailed: "Docker 状态异常,请检查服务状态" ErrDockerFailed: "Docker 状态异常,请检查服务状态"
ErrDockerComposeCmdNotFound: "Docker Compose 命令不存在,请先在宿主机安装此命令" ErrDockerComposeCmdNotFound: "Docker Compose 命令不存在,请先在宿主机安装"
UseExistImage: "拉取镜像失败,使用存量镜像" UseExistImage: "镜像已存在,使用存量镜像"
ErrDatabaseNotFound: "数据库 {{ .name }} 不存在" ErrDatabaseNotFound: "数据库 {{ .name }} 不存在"
#ssh #ssh
@@ -122,30 +122,30 @@ ExportDate: "时间"
#file #file
ErrFileCanNotRead: "此文件不支持预览" ErrFileCanNotRead: "此文件不支持预览"
ErrFileToLarge: "文件超过10M,无法打开" ErrFileToLarge: "文件超过 10M,无法打开"
ErrPathNotFound: "目录不存在" ErrPathNotFound: "目录不存在"
ErrMovePathFailed: "目标路径不能包含原路径!" ErrMovePathFailed: "目标路径不能包含原路径!"
ErrLinkPathNotFound: "目标路径不存在!" ErrLinkPathNotFound: "目标路径不存在!"
ErrFileIsExist: "文件或文件夹已存在!" ErrFileIsExist: "文件或文件夹已存在!"
ErrFileUpload: "{{ .name }} 上传文件失败 {{ .detail }}" ErrFileUpload: "{{ .name }} 上传文件失败 {{ .detail }}"
ErrFileDownloadDir: "不支持下载文件夹" ErrFileDownloadDir: "不支持下载目录"
ErrCmdNotFound: "{{ .name}} 命令不存在,请先在宿主机安装此命令" ErrCmdNotFound: "{{ .name }} 命令不存在,请先在宿主机安装此命令"
ErrSourcePathNotFound: "源目录不存在" ErrSourcePathNotFound: "源目录不存在"
ErrFavoriteExist: "已收藏此路径" ErrFavoriteExist: "已收藏此路径"
ErrInvalidChar: "禁止使用非法字符" ErrInvalidChar: "禁止使用非法字符"
ErrPathNotDelete: "所选目录不可删除" ErrPathNotDelete: "所选目录不可删除"
ErrLogFileToLarge: "日志文件超过 500M,无法打开" ErrLogFileToLarge: "日志文件超过 500M,无法打开"
FileDropFailed: "清理文件 {{ .name }} 失败 {{ .err }}" FileDropFailed: "清理文件 {{ .name }} 失败 {{ .err }}"
FileDropSuccess: "清理文件 {{ .name }} 成功,清理文件 {{ .count }},释放磁盘空间 {{ .size }}" FileDropSuccess: "清理 {{ .name }} 成功,文件 {{ .count }},释放 {{ .size }}"
FileDropSum: "文件清理成功,清理文件共计 {{ .count }},释放磁盘空间共计 {{ .size }}" FileDropSum: "文件清理完成,共 {{ .count }},释放 {{ .size }}"
ErrBadDecrypt: "压缩包解压密码错误,解压失败,请检查后重试!!" ErrBadDecrypt: "压缩包密码错误,解压失败,请检查后重试"
#website #website
ErrAliasIsExist: "代号已存在" ErrAliasIsExist: "标识已存在"
ErrBackupMatch: '该备份文件与当前网站部分数据不匹配 {{ .detail }}' ErrBackupMatch: '该备份文件与当前网站部分数据不匹配 {{ .detail }}'
ErrBackupExist: '该备份文件对应部分源数据不存在 {{ .detail }}' ErrBackupExist: '该备份文件对应部分源数据不存在 {{ .detail }}'
ErrPHPResource: '本地运行环境不支持切换!' ErrPHPResource: '本地运行环境不支持切换!'
ErrPathPermission: 'index 目录下检测到非 1000:1000 权限文件夹,可能导致网站访问 Access denied 错误,请点击上方保存按钮' ErrPathPermission: 'index 目录存在非 1000:1000 权限目录,可能导致 Access denied,请点击上方保存'
ErrDomainIsUsed: "域名已被网站【{{ .name }}】使用" ErrDomainIsUsed: "域名已被网站【{{ .name }}】使用"
ErrDomainFormat: "{{ .name }} 域名格式不正确" ErrDomainFormat: "{{ .name }} 域名格式不正确"
ErrDefaultAlias: "default 为保留代号,请使用其他代号" ErrDefaultAlias: "default 为保留代号,请使用其他代号"
@@ -166,14 +166,14 @@ pause: '暂停'
unpause: '恢复' unpause: '恢复'
remove: '删除' remove: '删除'
delete: '删除' delete: '删除'
ErrDefaultWebsite: "已经设置默认网站,请取消后再设置!" ErrDefaultWebsite: "已设置默认网站,请先取消再设置"
SSL: '证书' SSL: '证书'
Set: '设置' Set: '设置'
#ssl #ssl
ErrSSLCannotDelete: "{{ .name }} 证书正在被网站使用,无法删除" ErrSSLCannotDelete: "{{ .name }} 证书正在被网站使用,无法删除"
ErrAccountCannotDelete: "账号关联证书,无法删除" ErrAccountCannotDelete: "账号关联证书,无法删除"
ErrSSLApply: "证书续签成功,openresty reload失败,请检查配置!" ErrSSLApply: "证书续签成功,但 OpenResty reload 失败,请检查配置"
ErrEmailIsExist: '邮箱已存在' ErrEmailIsExist: '邮箱已存在'
ErrSSLKeyNotFound: '私钥文件不存在' ErrSSLKeyNotFound: '私钥文件不存在'
ErrSSLCertificateNotFound: '证书文件不存在' ErrSSLCertificateNotFound: '证书文件不存在'
@@ -181,18 +181,18 @@ ErrSSLKeyFormat: '私钥文件校验失败'
ErrSSLCertificateFormat: '证书文件格式错误,请使用 pem 格式' ErrSSLCertificateFormat: '证书文件格式错误,请使用 pem 格式'
ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid 或 EabHmacKey 不能为空' ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid 或 EabHmacKey 不能为空'
ErrOpenrestyNotFound: 'Http 模式需要首先安装 Openresty' ErrOpenrestyNotFound: 'Http 模式需要首先安装 Openresty'
ApplySSLStart: '开始申请证书,域名 [{{ .domain }}] 申请方式 [{{ .type }}] ' ApplySSLStart: '开始申请证书,域名 [{{ .domain }}],方式 [{{ .type }}]'
dnsAccount: "DNS 自动" dnsAccount: "DNS 自动"
dnsManual: "DNS 手动" dnsManual: "DNS 手动"
http: "HTTP" http: "HTTP"
ApplySSLFailed: '申请 [{{ .domain }}] 证书失败, {{ .detail }} ' ApplySSLFailed: '申请 [{{ .domain }}] 证书失败,{{ .detail }}'
ApplySSLSuccess: '申请 [{{ .domain }}] 证书成功!!' ApplySSLSuccess: '申请 [{{ .domain }}] 证书成功'
DNSAccountName: 'DNS 账号 [{{ .name }}] 厂商 [{{ .type }}]' DNSAccountName: 'DNS 账号 [{{ .name }}] 厂商 [{{ .type }}]'
PushDirLog: '证书推送到目录 [{{ .path }}] {{ .status }}' PushDirLog: '证书推送到目录 [{{ .path }}] {{ .status }}'
ErrDeleteCAWithSSL: "当前机构下存在已签发证书,无法删除" ErrDeleteCAWithSSL: "当前机构下存在已签发证书,无法删除"
ErrDeleteWithPanelSSL: "面板 SSL 配置使用此证书,无法删除" ErrDeleteWithPanelSSL: "面板 SSL 配置使用此证书,无法删除"
ErrDefaultCA: "默认机构不能删除" ErrDefaultCA: "默认机构不能删除"
ApplyWebSiteSSLLog: "开始更新 {{ .name }} 网站证书" ApplyWebSiteSSLLog: "开始更新网站证书 {{ .name }}"
ErrUpdateWebsiteSSL: "{{ .name }} 网站更新证书失败: {{ .err }}" ErrUpdateWebsiteSSL: "{{ .name }} 网站更新证书失败: {{ .err }}"
ApplyWebSiteSSLSuccess: "更新网站证书成功" ApplyWebSiteSSLSuccess: "更新网站证书成功"
ErrExecShell: "执行脚本失败 {{ .err }}" ErrExecShell: "执行脚本失败 {{ .err }}"
@@ -201,19 +201,19 @@ ExecShellSuccess: "脚本执行成功"
StartUpdateSystemSSL: "开始更新系统证书" StartUpdateSystemSSL: "开始更新系统证书"
UpdateSystemSSLSuccess: "更新系统证书成功" UpdateSystemSSLSuccess: "更新系统证书成功"
ErrWildcardDomain: "HTTP 模式无法申请泛域名证书" ErrWildcardDomain: "HTTP 模式无法申请泛域名证书"
ErrApplySSLCanNotDelete: "正在申请的证书{{.name}}无法删除,请稍后再试" ErrApplySSLCanNotDelete: "正在申请的证书{{ .name }}无法删除,请稍后重试"
StartPushSSLToNode: "开始推送证书到节点" StartPushSSLToNode: "开始推送证书到节点"
PushSSLToNodeFailed: "推送证书到节点失败: {{ .err }}" PushSSLToNodeFailed: "推送证书到节点失败: {{ .err }}"
PushSSLToNodeSuccess: "推送证书到节点成功" PushSSLToNodeSuccess: "推送证书到节点成功"
#mysql #mysql
ErrUserIsExist: "当前用户已存在,请重新输入" ErrUserIsExist: "用户已存在,请重新输入"
ErrDatabaseIsExist: "当前数据库已存在,请重新输入" ErrDatabaseIsExist: "数据库已存在,请重新输入"
ErrExecTimeOut: "SQL 执行超时,请检查数据库" ErrExecTimeOut: "SQL 执行超时,请检查数据库"
ErrRemoteExist: "远程数据库已存在该名称,请修改后重试" ErrRemoteExist: "远程数据库已存在该名称,请修改后重试"
ErrLocalExist: "本地数据库已存在该名称,请修改后重试" ErrLocalExist: "本地数据库已存在该名称,请修改后重试"
RemoteBackup: "备份远程数据库需要先使用镜像 {{ .name }} 启动本地容器数据库服务,请稍候..." RemoteBackup: "备份远程数据库前需先用镜像 {{ .name }} 启动本地容器数据库服务,请稍候"
RemoteRecover: "恢复远程数据库需要先使用镜像 {{ .name }} 启动本地容器数据库服务,请稍候..." RemoteRecover: "恢复远程数据库前需先用镜像 {{ .name }} 启动本地容器数据库服务,请稍候"
Arg: "参数" Arg: "参数"
#redis #redis
@@ -224,7 +224,7 @@ ErrInUsed: "{{ .detail }} 正被使用,无法删除!"
ErrObjectInUsed: "该对象正被使用,无法删除!" ErrObjectInUsed: "该对象正被使用,无法删除!"
ErrObjectBeDependent: "该镜像正被其他镜像所依赖,无法删除!" ErrObjectBeDependent: "该镜像正被其他镜像所依赖,无法删除!"
ErrPortRules: "端口数目不匹配,请重新输入!" ErrPortRules: "端口数目不匹配,请重新输入!"
ErrPgImagePull: "镜像拉取超时,请配置镜像加速或手动拉取 {{ .name }} 镜像后重试" ErrPgImagePull: "镜像拉取超时,请配置镜像加速或手动拉取 {{ .name }} 后重试"
PruneHelper: "本次清理 {{ .name }} 释放磁盘空间 {{ .size }}" PruneHelper: "本次清理 {{ .name }} 释放磁盘空间 {{ .size }}"
ImageRemoveHelper: "删除镜像 {{ .name }} ,释放磁盘空间 {{ .size }}" ImageRemoveHelper: "删除镜像 {{ .name }} ,释放磁盘空间 {{ .size }}"
BuildCache: "构建缓存" BuildCache: "构建缓存"
@@ -241,7 +241,7 @@ ErrRuntimeStart: "启动失败"
ErrPackageJsonNotFound: "package.json 文件不存在" ErrPackageJsonNotFound: "package.json 文件不存在"
ErrScriptsNotFound: "没有在 package.json 中找到 scripts 配置项" ErrScriptsNotFound: "没有在 package.json 中找到 scripts 配置项"
ErrContainerNameNotFound: "无法获取容器名称,请检查 .env 文件" ErrContainerNameNotFound: "无法获取容器名称,请检查 .env 文件"
ErrNodeModulesNotFound: "node_modules 文件夹不存在!请编辑运行环境或者等待运行环境启动成功" ErrNodeModulesNotFound: "node_modules 文件夹不存在!请编辑运行环境或等待运行环境启动成功"
ErrContainerNameIsNull: "容器名称不存在" ErrContainerNameIsNull: "容器名称不存在"
ErrPHPPortIsDefault: "9000 端口为默认端口,请修改后重试" ErrPHPPortIsDefault: "9000 端口为默认端口,请修改后重试"
ErrPHPRuntimePortFailed: "{{ .name }} 端口已被当前运行环境使用,请修改后重试" ErrPHPRuntimePortFailed: "{{ .name }} 端口已被当前运行环境使用,请修改后重试"
@@ -268,16 +268,16 @@ Upload: "上传"
IgnoreBackupErr: "备份失败,错误:{{ .detail }},忽略本次错误..." IgnoreBackupErr: "备份失败,错误:{{ .detail }},忽略本次错误..."
IgnoreUploadErr: "上传失败,错误:{{ .detail }},忽略本次错误..." IgnoreUploadErr: "上传失败,错误:{{ .detail }},忽略本次错误..."
LoadBackupFailed: "获取备份账号连接失败,错误:{{ .detail }}" LoadBackupFailed: "获取备份账号连接失败,错误:{{ .detail }}"
InExecuting: "当前任务正在执行中,请勿重复执行!" InExecuting: "任务执行中,请勿重复执行"
NoSuchResource: "数据库中未能查询到备份内容,跳过..." NoSuchResource: "数据库未查询到备份内容,跳过"
CleanLog: "清理日志" CleanLog: "清理日志"
CleanLogByName: "清理 {{.name}} 日志" CleanLogByName: "清理 {{ .name }} 日志"
WafIpGroupNotFound: "WAF IP组未找到,请先到【高级功能-WAF-黑白名单-IP组】添加远程下载方式的IP组" WafIpGroupNotFound: "WAF IP组未找到,请先到【高级功能-WAF-黑白名单-IP组】添加远程下载方式的IP组"
#toolbox #toolbox
ErrNotExistUser: "当前用户不存在,请修改后重试!" ErrNotExistUser: "当前用户不存在,请修改后重试!"
ErrBanAction: "设置失败,当前 {{ .name }} 服务不可用,请检查后重试!!" ErrBanAction: "设置失败,{{ .name }} 服务不可用,请检查后重试"
ErrClamdscanNotFound: "未检测到 clamdscan 命令,请参考文档安装!" ErrClamdscanNotFound: "未检测到 clamdscan 命令,请按文档安装"
TaskSwapSet: "设置 Swap" TaskSwapSet: "设置 Swap"
SetSwap: "设置 Swap {{ .path }} - {{ .size }}" SetSwap: "设置 Swap {{ .path }} - {{ .size }}"
CreateSwap: "创建 Swap 文件" CreateSwap: "创建 Swap 文件"
@@ -310,10 +310,10 @@ xss: 'XSS'
phpExec: 'PHP 脚本执行' phpExec: 'PHP 脚本执行'
oneWordTrojan: '一句话木马' oneWordTrojan: '一句话木马'
appFilter: '应用危险目录过滤' appFilter: '应用危险目录过滤'
webshell: 'Webshell' webShell: 'WebShell'
args: '参数规则' args: '参数规则'
protocolFilter: '协议过滤' protocolFilter: '协议过滤'
javaFileter: 'Java 危险文件过滤' javaFilter: 'Java 危险文件过滤'
scannerFilter: '扫描器过滤' scannerFilter: '扫描器过滤'
escapeFilter: '转义过滤' escapeFilter: '转义过滤'
customRule: '自定义规则' customRule: '自定义规则'
@@ -344,8 +344,8 @@ allow: "允许"
deny: "禁止" deny: "禁止"
OpenrestyNotFound: "Openresty 未安装" OpenrestyNotFound: "Openresty 未安装"
remoteIpIsNull: "IP 列表为空" remoteIpIsNull: "IP 列表为空"
OpenrestyVersionErr: "Openresty 版本过低,请升级 Openresty 至 1.27.1.2-2-2-focal" OpenrestyVersionErr: "OpenResty 版本过低,请升级到 1.27.1.2-2-2-focal"
ErrFileTooLarge: "文件超过 1MB 无法上传" ErrFileTooLarge: "文件超过 1MB,无法上传"
#task #task
TaskStart: "{{ .name }} 任务开始 [START]" TaskStart: "{{ .name }} 任务开始 [START]"
@@ -403,7 +403,7 @@ TaskSync: "同步"
LocalApp: "本地应用" LocalApp: "本地应用"
SubTask: "子任务" SubTask: "子任务"
RuntimeExtension: "运行环境扩展" RuntimeExtension: "运行环境扩展"
TaskIsExecuting: "任务正在运行" TaskIsExecuting: "任务运行中"
CustomAppstore: "自定义应用仓库" CustomAppstore: "自定义应用仓库"
TaskExec: "执行" TaskExec: "执行"
TaskBatch: "批量操作" TaskBatch: "批量操作"
@@ -414,14 +414,14 @@ Clamscan: "扫描 {{ .name }}"
TaskScan: "扫描" TaskScan: "扫描"
# task - ai # task - ai
OllamaModelPull: "拉取 Ollama 模型 {{ .name }} " OllamaModelPull: "拉取 Ollama 模型 {{ .name }}"
OllamaModelSize: "获取 Ollama 模型 {{ .name }} 大小 " OllamaModelSize: "获取 Ollama 模型 {{ .name }} 大小"
# task - snapshot # task - snapshot
Snapshot: "快照" Snapshot: "快照"
SnapDBInfo: "写入 1Panel 数据库信息" SnapDBInfo: "写入 1Panel 数据库信息"
SnapCopy: "复制文件&目录 {{ .name }} " SnapCopy: "复制文件/目录 {{ .name }}"
SnapNewDB: "初始化数据库 {{ .name }} 连接 " SnapNewDB: "初始化数据库 {{ .name }} 连接"
SnapDeleteOperationLog: "删除操作日志" SnapDeleteOperationLog: "删除操作日志"
SnapDeleteLoginLog: "删除访问日志" SnapDeleteLoginLog: "删除访问日志"
SnapDeleteMonitor: "删除监控数据" SnapDeleteMonitor: "删除监控数据"
@@ -451,10 +451,10 @@ RecoverDownloadAccount: "获取快照下载备份账号 {{ .name }}"
RecoverDecompress: "解压快照压缩文件" RecoverDecompress: "解压快照压缩文件"
Decompress: "解压" Decompress: "解压"
BackupBeforeRecover: "快照前备份系统相关数据" BackupBeforeRecover: "快照前备份系统相关数据"
Readjson: "读取快照内 Json 文件" ReadJson: "读取快照内 Json 文件"
ReadjsonPath: "获取快照内 Json 文件路径" ReadJsonPath: "获取快照内 Json 文件路径"
ReadjsonContent: "读取 Json 文件" ReadJsonContent: "读取 Json 文件"
ReadjsonMarshal: "Json 转义处理" ReadJsonMarshal: "Json 转义处理"
RecoverApp: "恢复已安装应用" RecoverApp: "恢复已安装应用"
RecoverWebsite: "恢复网站目录" RecoverWebsite: "恢复网站目录"
RecoverAppImage: "恢复快照镜像备份" RecoverAppImage: "恢复快照镜像备份"
@@ -470,7 +470,6 @@ RecoverBackups: "恢复本地备份目录"
RecoverPanelData: "恢复数据目录" RecoverPanelData: "恢复数据目录"
# task - container # task - container
ContainerNewCliet: "初始化 Docker Client"
ContainerImagePull: "拉取容器镜像 {{ .name }}" ContainerImagePull: "拉取容器镜像 {{ .name }}"
ContainerRemoveOld: "删除原容器 {{ .name }}" ContainerRemoveOld: "删除原容器 {{ .name }}"
ContainerImageCheck: "检查镜像是否正常拉取" ContainerImageCheck: "检查镜像是否正常拉取"
@@ -482,17 +481,12 @@ ContainerStartCheck: "检查容器是否已启动"
# task - image # task - image
ImageBuild: "镜像构建" ImageBuild: "镜像构建"
ImageBuildStdoutCheck: "解析镜像输出内容"
ImageBuildRes: "镜像构建输出:{{ .name }}"
ImagePull: "拉取镜像" ImagePull: "拉取镜像"
ImageRepoAuthFromDB: "从数据库获取仓库认证信息" ImageRepoAuthFromDB: "从数据库获取仓库认证信息"
ImaegPullRes: "镜像拉取输出:{{ .name }}"
ImagePush: "推送镜像" ImagePush: "推送镜像"
ImageRenameTag: "修改镜像 Tag" ImageRenameTag: "修改镜像 Tag"
ImageNewTag: "新镜像 Tag {{ .name }}" ImageNewTag: "新镜像 Tag {{ .name }}"
ImaegPushRes: "镜像推送输出:{{ .name }}"
ComposeCreate: "创建编排" ComposeCreate: "创建编排"
ComposeCreateRes: "编排创建输出:{{ .name }}"
# task - website # task - website
BackupNginxConfig: "备份网站 OpenResty 配置文件" BackupNginxConfig: "备份网站 OpenResty 配置文件"
@@ -503,15 +497,11 @@ ErrCheckValid: "校验备份文件失败,{{ .name }}"
Rollback: "回滚" Rollback: "回滚"
websiteDir: "网站目录" websiteDir: "网站目录"
RecoverFailedStartRollBack: "恢复失败,开始回滚" RecoverFailedStartRollBack: "恢复失败,开始回滚"
AppBackupFileIncomplete: "备份文件不完整 缺少 app.json 或者 app.tar.gz 文件" AppBackupFileIncomplete: "备份文件不完整,缺少 app.json 或 app.tar.gz 文件"
AppAttributesNotMatch: "应用类型或者名称不一致" AppAttributesNotMatch: "应用类型或名称不一致"
#alert #alert
ErrAlert: "告警信息格式错误,请检查后重试!!" ErrAlertSync: "告警信息同步错误,请检查后重试"
ErrAlertPush: "告警信息推送错误,请检查后重试!!"
ErrAlertSave: "告警信息保存错误,请检查后重试!!"
ErrAlertSync: "告警信息同步错误,请检查后重试!!"
ErrAlertRemote: "告警信息远端错误,请检查后重试!!"
#task - runtime #task - runtime
ErrInstallExtension: "已有安装任务正在进行,请等待任务结束" ErrInstallExtension: "已有安装任务正在进行,请等待任务结束"
@@ -519,20 +509,20 @@ ErrInstallExtension: "已有安装任务正在进行,请等待任务结束"
# alert mail template # alert mail template
PanelAlertTitle: "面板告警通知" PanelAlertTitle: "面板告警通知"
TestAlertTitle: "测试邮件 - 验证邮箱连通性" TestAlertTitle: "测试邮件 - 验证邮箱连通性"
TestAlert: "这是一封测试邮件,旨在验证您的邮箱发件配置是否正确。" TestAlert: "这是一封测试邮件,用于验证邮箱发件配置。"
LicenseExpirationAlert: "您的 {{ .node }}{{ .ip }} 面板,许可证将在 {{ .day }} 天后到期,详情请登录面板查看。" LicenseExpirationAlert: "您的 {{ .node }}{{ .ip }} 面板,许可证将在 {{ .day }} 天后到期,请登录面板查看详情。"
CronJobFailedAlert: "您的 {{ .node }}{{ .ip }} 面板,计划任务-{{ .name }}执行失败,详情请登录面板查看。" CronJobFailedAlert: "您的 {{ .node }}{{ .ip }} 面板,计划任务-{{ .name }}执行失败,请登录面板查看详情。"
ClamAlert: "您的 {{ .node }}{{ .ip }} 面板,病毒扫描任务发现 {{ .num }} 个感染文件,详情请登录面板查看。" ClamAlert: "您的 {{ .node }}{{ .ip }} 面板,病毒扫描任务发现 {{ .num }} 个感染文件,请登录面板查看详情。"
WebSiteAlert: "您的 {{ .node }}{{ .ip }} 面板,有 {{ .num }} 个网站将在 {{ .day }} 天后到期,详情请登录面板查看。" WebSiteAlert: "您的 {{ .node }}{{ .ip }} 面板,有 {{ .num }} 个网站将在 {{ .day }} 天后到期,请登录面板查看详情。"
SSLAlert: "您的 {{ .node }}{{ .ip }} 面板,有 {{ .num }} 张SSL证书将在 {{ .day }} 天后到期,详情请登录面板查看。" SSLAlert: "您的 {{ .node }}{{ .ip }} 面板,有 {{ .num }} 张SSL证书将在 {{ .day }} 天后到期,请登录面板查看详情。"
DiskUsedAlert: "您的 {{ .node }}{{ .ip }} 面板,磁盘 {{ .name }} 已使用 {{ .used }},详情请登录面板查看。" DiskUsedAlert: "您的 {{ .node }}{{ .ip }} 面板,磁盘 {{ .name }} 已使用 {{ .used }},请登录面板查看详情。"
ResourceAlert: "您的 {{ .node }}{{ .ip }} 面板,平均 {{ .time }} 分钟内的 {{ .name }} 使用率为 {{ .used }},详情请登录面板查看。" ResourceAlert: "您的 {{ .node }}{{ .ip }} 面板,平均 {{ .time }} 分钟内的 {{ .name }} 使用率为 {{ .used }},请登录面板查看详情。"
PanelVersionAlert: "您的 {{ .node }}{{ .ip }} 面板,有最新面板版本可供升级,详情请登录面板查看。" PanelVersionAlert: "您的 {{ .node }}{{ .ip }} 面板,有最新面板版本可供升级,请登录面板查看详情。"
PanelPwdExpirationAlert: "您的 {{ .node }}{{ .ip }} 面板,面板密码将在 {{ .day }} 天后到期,详情请登录面板查看。" PanelPwdExpirationAlert: "您的 {{ .node }}{{ .ip }} 面板,面板密码将在 {{ .day }} 天后到期,请登录面板查看详情。"
CommonAlert: "您的 {{ .node }}{{ .ip }} 面板,{{ .msg }},详情请登录面板查看。" CommonAlert: "您的 {{ .node }}{{ .ip }} 面板,{{ .msg }},请登录面板查看详情。"
NodeExceptionAlert: "您的 {{ .node }}{{ .ip }} 面板,{{ .num }} 个节点存在异常,详情请登录面板查看。" NodeExceptionAlert: "您的 {{ .node }}{{ .ip }} 面板,{{ .num }} 个节点存在异常,请登录面板查看详情。"
LicenseExceptionAlert: "您的 {{ .node }}{{ .ip }} 面板,{{ .num }} 个许可证存在异常,详情请登录面板查看。" LicenseExceptionAlert: "您的 {{ .node }}{{ .ip }} 面板,{{ .num }} 个许可证存在异常,请登录面板查看详情。"
SSHAndPanelLoginAlert: "您的 {{ .node }}{{ .ip }} 面板,面板{{ .name }}登录{{ .loginIp }}异常,详情请登录面板查看。" SSHAndPanelLoginAlert: "您的 {{ .node }}{{ .ip }} 面板,面板 {{ .name }} 登录 {{ .loginIp }} 异常,请登录面板查看详情。"
#disk #disk
DeviceNotFound: "设备 {{ .name }} 未找到" DeviceNotFound: "设备 {{ .name }} 未找到"
@@ -540,5 +530,4 @@ DeviceIsMounted: "设备 {{ .name }} 已挂载,请先卸载"
PartitionDiskErr: "分区失败,{{ .err }}" PartitionDiskErr: "分区失败,{{ .err }}"
FormatDiskErr: "格式化磁盘失败,{{ .err }}" FormatDiskErr: "格式化磁盘失败,{{ .err }}"
MountDiskErr: "挂载磁盘失败,{{ .err }}" MountDiskErr: "挂载磁盘失败,{{ .err }}"
UnMountDiskErr: "卸载磁盘失败,{{ .err }}"
XfsNotFound: "未检测到 xfs 文件系统,请先安装 xfsprogs" XfsNotFound: "未检测到 xfs 文件系统,请先安装 xfsprogs"
+8 -1
View File
@@ -27,11 +27,12 @@ func Init() {
initDockerConf() initDockerConf()
initAlertTask() initAlertTask()
initMonitorDB()
} }
func initGlobalData() { func initGlobalData() {
settingRepo := repo.NewISettingRepo() settingRepo := repo.NewISettingRepo()
if _, err := settingRepo.Get(settingRepo.WithByKey("SystemStatus")); err != nil { if _, err := settingRepo.GetValueByKey("SystemStatus"); err != nil {
_ = settingRepo.Create("SystemStatus", "Free") _ = settingRepo.Create("SystemStatus", "Free")
} }
if err := settingRepo.Update("SystemStatus", "Free"); err != nil { if err := settingRepo.Update("SystemStatus", "Free"); err != nil {
@@ -42,6 +43,7 @@ func initGlobalData() {
_ = settingRepo.Update("SystemVersion", node.Version) _ = settingRepo.Update("SystemVersion", node.Version)
} }
global.CONF.Base.Version = node.Version global.CONF.Base.Version = node.Version
global.CONF.Base.Edition, _ = settingRepo.GetValueByKey("Edition")
global.CONF.Base.EncryptKey, _ = settingRepo.GetValueByKey("EncryptKey") global.CONF.Base.EncryptKey, _ = settingRepo.GetValueByKey("EncryptKey")
} }
@@ -151,3 +153,8 @@ func initDockerConf() {
func initAlertTask() { func initAlertTask() {
service.NewIAlertTaskHelper().ResetTask() service.NewIAlertTaskHelper().ResetTask()
} }
func initMonitorDB() {
_ = global.MonitorDB.AutoMigrate(&model.MonitorBase{}, &model.MonitorNetwork{}, &model.MonitorGPU{}, &model.MonitorIO{})
_ = global.TaskDB.AutoMigrate(&model.Task{})
}
+2 -2
View File
@@ -105,7 +105,7 @@ func loadRestorePath(upgradeDir string) (string, error) {
} }
func downloadLangFromRemote(fileOp files.FileOp) { 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 { if err := fileOp.DownloadFile(path, "/usr/local/bin/lang.tar.gz"); err != nil {
global.LOG.Errorf("download lang.tar.gz failed, err: %v", err) global.LOG.Errorf("download lang.tar.gz failed, err: %v", err)
return return
@@ -123,7 +123,7 @@ func downloadLangFromRemote(fileOp files.FileOp) {
} }
func downloadGeoFromRemote(fileOp files.FileOp, targetPath string) { func downloadGeoFromRemote(fileOp files.FileOp, targetPath string) {
_ = os.MkdirAll(path.Dir(targetPath), os.ModePerm) _ = 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 { if err := fileOp.DownloadFile(pathItem, targetPath); err != nil {
global.LOG.Errorf("download geo ip failed, err: %v", err) global.LOG.Errorf("download geo ip failed, err: %v", err)
return return
+7
View File
@@ -65,6 +65,13 @@ func InitAgentDB() {
migrations.AddWebsiteAcmeAccountColumn, migrations.AddWebsiteAcmeAccountColumn,
migrations.AddAgentTables, migrations.AddAgentTables,
migrations.MigrateOpenclawAgents, migrations.MigrateOpenclawAgents,
migrations.AddAgentCustomModelFields,
migrations.AddAppInstallSortOrder,
migrations.AddAgentAccountRememberAPIKey,
migrations.AddEditionSetting,
migrations.AddAgentTypeForAgents,
migrations.NormalizeAgentAccountVerifiedStatus,
migrations.NormalizeOllamaAccountAPIType,
}) })
if err := m.Migrate(); err != nil { if err := m.Migrate(); err != nil {
global.LOG.Error(err) global.LOG.Error(err)
+94 -1
View File
@@ -128,7 +128,8 @@ var InitSetting = &gormigrate.Migration{
if err := tx.Create(&model.Setting{Key: "SystemStatus", Value: "Free"}).Error; err != nil { if err := tx.Create(&model.Setting{Key: "SystemStatus", Value: "Free"}).Error; err != nil {
return err 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 return err
} }
if err := tx.Create(&model.Setting{Key: "SystemIP", Value: ""}).Error; err != nil { if err := tx.Create(&model.Setting{Key: "SystemIP", Value: ""}).Error; err != nil {
@@ -941,3 +942,95 @@ var MigrateOpenclawAgents = &gormigrate.Migration{
return nil return nil
}, },
} }
var AddAgentCustomModelFields = &gormigrate.Migration{
ID: "20260224-add-agent-custom-model-fields",
Migrate: func(tx *gorm.DB) error {
if err := tx.AutoMigrate(&model.Agent{}, &model.AgentAccount{}); err != nil {
return err
}
if err := tx.Model(&model.AgentAccount{}).Where("api_type = '' OR api_type IS NULL").Update("api_type", "openai-completions").Error; err != nil {
return err
}
if err := tx.Model(&model.Agent{}).Where("api_type = '' OR api_type IS NULL").Update("api_type", "openai-completions").Error; err != nil {
return err
}
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
},
}
+9
View File
@@ -54,5 +54,14 @@ func (a *AIToolsRouter) InitRouter(Router *gin.RouterGroup) {
aiToolsRouter.POST("/agents/channel/feishu/get", baseApi.GetAgentFeishuConfig) aiToolsRouter.POST("/agents/channel/feishu/get", baseApi.GetAgentFeishuConfig)
aiToolsRouter.POST("/agents/channel/feishu/update", baseApi.UpdateAgentFeishuConfig) aiToolsRouter.POST("/agents/channel/feishu/update", baseApi.UpdateAgentFeishuConfig)
aiToolsRouter.POST("/agents/channel/feishu/approve", baseApi.ApproveAgentFeishuPairing) 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/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)
} }
} }
+1
View File
@@ -40,6 +40,7 @@ func (a *AppRouter) InitRouter(Router *gin.RouterGroup) {
appRouter.POST("/installed/params/update", baseApi.UpdateInstalled) appRouter.POST("/installed/params/update", baseApi.UpdateInstalled)
appRouter.POST("/installed/update/versions", baseApi.GetUpdateVersions) appRouter.POST("/installed/update/versions", baseApi.GetUpdateVersions)
appRouter.POST("/installed/config/update", baseApi.UpdateAppConfig) appRouter.POST("/installed/config/update", baseApi.UpdateAppConfig)
appRouter.POST("/installed/sort/update", baseApi.UpdateAppInstallSort)
appRouter.GET("/installed/info/:appInstallId", baseApi.GetAppInstallInfo) appRouter.GET("/installed/info/:appInstallId", baseApi.GetAppInstallInfo)
appRouter.POST("/installed/ignore", baseApi.IgnoreAppUpgrade) appRouter.POST("/installed/ignore", baseApi.IgnoreAppUpgrade)
-1
View File
@@ -15,7 +15,6 @@ func (s *ContainerRouter) InitRouter(Router *gin.RouterGroup) {
baRouter.GET("/stats/:id", baseApi.ContainerStats) baRouter.GET("/stats/:id", baseApi.ContainerStats)
baRouter.POST("", baseApi.ContainerCreate) baRouter.POST("", baseApi.ContainerCreate)
baRouter.POST("command", baseApi.ContainerCreateByCommand)
baRouter.POST("/update", baseApi.ContainerUpdate) baRouter.POST("/update", baseApi.ContainerUpdate)
baRouter.POST("/upgrade", baseApi.ContainerUpgrade) baRouter.POST("/upgrade", baseApi.ContainerUpgrade)
baRouter.POST("/info", baseApi.ContainerInfo) baRouter.POST("/info", baseApi.ContainerInfo)
+2
View File
@@ -54,6 +54,8 @@ func (a *WebsiteRouter) InitRouter(Router *gin.RouterGroup) {
websiteRouter.POST("/proxies", baseApi.GetProxyConfig) websiteRouter.POST("/proxies", baseApi.GetProxyConfig)
websiteRouter.POST("/proxies/update", baseApi.UpdateProxyConfig) 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("/proxies/file", baseApi.UpdateProxyConfigFile)
websiteRouter.POST("/proxy/config", baseApi.UpdateProxyCache) websiteRouter.POST("/proxy/config", baseApi.UpdateProxyCache)
websiteRouter.GET("/proxy/config/:id", baseApi.GetProxyCache) websiteRouter.GET("/proxy/config/:id", baseApi.GetProxyCache)
+36 -16
View File
@@ -4,7 +4,7 @@ import (
"crypto/rand" "crypto/rand"
"fmt" "fmt"
"io" "io"
mathRand "math/rand" "math/big"
"net" "net"
"os/exec" "os/exec"
"reflect" "reflect"
@@ -135,13 +135,6 @@ func isDigit(r rune) bool {
return r >= '0' && r <= '9' return r >= '0' && r <= '9'
} }
func max(x, y int) int {
if x > y {
return x
}
return y
}
func GetSortedVersions(versions []string) []string { func GetSortedVersions(versions []string) []string {
sort.Slice(versions, func(i, j int) bool { sort.Slice(versions, func(i, j int) bool {
return CompareVersion(versions[i], versions[j]) return CompareVersion(versions[i], versions[j])
@@ -169,21 +162,29 @@ var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456
func RandStr(n int) string { func RandStr(n int) string {
b := make([]rune, n) b := make([]rune, n)
max := big.NewInt(int64(len(letters)))
for i := range b { 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) return string(b)
} }
func RandStrAndNum(n int) string { func RandStrAndNum(n int) string {
source := mathRand.NewSource(time.Now().UnixNano())
randGen := mathRand.New(source)
const charset = "abcdefghijklmnopqrstuvwxyz0123456789" const charset = "abcdefghijklmnopqrstuvwxyz0123456789"
b := make([]byte, n) b := make([]byte, n)
max := big.NewInt(int64(len(charset)))
for i := range b { 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 { func ScanPort(port int) bool {
@@ -191,7 +192,7 @@ func ScanPort(port int) bool {
if err != nil { if err != nil {
return true return true
} }
defer ln.Close() defer func() { _ = ln.Close() }()
return false return false
} }
@@ -200,7 +201,7 @@ func ScanUDPPort(port int) bool {
if err != nil { if err != nil {
return true return true
} }
defer ln.Close() defer func() { _ = ln.Close() }()
return false return false
} }
@@ -225,7 +226,7 @@ func ScanPortWithIP(ip string, port int) bool {
} }
return false return false
} }
defer conn.Close() defer func() { _ = conn.Close() }()
return true return true
} }
@@ -419,3 +420,22 @@ func GetDockerComposeCommand() string {
} }
return "" 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", "")
}
+20 -5
View File
@@ -67,14 +67,29 @@ func GetDBWithPath(dbPath string) (*gorm.DB, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
sqlDB, dbError := db.DB()
if dbError != nil { sqlDB, err := db.DB()
return nil, dbError if err != nil {
return nil, err
} }
sqlDB.SetMaxOpenConns(4) sqlDB.SetMaxOpenConns(4)
sqlDB.SetMaxIdleConns(1) sqlDB.SetMaxIdleConns(1)
sqlDB.SetConnMaxIdleTime(15 * time.Minute) sqlDB.SetConnMaxLifetime(0)
sqlDB.SetConnMaxLifetime(time.Hour) 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 return db, nil
} }
+91 -19
View File
@@ -15,7 +15,6 @@ import (
"github.com/1Panel-dev/1Panel/agent/utils/cmd" "github.com/1Panel-dev/1Panel/agent/utils/cmd"
"github.com/1Panel-dev/1Panel/agent/utils/common" "github.com/1Panel-dev/1Panel/agent/utils/common"
"github.com/1Panel-dev/1Panel/agent/utils/docker" "github.com/1Panel-dev/1Panel/agent/utils/docker"
"gopkg.in/yaml.v3"
) )
func checkCmd() error { func checkCmd() error {
@@ -29,31 +28,37 @@ func checkCmd() error {
return nil 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) { func Up(filePath string) (string, error) {
if err := checkCmd(); err != nil { if err := checkCmd(); err != nil {
return "", err 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 { func UpWithTask(filePath string, task *task.Task, forcePull bool) error {
if err := pullComposeImages(filePath, forcePull, task); err != nil { if err := pullComposeImages(filePath, forcePull, task); err != nil {
return err return err
} }
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 { func pullComposeImages(filePath string, forcePull bool, task *task.Task) error {
content, err := os.ReadFile(filePath) images, err := GetComposeImages(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)
if err != nil { if err != nil {
return err return err
} }
@@ -110,32 +115,94 @@ func pullComposeImages(filePath string, forcePull bool, task *task.Task) error {
return nil 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", "--images")
stdout, err := cmd.NewCommandMgr(cmd.WithTimeout(5*time.Minute)).
RunWithStdout(base, args...)
if err != nil {
return nil, fmt.Errorf("run compose config --images failed, std: %s, err: %v", stdout, err)
}
var images []string
seen := make(map[string]struct{})
for _, line := range strings.Split(stdout, "\n") {
image := strings.TrimSpace(line)
if len(image) == 0 {
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")
}
return images, nil
}
func Down(filePath string) (string, error) { func Down(filePath string) (string, error) {
if err := checkCmd(); err != nil { if err := checkCmd(); err != nil {
return "", err 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) { func Stop(filePath string) (string, error) {
if err := checkCmd(); err != nil { if err := checkCmd(); err != nil {
return "", err 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) { func Restart(filePath string) (string, error) {
if err := checkCmd(); err != nil { if err := checkCmd(); err != nil {
return "", err 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) { func Operate(filePath, operation string) (string, error) {
if err := checkCmd(); err != nil { if err := checkCmd(); err != nil {
return "", err 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) { func DownAndUp(filePath string) (string, error) {
@@ -143,11 +210,16 @@ func DownAndUp(filePath string) (string, error) {
return "", err return "", err
} }
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(20 * time.Minute)) 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 { if err != nil {
return stdout, err 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 return stdout, err
} }
+22 -4
View File
@@ -118,10 +118,24 @@ func padding(plaintext []byte, blockSize int) []byte {
return append(plaintext, padtext...) return append(plaintext, padtext...)
} }
func unPadding(origData []byte) []byte { func unPadding(origData []byte) ([]byte, error) {
length := len(origData) length := len(origData)
if length == 0 {
return nil, fmt.Errorf("invalid padding size")
}
unpadding := int(origData[length-1]) 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) { func aesEncryptWithSalt(key, plaintext []byte) ([]byte, error) {
@@ -152,6 +166,10 @@ func aesDecryptWithSalt(key, ciphertext []byte) ([]byte, error) {
ciphertext = ciphertext[aes.BlockSize:] ciphertext = ciphertext[aes.BlockSize:]
cbc := cipher.NewCBCDecrypter(block, iv) cbc := cipher.NewCBCDecrypter(block, iv)
cbc.CryptBlocks(ciphertext, ciphertext) cbc.CryptBlocks(ciphertext, ciphertext)
ciphertext = unPadding(ciphertext)
return ciphertext, nil unpadded, err := unPadding(ciphertext)
if err != nil {
return nil, err
}
return unpadded, nil
} }
+4 -4
View File
@@ -233,7 +233,7 @@ func (r *Local) Backup(info BackupInfo) error {
if err != nil { if err != nil {
return fmt.Errorf("open file %s failed, err: %v", path.Join(info.TargetDir, info.FileName), err) 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" dumpCmd := "mysqldump"
if r.Type == constant.AppMariaDB { if r.Type == constant.AppMariaDB {
dumpCmd = "mariadb-dump" dumpCmd = "mariadb-dump"
@@ -268,7 +268,7 @@ func (r *Local) Backup(info BackupInfo) error {
func (r *Local) Recover(info RecoverInfo) error { func (r *Local) Recover(info RecoverInfo) error {
fi, _ := os.Open(info.SourceFile) fi, _ := os.Open(info.SourceFile)
defer fi.Close() defer func() { _ = fi.Close() }()
mysqlCli := r.Type mysqlCli := r.Type
if mysqlCli == "mysql-cluster" { if mysqlCli == "mysql-cluster" {
mysqlCli = "mysql" mysqlCli = "mysql"
@@ -280,12 +280,12 @@ func (r *Local) Recover(info RecoverInfo) error {
if err != nil { if err != nil {
return err return err
} }
defer gzipFile.Close() defer func() { _ = gzipFile.Close() }()
gzipReader, err := gzip.NewReader(gzipFile) gzipReader, err := gzip.NewReader(gzipFile)
if err != nil { if err != nil {
return err return err
} }
defer gzipReader.Close() defer func() { _ = gzipReader.Close() }()
cmd.Stdin = gzipReader cmd.Stdin = gzipReader
} else { } else {
cmd.Stdin = fi cmd.Stdin = fi
+7 -6
View File
@@ -248,7 +248,7 @@ func (r *Remote) Backup(info BackupInfo) error {
if err != nil { if err != nil {
return fmt.Errorf("open file %s failed, err: %v", path.Join(info.TargetDir, info.FileName), err) 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" dumpCmd := "mysqldump"
if r.Type == constant.AppMariaDB { if r.Type == constant.AppMariaDB {
dumpCmd = "mariadb-dump" dumpCmd = "mariadb-dump"
@@ -293,7 +293,7 @@ func (r *Remote) Recover(info RecoverInfo) error {
return buserr.New("ErrCmdIllegal") return buserr.New("ErrCmdIllegal")
} }
fi, _ := os.Open(info.SourceFile) fi, _ := os.Open(info.SourceFile)
defer fi.Close() defer func() { _ = fi.Close() }()
image, err := loadImage(info.Type, info.Version) image, err := loadImage(info.Type, info.Version)
if err != nil { if err != nil {
@@ -311,12 +311,12 @@ func (r *Remote) Recover(info RecoverInfo) error {
if err != nil { if err != nil {
return err return err
} }
defer gzipFile.Close() defer func() { _ = gzipFile.Close() }()
gzipReader, err := gzip.NewReader(gzipFile) gzipReader, err := gzip.NewReader(gzipFile)
if err != nil { if err != nil {
return err return err
} }
defer gzipReader.Close() defer func() { _ = gzipReader.Close() }()
cmd.Stdin = gzipReader cmd.Stdin = gzipReader
} else { } else {
cmd.Stdin = fi cmd.Stdin = fi
@@ -336,7 +336,7 @@ func (r *Remote) SyncDB(version string) ([]SyncDBInfo, error) {
if err != nil { if err != nil {
return datas, err return datas, err
} }
defer rows.Close() defer func() { _ = rows.Close() }()
for rows.Next() { for rows.Next() {
var dbName, charsetName, collation string var dbName, charsetName, collation string
@@ -431,7 +431,7 @@ func (r *Remote) LoadFormatCollation(timeout uint) ([]dto.MysqlFormatCollationOp
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer rows.Close() defer func() { _ = rows.Close() }()
formatMap := make(map[string][]string) formatMap := make(map[string][]string)
for rows.Next() { for rows.Next() {
@@ -471,6 +471,7 @@ func (r *Remote) ExecSQLForHosts(timeout uint) ([]string, error) {
return nil, buserr.New("ErrExecTimeOut") return nil, buserr.New("ErrExecTimeOut")
} }
var rows []string var rows []string
defer func() { _ = results.Close() }()
for results.Next() { for results.Next() {
var host string var host string
if err := results.Scan(&host); err != nil { if err := results.Scan(&host); err != nil {
+102
View File
@@ -0,0 +1,102 @@
package nginx
import (
"errors"
"net/url"
"strings"
"unicode"
"github.com/1Panel-dev/1Panel/agent/utils/re"
)
type Mode int
const (
ModeGeneric Mode = iota
ModeHost
ModeURL
ModePath
ModeAllowMethods
)
func NginxSafeString(input string, mode Mode) (string, error) {
if input == "" {
return "", errors.New("empty value not allowed")
}
for _, r := range input {
if unicode.IsControl(r) {
return "", errors.New("control characters not allowed")
}
}
if strings.ContainsAny(input, ";\n\r{}#`$") {
return "", errors.New("illegal nginx syntax characters")
}
switch mode {
case ModeHost:
return validateHost(input)
case ModeURL:
return validateURL(input)
case ModePath:
return validatePath(input)
case ModeAllowMethods:
return validateAllowMethods(input)
default:
return input, nil
}
}
func validateHost(host string) (string, error) {
if !re.GetRegex(re.NginxHostPattern).MatchString(host) {
return "", errors.New("invalid host format")
}
return host, nil
}
func validateURL(raw string) (string, error) {
u, err := url.Parse(raw)
if err != nil {
return "", errors.New("invalid url")
}
if u.Scheme != "http" && u.Scheme != "https" {
return "", errors.New("unsupported scheme")
}
if u.Host == "" {
return "", errors.New("missing host")
}
return raw, nil
}
func validatePath(p string) (string, error) {
if !re.GetRegex(re.NginxPathPattern).MatchString(p) {
return "", errors.New("invalid path")
}
return p, nil
}
var allowedMethods = map[string]bool{
"GET": true,
"POST": true,
"PUT": true,
"DELETE": true,
"PATCH": true,
"OPTIONS": true,
"HEAD": true,
}
func validateAllowMethods(input string) (string, error) {
parts := strings.Split(input, ",")
for i, method := range parts {
method = strings.TrimSpace(strings.ToUpper(method))
if !allowedMethods[method] {
return "", errors.New("invalid HTTP method: " + method)
}
parts[i] = method
}
return strings.Join(parts, ", "), nil
}
+4
View File
@@ -29,6 +29,8 @@ const (
AnsiEscapePattern = "\x1b\\[[0-9;?]*[A-Za-z]|\x1b=|\x1b>" AnsiEscapePattern = "\x1b\\[[0-9;?]*[A-Za-z]|\x1b=|\x1b>"
RecycleBinFilePattern = `_1p_file_1p_(.+)_p_(\d+)_(\d+)` RecycleBinFilePattern = `_1p_file_1p_(.+)_p_(\d+)_(\d+)`
OrderByValidationPattern = `^[a-zA-Z_][a-zA-Z0-9_]*$` OrderByValidationPattern = `^[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) var regexMap = make(map[string]*regexp.Regexp)
@@ -58,6 +60,8 @@ func Init() {
AnsiEscapePattern, AnsiEscapePattern,
RecycleBinFilePattern, RecycleBinFilePattern,
OrderByValidationPattern, OrderByValidationPattern,
NginxHostPattern,
NginxPathPattern,
} }
for _, pattern := range patterns { for _, pattern := range patterns {
+10
View File
@@ -24,6 +24,7 @@ import (
"github.com/go-acme/lego/v4/providers/dns/regru" "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/route53"
"github.com/go-acme/lego/v4/providers/dns/spaceship" "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/tencentcloud"
"github.com/go-acme/lego/v4/providers/dns/vercel" "github.com/go-acme/lego/v4/providers/dns/vercel"
"github.com/go-acme/lego/v4/providers/dns/volcengine" "github.com/go-acme/lego/v4/providers/dns/volcengine"
@@ -59,6 +60,7 @@ const (
Ovh DnsType = "Ovh" Ovh DnsType = "Ovh"
AcmeDNS DnsType = "AcmeDNS" AcmeDNS DnsType = "AcmeDNS"
PorkBun DnsType = "PorkBun" PorkBun DnsType = "PorkBun"
Technitium DnsType = "Technitium"
) )
type DNSParam struct { type DNSParam struct {
@@ -301,6 +303,14 @@ func getDNSProviderConfig(dnsType DnsType, params string) (challenge.Provider, e
config.PollingInterval = pollingInterval config.PollingInterval = pollingInterval
config.TTL = ttl config.TTL = ttl
p, err = porkbun.NewDNSProviderConfig(config) 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 { if err != nil {
+3 -3
View File
@@ -74,15 +74,15 @@ func (f *Fail2ban) Operate(operate string) error {
func (f *Fail2ban) ReBanIPs(ips []string) error { func (f *Fail2ban) ReBanIPs(ips []string) error {
ipItems, _ := f.ListBanned() 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 { 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 { if err != nil {
global.LOG.Errorf("rebanip after fail2ban-client unban --all failed, err: %s", stdout1) global.LOG.Errorf("rebanip after fail2ban-client unban --all failed, err: %s", stdout1)
} }
return fmt.Errorf("fail2ban-client unban --all failed, err: %s", stdout) 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 { if err != nil {
return fmt.Errorf("handle `fail2ban-client set sshd banip %s` failed, err: %s", strings.Join(ips, " "), stdout) return fmt.Errorf("handle `fail2ban-client set sshd banip %s` failed, err: %s", strings.Join(ips, " "), stdout)
} }
+3 -3
View File
@@ -51,7 +51,7 @@ func GetUpgradeVersionInfo() (*dto.UpgradeInfo, error) {
if strings.Contains(itemVersion, "beta") { if strings.Contains(itemVersion, "beta") {
mode = "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 { if err != nil {
return nil, fmt.Errorf("load releases-notes of version %s failed, err: %v", itemVersion, err) 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 { 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 { 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) _, latestVersionRes, err := HandleRequest(path, http.MethodGet, constant.TimeOut20s)
if err != nil { if err != nil {
+3 -17
View File
@@ -4,17 +4,15 @@ package xpack
import ( import (
"crypto/tls" "crypto/tls"
"fmt"
"net" "net"
"net/http" "net/http"
"strings"
"time" "time"
"github.com/1Panel-dev/1Panel/agent/app/dto" "github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/app/model" "github.com/1Panel-dev/1Panel/agent/app/model"
"github.com/1Panel-dev/1Panel/agent/buserr" "github.com/1Panel-dev/1Panel/agent/buserr"
"github.com/1Panel-dev/1Panel/agent/global" "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" "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) { func LoadNodeInfo(isBase bool) (model.NodeInfo, error) {
var info model.NodeInfo var info model.NodeInfo
info.BaseDir = loadParams("BASE_DIR") info.BaseDir = common.LoadParams("BASE_DIR")
info.Version = loadParams("ORIGINAL_VERSION") info.Version = common.LoadParams("ORIGINAL_VERSION")
info.Scope = "master" info.Scope = "master"
global.IsMaster = true global.IsMaster = true
return info, nil 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 { func GetImagePrefix() string {
return "" return ""
} }
+17 -3
View File
@@ -9,6 +9,7 @@ import (
"github.com/1Panel-dev/1Panel/core/app/api/v2/helper" "github.com/1Panel-dev/1Panel/core/app/api/v2/helper"
"github.com/1Panel-dev/1Panel/core/app/dto" "github.com/1Panel-dev/1Panel/core/app/dto"
"github.com/1Panel-dev/1Panel/core/app/model" "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/constant"
"github.com/1Panel-dev/1Panel/core/global" "github.com/1Panel-dev/1Panel/core/global"
"github.com/1Panel-dev/1Panel/core/utils/captcha" "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)) 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" || msgKey == "ErrEntrance" {
if msgKey == "ErrAuth" { if msgKey == "ErrAuth" {
global.IPTracker.SetNeedCaptcha(ip) global.IPTracker.SetNeedCaptcha(ip)
@@ -90,6 +93,7 @@ func (b *BaseApi) MFALogin(c *gin.Context) {
} }
user, msgKey, err := authService.MFALogin(c, req, string(entrance)) user, msgKey, err := authService.MFALogin(c, req, string(entrance))
go saveLoginLogs(c, wrapLoginErr(msgKey, err))
if msgKey == "ErrAuth" { if msgKey == "ErrAuth" {
helper.BadAuth(c, msgKey, err) helper.BadAuth(c, msgKey, err)
return return
@@ -135,7 +139,7 @@ func (b *BaseApi) PasskeyFinishLogin(c *gin.Context) {
sessionID := c.GetHeader("Passkey-Session") sessionID := c.GetHeader("Passkey-Session")
entrance := loadEntranceFromRequest(c) entrance := loadEntranceFromRequest(c)
user, msgKey, err := authService.PasskeyFinishLogin(c, sessionID, entrance) 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" || msgKey == "ErrEntrance" {
if msgKey == "ErrAuth" { if msgKey == "ErrAuth" {
global.IPTracker.SetNeedCaptcha(common.GetRealClientIP(c)) global.IPTracker.SetNeedCaptcha(common.GetRealClientIP(c))
@@ -211,7 +215,7 @@ func (b *BaseApi) GetLoginSetting(c *gin.Context) {
needCaptcha := global.IPTracker.NeedCaptcha(ip) needCaptcha := global.IPTracker.NeedCaptcha(ip)
res := &dto.LoginSetting{ res := &dto.LoginSetting{
IsDemo: global.CONF.Base.IsDemo, IsDemo: global.CONF.Base.IsDemo,
IsIntl: global.CONF.Base.IsIntl, IsIntl: global.CONF.Base.Edition == "intl",
IsFxplay: global.CONF.Base.IsFxplay, IsFxplay: global.CONF.Base.IsFxplay,
IsOffLine: global.CONF.Base.IsOffLine, IsOffLine: global.CONF.Base.IsOffLine,
Language: settingInfo.Language, Language: settingInfo.Language,
@@ -237,6 +241,16 @@ func saveLoginLogs(c *gin.Context, err error) {
_ = logService.CreateLoginLog(logs) _ = 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 { func loadEntranceFromRequest(c *gin.Context) string {
entranceItem := c.Request.Header.Get("EntranceCode") entranceItem := c.Request.Header.Get("EntranceCode")
var entrance []byte var entrance []byte
+32
View File
@@ -15,6 +15,7 @@ import (
"github.com/1Panel-dev/1Panel/core/buserr" "github.com/1Panel-dev/1Panel/core/buserr"
"github.com/1Panel-dev/1Panel/core/constant" "github.com/1Panel-dev/1Panel/core/constant"
"github.com/1Panel-dev/1Panel/core/global" "github.com/1Panel-dev/1Panel/core/global"
"github.com/1Panel-dev/1Panel/core/utils/common"
"github.com/1Panel-dev/1Panel/core/utils/mfa" "github.com/1Panel-dev/1Panel/core/utils/mfa"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
@@ -98,6 +99,14 @@ func (b *BaseApi) UpdateSetting(c *gin.Context) {
return 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 { if err := settingService.Update(req.Key, req.Value); err != nil {
helper.InternalServer(c, err) helper.InternalServer(c, err)
@@ -666,3 +675,26 @@ func checkEntrancePattern(val string) bool {
} }
return true 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
}
+5 -1
View File
@@ -15,6 +15,7 @@ type SettingInfo struct {
Ipv6 string `json:"ipv6"` Ipv6 string `json:"ipv6"`
BindAddress string `json:"bindAddress"` BindAddress string `json:"bindAddress"`
PanelName string `json:"panelName"` PanelName string `json:"panelName"`
Edition string `json:"edition"`
Theme string `json:"theme"` Theme string `json:"theme"`
MenuTabs string `json:"menuTabs"` MenuTabs string `json:"menuTabs"`
Language string `json:"language"` Language string `json:"language"`
@@ -23,6 +24,7 @@ type SettingInfo struct {
SSL string `json:"ssl"` SSL string `json:"ssl"`
SSLType string `json:"sslType"` SSLType string `json:"sslType"`
BindDomain string `json:"bindDomain"` BindDomain string `json:"bindDomain"`
PasskeyTrustedProxies string `json:"passkeyTrustedProxies"`
AllowIPs string `json:"allowIPs"` AllowIPs string `json:"allowIPs"`
SecurityEntrance string `json:"securityEntrance"` SecurityEntrance string `json:"securityEntrance"`
DashboardMemoVisible string `json:"dashboardMemoVisible"` DashboardMemoVisible string `json:"dashboardMemoVisible"`
@@ -31,7 +33,6 @@ type SettingInfo struct {
ExpirationTime string `json:"expirationTime"` ExpirationTime string `json:"expirationTime"`
ComplexityVerification string `json:"complexityVerification"` ComplexityVerification string `json:"complexityVerification"`
MFAStatus string `json:"mfaStatus"` MFAStatus string `json:"mfaStatus"`
MFASecret string `json:"mfaSecret"`
MFAInterval string `json:"mfaInterval"` MFAInterval string `json:"mfaInterval"`
AppStoreVersion string `json:"appStoreVersion"` AppStoreVersion string `json:"appStoreVersion"`
@@ -226,6 +227,9 @@ type TerminalInfo struct {
LineHeight string `json:"lineHeight"` LineHeight string `json:"lineHeight"`
LetterSpacing string `json:"letterSpacing"` LetterSpacing string `json:"letterSpacing"`
FontSize string `json:"fontSize"` FontSize string `json:"fontSize"`
FontFamily string `json:"fontFamily"`
BackgroundColor string `json:"backgroundColor"`
ForegroundColor string `json:"foregroundColor"`
CursorBlink string `json:"cursorBlink"` CursorBlink string `json:"cursorBlink"`
CursorStyle string `json:"cursorStyle"` CursorStyle string `json:"cursorStyle"`
Scrollback string `json:"scrollback"` Scrollback string `json:"scrollback"`
+44 -6
View File
@@ -2,14 +2,22 @@ package repo
import ( import (
"errors" "errors"
"time"
"github.com/1Panel-dev/1Panel/core/app/model" "github.com/1Panel-dev/1Panel/core/app/model"
"github.com/1Panel-dev/1Panel/core/global" "github.com/1Panel-dev/1Panel/core/global"
"github.com/1Panel-dev/1Panel/core/init/migration/helper" "github.com/1Panel-dev/1Panel/core/init/migration/helper"
"github.com/patrickmn/go-cache"
"gorm.io/gorm" "gorm.io/gorm"
) )
type SettingRepo struct{} type SettingRepo struct{}
var (
settingCache = cache.New(5*time.Minute, 10*time.Minute)
settingTTL = 5 * time.Minute
)
type ISettingRepo interface { type ISettingRepo interface {
List(opts ...global.DBOption) ([]model.Setting, error) List(opts ...global.DBOption) ([]model.Setting, error)
Get(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, Key: key,
Value: value, 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) { 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 { for _, opt := range opts {
db = opt(db) db = opt(db)
} }
err := db.First(&settings).Error err := db.First(&settings).Error
if err == nil && settings.Key != "" {
settingCache.Set(settings.Key, settings.Value, settingTTL)
}
return settings, err return settings, err
} }
func (u *SettingRepo) GetValueByKey(key string) (string, error) { func (u *SettingRepo) GetValueByKey(key string) (string, error) {
if val, found := settingCache.Get(key); found {
return val.(string), nil
}
var setting model.Setting var setting model.Setting
if err := global.DB.Model(&model.Setting{}).Where("key = ?", key).First(&setting).Error; err != nil { if err := global.DB.Model(&model.Setting{}).Where("key = ?", key).First(&setting).Error; err != nil {
return "", err return "", err
} }
settingCache.Set(key, setting.Value, settingTTL)
return setting.Value, nil return setting.Value, nil
} }
func (u *SettingRepo) Update(key, value string) error { 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 { 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) result := global.DB.Where("key = ?", key).First(&setting)
if result.Error != nil { if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) { 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 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 { func (u *SettingRepo) DefaultMenu() error {
return global.DB.Model(&model.Setting{}). menus := helper.LoadMenus()
if err := global.DB.Model(&model.Setting{}).
Where("key = ?", "HideMenu"). 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
View File
@@ -5,6 +5,7 @@ import (
"crypto/rand" "crypto/rand"
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"net" "net"
"strconv" "strconv"
@@ -22,6 +23,7 @@ import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/go-webauthn/webauthn/protocol" "github.com/go-webauthn/webauthn/protocol"
"github.com/go-webauthn/webauthn/webauthn" "github.com/go-webauthn/webauthn/webauthn"
"gorm.io/gorm"
) )
type AuthService struct{} 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) success := mfa.ValidCode(info.Code, mfaInterval.Value, mfaSecret.Value)
if !success { if !success {
return nil, "ErrAuth", nil return nil, "ErrMFA", nil
} }
res, err := u.generateSession(c, info.Name) res, err := u.generateSession(c, info.Name)
if err != nil { if err != nil {
@@ -454,13 +456,6 @@ func (u *AuthService) PasskeyDelete(id string) error {
} }
func (u *AuthService) passkeyEnabled(c *gin.Context) (bool, 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 return strings.EqualFold(passkeyRequestScheme(c), "https"), nil
} }
@@ -679,9 +674,114 @@ func passkeyRequestScheme(c *gin.Context) string {
if c.Request.TLS != nil { if c.Request.TLS != nil {
return "https" 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" 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 { func stripHostPort(hostport string) string {
if hostport == "" { if hostport == "" {
return hostport return hostport
+16 -5
View File
@@ -1,9 +1,10 @@
package service package service
import ( import (
"crypto/rand"
"encoding/json" "encoding/json"
"fmt" "fmt"
mathRand "math/rand" "math/big"
"net/http" "net/http"
"os" "os"
"path" "path"
@@ -172,7 +173,17 @@ func StartSync() {
service := NewIScriptService() service := NewIScriptService()
scriptSync, _ := repo.NewISettingRepo().GetValueByKey("ScriptSync") scriptSync, _ := repo.NewISettingRepo().GetValueByKey("ScriptSync")
if !global.CONF.Base.IsOffLine && scriptSync == constant.StatusEnable { 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 { if err != nil {
global.LOG.Errorf("[core] can not add script sync corn job: %s", err.Error()) 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) { 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) _, versionRes, err := req_helper.HandleRequestWithProxy(versionUrl, http.MethodGet, constant.TimeOut20s)
if err != nil { if err != nil {
return fmt.Errorf("load scripts version from remote failed, err: %v", err) 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 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) _, dataRes, err := req_helper.HandleRequestWithProxy(dataUrl, http.MethodGet, constant.TimeOut20s)
syncTask.LogWithStatus(i18n.GetMsgByKey("DownloadData"), err) syncTask.LogWithStatus(i18n.GetMsgByKey("DownloadData"), err)
if err != nil { if err != nil {
@@ -232,7 +243,7 @@ func (u *ScriptService) Sync(req dto.OperateByTaskID) error {
if _, err := os.Stat(tmpDir); err != nil { if _, err := os.Stat(tmpDir); err != nil {
_ = os.MkdirAll(tmpDir, 0755) _ = 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") err = files.DownloadFileWithProxyStream(scriptsUrl, tmpDir+"/scripts.tar.gz")
syncTask.LogWithStatus(i18n.GetMsgByKey("DownloadPackage"), err) syncTask.LogWithStatus(i18n.GetMsgByKey("DownloadPackage"), err)
if err != nil { if err != nil {
+28 -28
View File
@@ -61,8 +61,6 @@ type ISettingService interface {
UpdateSystemSSL() error UpdateSystemSSL() error
GenerateRSAKey() error GenerateRSAKey() error
GetLoginSetting() (*dto.SystemSetting, error)
UpdateAppstoreConfig(req dto.AppstoreUpdate) error UpdateAppstoreConfig(req dto.AppstoreUpdate) error
GetAppstoreConfig() (*dto.AppstoreConfig, error) GetAppstoreConfig() (*dto.AppstoreConfig, error)
DefaultMenu() error DefaultMenu() error
@@ -92,6 +90,10 @@ func (u *SettingService) GetSettingInfo() (*dto.SettingInfo, error) {
if err := json.Unmarshal(arr, &info); err != nil { if err := json.Unmarshal(arr, &info); err != nil {
return nil, err return nil, err
} }
if info.Edition == "" {
info.Edition = "cn"
_ = settingRepo.UpdateOrCreate("Edition", info.Edition)
}
if info.ProxyPasswdKeep != constant.StatusEnable { if info.ProxyPasswdKeep != constant.StatusEnable {
info.ProxyPasswd = "" info.ProxyPasswd = ""
} else { } else {
@@ -168,6 +170,11 @@ func (u *SettingService) Update(key, value string) error {
} else { } else {
global.Cron.Remove(global.ScriptSyncJobID) 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 return nil
@@ -283,9 +290,6 @@ func (u *SettingService) UpdateSSL(c *gin.Context, req dto.SSLUpdate) error {
if err := settingRepo.Update("SSLType", "self"); err != nil { if err := settingRepo.Update("SSLType", "self"); err != nil {
return err return err
} }
if err := u.clearPasskeySettings(); err != nil {
return err
}
_ = os.Remove(path.Join(secretDir, "server.crt")) _ = os.Remove(path.Join(secretDir, "server.crt"))
_ = os.Remove(path.Join(secretDir, "server.key")) _ = os.Remove(path.Join(secretDir, "server.key"))
go func() { go func() {
@@ -391,9 +395,6 @@ func (u *SettingService) UpdateSSL(c *gin.Context, req dto.SSLUpdate) error {
if err := settingRepo.Update("SSL", req.SSL); err != nil { if err := settingRepo.Update("SSL", req.SSL); err != nil {
return err return err
} }
if err := u.clearPasskeySettings(); err != nil {
return err
}
return u.UpdateSystemSSL() return u.UpdateSystemSSL()
} }
@@ -500,25 +501,37 @@ func (u *SettingService) GetTerminalInfo() (*dto.TerminalInfo, error) {
return &info, err return &info, err
} }
func (u *SettingService) UpdateTerminal(req dto.TerminalInfo) error { 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 return err
} }
if err := settingRepo.Update("LetterSpacing", req.LetterSpacing); err != nil { if err := settingRepo.UpdateOrCreate("LetterSpacing", req.LetterSpacing); err != nil {
return err return err
} }
if err := settingRepo.Update("FontSize", req.FontSize); err != nil { if err := settingRepo.UpdateOrCreate("FontSize", req.FontSize); err != nil {
return err return err
} }
if err := settingRepo.Update("CursorBlink", req.CursorBlink); err != nil { if err := settingRepo.UpdateOrCreate("FontFamily", req.FontFamily); err != nil {
return err return err
} }
if err := settingRepo.Update("CursorStyle", req.CursorStyle); err != nil { if err := settingRepo.UpdateOrCreate("CursorBlink", req.CursorBlink); err != nil {
return err return err
} }
if err := settingRepo.Update("Scrollback", req.Scrollback); err != nil { if err := settingRepo.UpdateOrCreate("BackgroundColor", req.BackgroundColor); err != nil {
return err 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 err
} }
return nil return nil
@@ -673,19 +686,6 @@ func (u *SettingService) GenerateRSAKey() error {
return nil 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 { func (u *SettingService) UpdateAppstoreConfig(req dto.AppstoreUpdate) error {
return settingRepo.UpdateOrCreate(req.Scope, req.Status) return settingRepo.UpdateOrCreate(req.Scope, req.Status)
} }
+5 -5
View File
@@ -117,7 +117,7 @@ func (u *UpgradeService) SearchUpgrade() (*dto.UpgradeInfo, error) {
if strings.HasPrefix(upgrade.TestVersion, upgrade.LatestVersion+"-beta") { if strings.HasPrefix(upgrade.TestVersion, upgrade.LatestVersion+"-beta") {
upgrade.TestVersion = "" 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 { if err != nil {
return nil, fmt.Errorf("load releases-notes of version %s failed, err: %v", itemVersion, err) 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") { if strings.Contains(req.Version, "beta") {
mode = "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 { if err != nil {
return "", fmt.Errorf("load releases-notes of version %s failed, err: %v", req.Version, err) 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") { if strings.Contains(req.Version, "beta") {
mode = "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) fileName := fmt.Sprintf("1panel-%s-%s-%s.tar.gz", req.Version, "linux", itemArch)
_ = settingRepo.Update("SystemStatus", "Upgrading") _ = settingRepo.Update("SystemStatus", "Upgrading")
go func() { go func() {
@@ -442,9 +442,9 @@ func (u *UpgradeService) loadVersionByMode(developer, currentVersion string) (st
} }
func (u *UpgradeService) loadVersion(isLatest bool, currentVersion, mode string) string { 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 { 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) _, latestVersionRes, err := req_helper.HandleRequestWithProxy(path, http.MethodGet, constant.TimeOut20s)
if err != nil { if err != nil {
+12 -3
View File
@@ -62,7 +62,10 @@ var resetSSLCmd = &cobra.Command{
return err 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{ var resetEntranceCmd = &cobra.Command{
@@ -94,7 +97,10 @@ var resetBindIpsCmd = &cobra.Command{
return err return err
} }
return setSettingByKey(db, "AllowIPs", "") if err := setSettingByKey(db, "AllowIPs", ""); err != nil {
return err
}
return nil
}, },
} }
var resetDomainCmd = &cobra.Command{ var resetDomainCmd = &cobra.Command{
@@ -110,7 +116,10 @@ var resetDomainCmd = &cobra.Command{
return err return err
} }
return setSettingByKey(db, "BindDomain", "") if err := setSettingByKey(db, "BindDomain", ""); err != nil {
return err
}
return nil
}, },
} }
+45
View File
@@ -92,9 +92,16 @@ var restoreCmd = &cobra.Command{
fmt.Println(i18n.GetMsgByKeyForCmd("RestoreStep4")) fmt.Println(i18n.GetMsgByKeyForCmd("RestoreStep4"))
if _, err := os.Stat(path.Join(tmpPath, "db")); err == nil { if _, err := os.Stat(path.Join(tmpPath, "db")); err == nil {
dbPath := path.Join(baseDir, "1panel") 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 { if err := files.CopyItem(true, true, path.Join(tmpPath, "db"), dbPath); err != nil {
global.LOG.Errorf("rollback 1panel db failed, err: %v", err) 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")) fmt.Println(i18n.GetMsgByKeyForCmd("RestoreStep5"))
@@ -140,3 +147,41 @@ func loadRollbackVersion(upgradeDir string) string {
} }
return info 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
}
+1 -1
View File
@@ -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 return false
} }
if (numCount == 0 && alphaCount == 0) || (alphaCount == 0 && specialCount == 0) || (numCount == 0 && specialCount == 0) { if (numCount == 0 && alphaCount == 0) || (alphaCount == 0 && specialCount == 0) || (numCount == 0 && specialCount == 0) {
-6
View File
@@ -2,7 +2,6 @@ base:
install_dir: /opt install_dir: /opt
mode: dev mode: dev
is_demo: false is_demo: false
is_intl: false
is_offline: false is_offline: false
is_fxplay: false is_fxplay: false
port: 9999 port: 9999
@@ -10,11 +9,6 @@ base:
password: admin123 password: admin123
version: v2.0.0 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: log:
level: debug level: debug
time_zone: Asia/Shanghai time_zone: Asia/Shanghai
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+64 -22
View File
@@ -3008,27 +3008,10 @@
"formatZH": "php 版本变更 [domain]", "formatZH": "php 版本变更 [domain]",
"formatEN": "php version update [domain]" "formatEN": "php version update [domain]"
}, },
"/websites/proxies/file": { "/websites/proxies/delete": {
"bodyKeys": [ "bodyKeys": [
"websiteID" "id",
], "name"
"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]"
},
"/websites/proxies/update": {
"bodyKeys": [
"id"
], ],
"paramKeys": [], "paramKeys": [],
"beforeFunctions": [ "beforeFunctions": [
@@ -3041,8 +3024,67 @@
"output_value": "domain" "output_value": "domain"
} }
], ],
"formatZH": "修改网站 [domain] 反向代理配置 ", "formatZH": "删除网站 [domain] 反向代理配置 [name] ",
"formatEN": "Update domain [domain] proxy config" "formatEN": "Delete domain [domain] proxy config [name]"
},
"/websites/proxies/file": {
"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]"
},
"/websites/proxies/status": {
"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]"
},
"/websites/proxies/update": {
"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]"
}, },
"/websites/proxy/clear": { "/websites/proxy/clear": {
"bodyKeys": [], "bodyKeys": [],
-2
View File
@@ -4,8 +4,6 @@ import (
"fmt" "fmt"
"os" "os"
_ "net/http/pprof"
"github.com/1Panel-dev/1Panel/core/cmd/server/cmd" "github.com/1Panel-dev/1Panel/core/cmd/server/cmd"
_ "github.com/1Panel-dev/1Panel/core/cmd/server/docs" _ "github.com/1Panel-dev/1Panel/core/cmd/server/docs"
) )
+1
View File
@@ -46,6 +46,7 @@ const (
SyncAlertSetting = "SyncAlertSetting" SyncAlertSetting = "SyncAlertSetting"
SyncCustomApp = "SyncCustomApp" SyncCustomApp = "SyncCustomApp"
SyncLanguage = "SyncLanguage" SyncLanguage = "SyncLanguage"
SyncEdition = "SyncEdition"
SyncSystemProxyWithRestartDocker = "SyncSystemProxyWithRestartDocker" SyncSystemProxyWithRestartDocker = "SyncSystemProxyWithRestartDocker"
) )
+1 -7
View File
@@ -3,7 +3,6 @@ package global
type ServerConfig struct { type ServerConfig struct {
Base Base `mapstructure:"base"` Base Base `mapstructure:"base"`
Conn Conn `mapstructure:"conn"` Conn Conn `mapstructure:"conn"`
RemoteURL RemoteURL `mapstructure:"remote_url"`
LogConfig LogConfig `mapstructure:"log"` LogConfig LogConfig `mapstructure:"log"`
} }
@@ -13,9 +12,9 @@ type Base struct {
Password string `mapstructure:"password"` Password string `mapstructure:"password"`
Language string `mapstructure:"language"` Language string `mapstructure:"language"`
IsDemo bool `mapstructure:"is_demo"` IsDemo bool `mapstructure:"is_demo"`
IsIntl bool `mapstructure:"is_intl"`
IsOffLine bool `mapstructure:"is_offline"` IsOffLine bool `mapstructure:"is_offline"`
IsFxplay bool `mapstructure:"is_fxplay"` IsFxplay bool `mapstructure:"is_fxplay"`
Edition string `mapstructure:"edition"`
Version string `mapstructure:"version"` Version string `mapstructure:"version"`
InstallDir string `mapstructure:"install_dir"` InstallDir string `mapstructure:"install_dir"`
ChangeUserInfo string `mapstructure:"change_user_info"` ChangeUserInfo string `mapstructure:"change_user_info"`
@@ -37,11 +36,6 @@ type ApiInterface struct {
ApiKeyValidityTime string `mapstructure:"api_key_validity_time"` ApiKeyValidityTime string `mapstructure:"api_key_validity_time"`
} }
type RemoteURL struct {
RepoUrl string `mapstructure:"repo_url"`
ResourceURL string `mapstructure:"resource_url"`
}
type LogConfig struct { type LogConfig struct {
Level string `mapstructure:"level"` Level string `mapstructure:"level"`
TimeZone string `mapstructure:"timeZone"` TimeZone string `mapstructure:"timeZone"`
+19
View File
@@ -34,3 +34,22 @@ var (
) )
type DBOption func(*gorm.DB) *gorm.DB type DBOption func(*gorm.DB) *gorm.DB
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"
}
+72 -70
View File
@@ -6,16 +6,16 @@ ErrRecordExist: "Record already exists"
ErrRecordNotFound: "Record not found" ErrRecordNotFound: "Record not found"
ErrStructTransform: "Type conversion failed: {{ .detail }}" ErrStructTransform: "Type conversion failed: {{ .detail }}"
ErrNotLogin: "User not logged in: {{ .detail }}" ErrNotLogin: "User not logged in: {{ .detail }}"
ErrSessionDataNotFound: "Current session has expired!" ErrSessionDataNotFound: "Session expired"
ErrSessionDataFormat: "Current session data format is abnormal!" ErrSessionDataFormat: "Invalid session data format"
ErrPasswordExpired: "Current password has expired: {{ .detail }}" ErrPasswordExpired: "Password expired: {{ .detail }}"
ErrNotSupportType: "The current type is not supported: {{ .detail }}" ErrNotSupportType: "Unsupported type: {{ .detail }}"
ErrProxy: "Request error, please check the status of this node: {{ .detail }}" ErrProxy: "Request failed; check this node status: {{ .detail }}"
ErrApiConfigStatusInvalid: "API access is prohibited: {{ .detail }}" ErrApiConfigStatusInvalid: "API access disabled: {{ .detail }}"
ErrApiConfigKeyInvalid: "API key error: {{ .detail }}" ErrApiConfigKeyInvalid: "Invalid API key: {{ .detail }}"
ErrApiConfigIPInvalid: "The API request IP is not on the whitelist: {{ .detail }}" ErrApiConfigIPInvalid: "The API request IP is not on the whitelist: {{ .detail }}"
ErrApiConfigDisable: "This interface prohibits API calls: {{ .detail }}" ErrApiConfigDisable: "This interface prohibits API calls: {{ .detail }}"
ErrApiConfigKeyTimeInvalid: "API timestamp error: {{ .detail }}" ErrApiConfigKeyTimeInvalid: "Invalid API timestamp: {{ .detail }}"
ErrPasskeyDisabled: "Passkey requires HTTPS to be enabled" ErrPasskeyDisabled: "Passkey requires HTTPS to be enabled"
ErrPasskeyNotConfigured: "No passkey configured" ErrPasskeyNotConfigured: "No passkey configured"
ErrPasskeyLimit: "Passkey limit reached (max 5)" ErrPasskeyLimit: "Passkey limit reached (max 5)"
@@ -24,18 +24,18 @@ ErrPasskeyDuplicate: "Passkey already exists"
ErrPasskeyVerify: "Passkey verification failed" ErrPasskeyVerify: "Passkey verification failed"
# request # request
ErrNoSuchHost: "Unable to find the requested server {{ .err }}" ErrNoSuchHost: "Host resolution failed: {{ .err }}"
ErrHttpReqNotFound: "Unable to find the requested resource {{ .err }}" ErrHttpReqNotFound: "Requested resource not found: {{ .err }}"
ErrHttpReqFailed: "Request failed {{ .err }}" ErrHttpReqFailed: "Request failed {{ .err }}"
ErrHttpReqTimeOut: "Request timed out {{ .err }}" ErrHttpReqTimeOut: "Request timed out {{ .err }}"
ErrCreateHttpClient: "Failed to create request {{ .err }}" ErrCreateHttpClient: "Failed to create request {{ .err }}"
ErrProxySetting: "Proxy server information unavailable {{ .err }}, please check and try again!" ErrProxySetting: "Proxy server information unavailable {{ .err }}, check and try again!"
ErrEntranceFormat: "Security entrance {{ .name }} is not currently supported. Please check and try again!" ErrEntranceFormat: "Security entry {{ .name }} is not supported. Check and try again."
# common # common
ErrDemoEnvironment: "Demo server, this operation is prohibited!" ErrDemoEnvironment: "Demo server, this operation is prohibited!"
ErrCmdTimeout: "Command execution timeout!" ErrCmdTimeout: "Command execution timeout!"
ErrEntrance: "Security entrance information error, please check and try again!" ErrEntrance: "Security entrance information error, check and try again!"
ErrGroupIsDefault: "Default group, unable to delete" ErrGroupIsDefault: "Default group, unable to delete"
ErrGroupIsInUse: "The group is in use and cannot be deleted." ErrGroupIsInUse: "The group is in use and cannot be deleted."
ErrLocalDelete: "Cannot delete the local node!" ErrLocalDelete: "Cannot delete the local node!"
@@ -56,49 +56,50 @@ AppInstallCheck: 'Check application installation environment'
ErrBackupInUsed: "This backup account is used in scheduled tasks and cannot be deleted" ErrBackupInUsed: "This backup account is used in scheduled tasks and cannot be deleted"
ErrBackupCheck: "Backup account connection test failed {{ .err }}" ErrBackupCheck: "Backup account connection test failed {{ .err }}"
ErrBackupLocal: "Local server backup account does not support this operation!" ErrBackupLocal: "Local server backup account does not support this operation!"
ErrBackupPublic: "Detected that this backup account is not public, please check and try again!" ErrBackupPublic: "Detected that this backup account is not public, check and try again!"
ErrOSSConn: "Unable to get the latest version, please check the server's external network connectivity." ErrOSSConn: "Unable to get the latest version. Check server internet connectivity."
#license #license
LicenseCheck: 'Check if the license is available' LicenseCheck: 'Check if the license is available'
ErrLicenseInUsed: 'The license is already bound. Please check and try again!' ErrLicenseInUsed: 'The license is already bound. Check and try again!'
ErrLicenseExpired: 'The license has expired. Please check and try again!' ErrLicenseExpired: 'The license has expired. Check and try again!'
ErrLicense: "License format error, please check and retry!" ErrLicense: "License format error, check and retry!"
ErrLicenseCheck: "License validation failed, please check and retry!" ErrLicenseCheck: "License validation failed, check and retry!"
ErrXpackVersion: "License validation failed, this license is version-limited, cannot import, please check and retry!" ErrXpackVersion: "License validation failed, this license is version-limited, cannot import, check and retry!"
ErrLicenseSave: "Failed to save license information, error {{ .err }}, please retry!" ErrLicenseSave: "Failed to save license information, error {{ .err }}, retry!"
ErrLicenseSync: "License synchronization failed, no license info detected in database!" ErrLicenseSync: "License synchronization failed, no license info detected in database!"
ErrLicenseExist: "This license record already exists. You can directly go to the license page for node binding." ErrLicenseExist: "This license record already exists. You can directly go to the license page for node binding."
ErrXpackNotFound: "This section is for professional edition, please import the license in Panel Settings - License" ErrXpackNotFound: "This section requires Professional Edition. Import a license in Panel Settings - License"
ErrXpackExceptional: "This section is for professional edition, please sync license status in Panel Settings - License" ErrXpackExceptional: "This section requires Professional Edition. Sync license status in Panel Settings - License"
ErrXpackLost: "License has reached the maximum retry count, please go to the [Panel Settings] [License] page and click the sync button manually to ensure the professional features work correctly" ErrXpackLost: "License reached max retry count. Go to [Panel Settings] [License] and run manual sync"
ErrDeviceLost: "Required files for license verification are missing, please check and try again!" ErrDeviceLost: "Required files for license verification are missing, check and try again!"
ErrDeviceErr: "The current environment does not match the license import environment. Please edit the license and re-import!" ErrDeviceErr: "Current environment does not match the license import environment. Edit the license and re-import."
ErrXpackTimeout: "Request timeout, network connection might be unstable, please try again later!" ErrXpackTimeout: "Request timeout, network connection might be unstable, try again later!"
ErrUnbindMaster: "Detected nodes in node management, unable to unbind the current license, please remove nodes first and retry!" ErrUnbindMaster: "Nodes exist in node management. Remove nodes first, then unbind the current license."
ErrFreeNodeLimit: "Community version node limit reached, please go to www.lxware.cn/1panel to purchase and retry!" ErrFreeNodeLimit: "Community edition node limit reached. Go to www.lxware.cn/1panel to purchase and retry."
ErrNodeBound: "This license is bound to another node, please check and retry!" ErrNodeBound: "This license is bound to another node, check and retry!"
ErrNodeBoundDelete: "This license is bound and does not support delete operations. Please check and try again!" ErrNodeBoundDelete: "This license is bound and does not support delete operations. Check and try again!"
ErrNodeBoundLimit: "The current free node has reached its limit, please check and try again!" ErrNodeBoundLimit: "The current free node has reached its limit, check and try again!"
ErrLicenseFree: "Free nodes can only be used when the license is properly bound to a node. Please verify and try again!" ErrLicenseFree: "Free nodes are available only when the license is correctly bound to a node. Verify and retry."
ErrLicenseUnbind: "Community Edition nodes detected for this license. Please unbind in [Panel Settings - License] and try again!" ErrLicenseUnbind: "Community Edition nodes detected for this license. Unbind in [Panel Settings - License] and retry."
ErrNoSuchNode: "Node information not found, please check and retry!" ErrNoSuchNode: "Node information not found, check and retry!"
ErrNodeUnbind: "This node is not within the license binding range, please check and retry!" ErrNodeUnbind: "This node is not within the license binding range, check and retry!"
ErrNodeBind: "This node is already bound to a license, please check and retry!" ErrNodeBind: "This node is already bound to a license, check and retry!"
ErrNodeLocalRollback: "The primary node does not support direct rollback. Please manually execute the '1pctl restore' command to rollback!" ErrNodeLocalRollback: "The primary node does not support direct rollback. Manually execute the '1pctl restore' command to rollback!"
ErrIntlLicense: "The current version does not support importing international licenses yet. Stay tuned!"
InvalidRequestBodyType: "Invalid request body format, please check and ensure the content meets the required format before retrying!" InvalidRequestBodyType: "Invalid request body format. Ensure content matches the required format and retry."
InvalidLicenseCodeType: "Invalid license code format provided, please check and try again!" InvalidLicenseCodeType: "Invalid license code format provided, check and try again!"
LicenseNotFoundType: "License not found, no matching record exists in the system for the provided license. Please check and try again!" LicenseNotFoundType: "License not found, no matching record exists in the system for the provided license. Check and try again!"
LicenseRevokedType: "The requested license has been revoked and is no longer usable. Please check and try again!" LicenseRevokedType: "The requested license has been revoked and is no longer usable. Check and try again!"
LicenseExpiredType: "The license has expired. Please renew it or re-import the license in the Panel Settings - License section before retrying!" LicenseExpiredType: "License expired. Renew it or re-import it in Panel Settings - License before retrying."
LicenseProductMismatchType: "The license does not match the requested product or service!" LicenseProductMismatchType: "The license does not match the requested product or service!"
InvalidAssigneeType: "Invalid target user or device information for license assignment. Please check and try again!" InvalidAssigneeType: "Invalid target user or device information for license assignment. Check and try again!"
LicenseUsageNotFoundType: "No usage records found. This license has not been activated or used yet. Please check and try again!" LicenseUsageNotFoundType: "No usage records found. This license has not been activated or used yet. Check and try again!"
LicenseUsageLimitExceededType: "This license is already bound to another node. Please check and try again!" LicenseUsageLimitExceededType: "This license is already bound to another node. Check and try again!"
# alert # alert
ErrAlertSync: "Alert information sync error, please check and retry!" ErrAlertSync: "Alert information sync error, check and retry!"
# task # task
TaskStart: "{{ .name }} task started [START]" TaskStart: "{{ .name }} task started [START]"
@@ -106,19 +107,19 @@ TaskEnd: "{{ .name }} task ended [COMPLETED]"
TaskFailed: "{{ .name }} task failed" TaskFailed: "{{ .name }} task failed"
TaskTimeout: "{{ .name }} timed out" TaskTimeout: "{{ .name }} timed out"
TaskSuccess: "{{ .name }} task succeeded" TaskSuccess: "{{ .name }} task succeeded"
TaskRetry: "Starting retry {{ .name }}" TaskRetry: "Retry {{ .name }}"
SubTaskSuccess: "{{ .name }} succeeded" SubTaskSuccess: "{{ .name }} succeeded"
SubTaskFailed: "{{ .name }} failed: {{ .err }}" SubTaskFailed: "{{ .name }} failed: {{ .err }}"
TaskInstall: "Install" TaskInstall: "Install"
TaskUpgrade: "Upgrade" TaskUpgrade: "Upgrade"
TaskSync: 'Synchronize' TaskSync: 'Sync'
TaskSyncForNode: "Sync Node Data" TaskSyncForNode: "Sync node data"
TaskBackup: "Backup" TaskBackup: "Backup"
SuccessStatus: "{{ .name }} succeeded" SuccessStatus: "{{ .name }} succeeded"
FailedStatus: "{{ .name }} failed {{ .err }}" FailedStatus: "{{ .name }} failed {{ .err }}"
Start: "Start" Start: "Start"
SubTask: "Subtask" SubTask: "Subtask"
Skip: "Skip errors and continue..." Skip: "Ignore errors and continue"
PushAppInstallTaskToNode: "Push app installation task to node [{{ .name }}]" PushAppInstallTaskToNode: "Push app installation task to node [{{ .name }}]"
TaskPush: "Push" TaskPush: "Push"
AppInstallTask: "App installation task" AppInstallTask: "App installation task"
@@ -128,7 +129,7 @@ Success: "Success"
#script #script
ScriptLibrary: "Script Library" ScriptLibrary: "Script Library"
RemoteScriptLibrary: "Remote Script Library" RemoteScriptLibrary: "Remote Script Library"
ScriptSyncSkip: "Current script library is already the latest version!" ScriptSyncSkip: "Script library is already up to date"
DownloadData: "Downloading script library file data.yaml" DownloadData: "Downloading script library file data.yaml"
DownloadPackage: "Downloading script library package" DownloadPackage: "Downloading script library package"
AnalyticCompletion: "Analysis completed, now syncing to database..." AnalyticCompletion: "Analysis completed, now syncing to database..."
@@ -140,13 +141,14 @@ SyncPackageData: "Package sync data"
SyncPackageEncrypt: "Data package encryption" SyncPackageEncrypt: "Data package encryption"
SyncRequest: "Request node sync API" SyncRequest: "Request node sync API"
SyncFailedRetry: "Node data sync timeout (attempt {{ .index }}), retrying..." SyncFailedRetry: "Node data sync timeout (attempt {{ .index }}), retrying..."
SyncFailed: "Sync failed, please manually sync in the node list!" SyncFailed: "Sync failed, manually sync in the node list!"
SyncSystemProxy: "System Proxy Settings" SyncSystemProxy: "System Proxy Settings"
SyncScripts: "Script Library" SyncScripts: "Script Library"
SyncBackupAccounts: "Backup Accounts" SyncBackupAccounts: "Backup Accounts"
SyncAlertSetting: "Alert Settings" SyncAlertSetting: "Alert Settings"
SyncCustomApp: "Custom App" SyncCustomApp: "Custom App"
SyncLanguage: "System Language" SyncLanguage: "System Language"
SyncEdition: "Region"
#upgrade node #upgrade node
NodeUpgrade: "Upgrade node {{ .name }}" NodeUpgrade: "Upgrade node {{ .name }}"
@@ -174,7 +176,7 @@ ConnInfoNotMatch: "Connection info mismatch"
MakeAgentPackage: "Generate node installation package" MakeAgentPackage: "Generate node installation package"
SendAgent: "Distribute node installation package" SendAgent: "Distribute node installation package"
StartService: "Start service" StartService: "Start service"
NoBackupNode: "The backup node is currently empty. Please select a backup node to save and try again!" NoBackupNode: "Backup node is empty. Select one and save first"
#cmd #cmd
AppVersion: "App version" AppVersion: "App version"
@@ -188,7 +190,7 @@ AppMissVersion: "App version missing, use -v to specify"
AppVersionExist: "Version already exists!" AppVersionExist: "Version already exists!"
AppCreateSuccessful: "Creation successful!" AppCreateSuccessful: "Creation successful!"
AppWriteErr: "File {{ .name }} write failed {{ .err }}" AppWriteErr: "File {{ .name }} write failed {{ .err }}"
SudoHelper: "Please use {{ .cmd }} or switch to root user" SudoHelper: "Use {{ .cmd }} or switch to root user"
ListenIPCommands: "Switch listening ip" ListenIPCommands: "Switch listening ip"
ListenIPv4: "Listen on IPv4" ListenIPv4: "Listen on IPv4"
ListenIPv6: "Listen on IPv6" ListenIPv6: "Listen on IPv6"
@@ -201,13 +203,13 @@ ResetIPs: "Cancel 1Panel authorized ip restrictions"
ResetDomain: "Cancel 1Panel domain binding" ResetDomain: "Cancel 1Panel domain binding"
ResetPasskey: "Clear 1Panel passkeys" ResetPasskey: "Clear 1Panel passkeys"
RestoreCommands: "Rollback 1Panel service and data" RestoreCommands: "Rollback 1Panel service and data"
RestoreNoSuchFile: "No files available for rollback" RestoreNoSuchFile: "No rollback files found"
RestoreStep1: "(1/5) Starting rollback of 1Panel service and data from {{ .name }} directory..." RestoreStep1: "(1/5) Starting rollback of 1Panel service and data from {{ .name }} directory..."
RestoreStep2: "(2/5) 1Panel binary rollback successful" RestoreStep2: "(2/5) 1Panel binary rollback successful"
RestoreStep3: "(3/5) 1Panel script rollback successful" RestoreStep3: "(3/5) 1Panel script rollback successful"
RestoreStep4: "(4/5) 1Panel service rollback successful" RestoreStep4: "(4/5) 1Panel service rollback successful"
RestoreStep5: "(5/5) 1Panel data rollback successful" RestoreStep5: "(5/5) 1Panel data rollback successful"
RestoreSuccessful: "Rollback successful! Rolled back to {{ .version }}, restarting service, please wait..." RestoreSuccessful: "Rollback succeeded. Reverted to {{ .version }}, restarting service..."
UpdateCommands: "Update panel info" UpdateCommands: "Update panel info"
UpdateUser: "Update panel user" UpdateUser: "Update panel user"
UpdatePassword: "Update panel password" UpdatePassword: "Update panel password"
@@ -221,19 +223,19 @@ UpdateUserResult: "Panel user: {{ .name }}"
UpdatePasswordRead: "Error: Failed to read panel password information, {{ .err }}" UpdatePasswordRead: "Error: Failed to read panel password information, {{ .err }}"
UpdatePasswordNull: "Error: Panel password is empty!" UpdatePasswordNull: "Error: Panel password is empty!"
UpdateUPasswordBlank: "Error: Panel password contains spaces!" UpdateUPasswordBlank: "Error: Panel password contains spaces!"
UpdatePasswordFormat: "Error: Panel password only supports letters, numbers, special characters !@#$%*_,.?, length 8-30!" UpdatePasswordFormat: "Error: Panel password supports only letters, numbers, and special characters (!@#$%*_,.?) with a length of 8-30."
UpdatePasswordLen: "Error: Please enter a password longer than 6 characters!" UpdatePasswordLen: "Error: Enter a password longer than 6 characters"
UpdatePasswordRe: "Confirm password:" UpdatePasswordRe: "Confirm password:"
UpdatePasswordErr: "Error: Failed to update panel password, {{ .err }}" UpdatePasswordErr: "Error: Failed to update panel password, {{ .err }}"
UpdatePasswordSame: "Error: The two passwords do not match, please check and try again!" UpdatePasswordSame: "Error: The two passwords do not match, check and try again!"
UpdatePasswordResult: "Panel password: {{ .name }}" UpdatePasswordResult: "Panel password: {{ .name }}"
UpdatePortFormat: "Error: The input port number must be between 1 and 65535!" UpdatePortFormat: "Error: The input port number must be between 1 and 65535!"
UpdatePortUsed: "Error: The port number is already in use, please check and try again!" UpdatePortUsed: "Error: The port number is already in use, check and try again!"
UpdatePortErr: "Error: Failed to update panel port, {{ .err }}" UpdatePortErr: "Error: Failed to update panel port, {{ .err }}"
UpdatePortResult: "Panel Port: {{ .name }}" UpdatePortResult: "Panel Port: {{ .name }}"
UpdatePortFirewallAdd: "Failed to add firewall port rule, {{ .err }}, please manually add the {{ .name }} port to the firewall rules." UpdatePortFirewallAdd: "Failed to add firewall port rule, {{ .err }}, manually add the {{ .name }} port to the firewall rules."
UpdatePortFirewallDel: "Error: Failed to delete firewall port, {{ .err }}" UpdatePortFirewallDel: "Error: Failed to delete firewall port, {{ .err }}"
UpdatePortFirewallReload: "Failed to reload the firewall, {{ .err }}, please manually reload the firewall." UpdatePortFirewallReload: "Failed to reload the firewall, {{ .err }}, manually reload the firewall."
UserInfo: "Get panel information" UserInfo: "Get panel information"
UserInfoAddr: "Panel address: " UserInfoAddr: "Panel address: "
UserInfoPassHelp: "Tip: To change the password, you can execute the command: " UserInfoPassHelp: "Tip: To change the password, you can execute the command: "
@@ -242,16 +244,16 @@ SystemVersion: "version: "
SystemMode: "mode: " SystemMode: "mode: "
#mobile app #mobile app
ErrVerifyToken: 'Token verification error, please reset and scan again.' ErrVerifyToken: 'Token verification failed. Reset and scan again.'
ErrInvalidToken: 'Invalid token, please reset and scan again.' ErrInvalidToken: 'Invalid token. Reset and scan again.'
ErrExpiredToken: 'Token has expired, please reset and scan again.' ErrExpiredToken: 'Token expired. Reset and scan again.'
#cluster #cluster
ErrMasterDelete: "Unable to delete the master node, please delete the slave nodes first." ErrMasterDelete: "Unable to delete the master node. Delete slave nodes first."
ClusterNameIsExist: "Cluster name already exists." ClusterNameIsExist: "Cluster name already exists."
AppStatusUnHealthy: "Application status acquisition is abnormal, please check the installation node status in the node list." AppStatusUnHealthy: "Failed to fetch application status. Check installation node status in the node list."
MasterNodePortNotAvailable: "Node {{ .name }} port {{ .port }} connectivity verification failed, please check firewall/security group settings and master node status." MasterNodePortNotAvailable: "Node {{ .name }} port {{ .port }} connectivity check failed. Check firewall/security group settings and master node status."
ClusterMasterNotExist: "The master node of the cluster is disconnected, please delete the child nodes." ClusterMasterNotExist: "Cluster master node is disconnected. Delete child nodes."
#ssl #ssl
ErrReqFailed: "{{.name}} request failed: {{ .err }}" ErrReqFailed: "{{.name}} request failed: {{ .err }}"
+71 -69
View File
@@ -1,21 +1,21 @@
ErrInvalidParams: "Parámetros de solicitud no son válidos: {{ .detail }}" ErrInvalidParams: 'Solicitud inválida: {{ .detail }}'
ErrTokenParse: "Error al generar el token: {{ .detail }}" ErrTokenParse: 'Token inválido: {{ .detail }}'
ErrInitialPassword: "Contraseña inicial incorrecta" ErrInitialPassword: 'Contraseña original incorrecta'
ErrInternalServer: "Error interno del servidor: {{ .detail }}" ErrInternalServer: 'Error interno: {{ .detail }}'
ErrRecordExist: "El registro ya existe" ErrRecordExist: 'Registro ya existe'
ErrRecordNotFound: "Registro no encontrado" ErrRecordNotFound: 'Registro no encontrado'
ErrStructTransform: "Error en la conversión de tipo: {{ .detail }}" ErrStructTransform: 'Error de conversión: {{ .err }}'
ErrNotLogin: "Usuario no ha iniciado sesión: {{ .detail }}" ErrNotLogin: 'No has iniciado sesión: {{ .detail }}'
ErrSessionDataNotFound: "¡La sesión actual ha caducado!" ErrSessionDataNotFound: "La sesión actual ha caducado"
ErrSessionDataFormat: "¡El formato de los datos de la sesión actual es anómalo!" ErrSessionDataFormat: "El formato de los datos de la sesión actual es anómalo"
ErrPasswordExpired: "La contraseña actual ha expirado: {{ .detail }}" ErrPasswordExpired: 'Contraseña expirada: {{ .detail }}'
ErrNotSupportType: "El tipo actual no es compatible: {{ .detail }}" ErrNotSupportType: 'Tipo no soportado: {{ .name }}'
ErrProxy: "Error en la solicitud, por favor revise el estado de este nodo: {{ .detail }}" ErrProxy: 'Solicitud fallida: {{ .detail }}'
ErrApiConfigStatusInvalid: "Acceso a la API prohibido: {{ .detail }}" ErrApiConfigStatusInvalid: 'API desactivada: {{ .detail }}'
ErrApiConfigKeyInvalid: "Error de clave API: {{ .detail }}" ErrApiConfigKeyInvalid: 'Clave API inválida: {{ .detail }}'
ErrApiConfigIPInvalid: "La IP de la solicitud API no está en la lista blanca: {{ .detail }}" ErrApiConfigIPInvalid: 'IP no permitida: {{ .detail }}'
ErrApiConfigDisable: "Esta interfaz prohíbe llamadas a la API: {{ .detail }}" ErrApiConfigDisable: 'API no permitida: {{ .detail }}'
ErrApiConfigKeyTimeInvalid: "Error de marca de tiempo de API: {{ .detail }}" ErrApiConfigKeyTimeInvalid: 'Timestamp inválido: {{ .detail }}'
PushAppInstallTaskToNode: "Enviar tarea de instalación de aplicación al nodo [{{ .name }}]" PushAppInstallTaskToNode: "Enviar tarea de instalación de aplicación al nodo [{{ .name }}]"
TaskPush: "Enviar" TaskPush: "Enviar"
AppInstallTask: "Tarea de instalación de aplicación" AppInstallTask: "Tarea de instalación de aplicación"
@@ -28,17 +28,17 @@ ErrHttpReqNotFound: "No se pudo encontrar el recurso solicitado {{ .err }}"
ErrHttpReqFailed: "Solicitud fallida {{ .err }}" ErrHttpReqFailed: "Solicitud fallida {{ .err }}"
ErrHttpReqTimeOut: "La solicitud ha expirado {{ .err }}" ErrHttpReqTimeOut: "La solicitud ha expirado {{ .err }}"
ErrCreateHttpClient: "Error al crear la solicitud {{ .err }}" ErrCreateHttpClient: "Error al crear la solicitud {{ .err }}"
ErrProxySetting: "Información del servidor proxy no disponible {{ .err }}, ¡compruebe e inténtelo de nuevo!" ErrProxySetting: "Información del servidor proxy no disponible {{ .err }}, compruebe e inténtelo de nuevo"
ErrEntranceFormat: "La entrada de seguridad {{ .name }} no está actualmente soportada. ¡Por favor verifique e inténtelo de nuevo!" ErrEntranceFormat: "La entrada de seguridad {{ .name }} no está actualmente soportada. Por favor verifique e inténtelo de nuevo"
# common # common
ErrDemoEnvironment: "Servidor de demostración, ¡esta operación está prohibida!" ErrDemoEnvironment: 'No disponible en demo'
ErrCmdTimeout: "¡Tiempo de espera al ejecutar el comando!" ErrCmdTimeout: 'Comando agotó tiempo'
ErrEntrance: "Error en la información de entrada de seguridad, ¡por favor revise e intente de nuevo!" ErrEntrance: "Error en la información de entrada de seguridad, por favor revise e intente de nuevo"
ErrGroupIsDefault: "Grupo predeterminado, no se puede eliminar" ErrGroupIsDefault: "Grupo predeterminado, no se puede eliminar"
ErrGroupIsInUse: "El grupo está en uso y no se puede eliminar." ErrGroupIsInUse: "El grupo está en uso y no se puede eliminar."
ErrLocalDelete: "¡No se puede eliminar el nodo local!" ErrLocalDelete: "No se puede eliminar el nodo local"
ErrPortInUsed: "¡El puerto {{ .name }} ya está en uso!" ErrPortInUsed: "El puerto {{ .name }} ya está en uso"
ErrInternalServerKey: "Error interno del servidor:" ErrInternalServerKey: "Error interno del servidor:"
MasterNode: "Nodo Maestro" MasterNode: "Nodo Maestro"
@@ -47,45 +47,46 @@ CustomAppStoreFileValid: "El paquete de la tienda de aplicaciones debe tener for
ErrFileNotFound: "El archivo {{ .name }} no existe" ErrFileNotFound: "El archivo {{ .name }} no existe"
AppBackup: 'Copia de seguridad de aplicación' AppBackup: 'Copia de seguridad de aplicación'
AppBackupPush: 'Transferir archivo de copia de seguridad de aplicación {{.file}} al nodo {{ .name }}' AppBackupPush: 'Transferir archivo de copia de seguridad de aplicación {{.file}} al nodo {{ .name }}'
ErrSourceTargetSame: '¡El nodo de origen y el nodo de destino no pueden ser el mismo!' ErrSourceTargetSame: 'El nodo de origen y el nodo de destino no pueden ser el mismo'
AppInstall: 'Instalar aplicación {{ .name }} en nodo {{ .targetNode }}' AppInstall: 'Instalar aplicación {{ .name }} en nodo {{ .targetNode }}'
AppInstallCheck: 'Verificar entorno de instalación de aplicación' AppInstallCheck: 'Verificar entorno de instalación de aplicación'
# backup # backup
ErrBackupInUsed: "Esta cuenta de respaldo se utiliza en tareas programadas y no se puede eliminar" ErrBackupInUsed: 'Cuenta de respaldo en uso por tarea programada'
ErrBackupCheck: "Fallo en la prueba de conexión de la cuenta de respaldo {{ .err }}" ErrBackupCheck: 'Conexión de respaldo falló: {{ .err }}'
ErrBackupLocal: "¡La cuenta de respaldo del servidor local no admite esta operación!" ErrBackupLocal: "La cuenta de respaldo del servidor local no admite esta operación"
ErrBackupPublic: "Se detectó que esta cuenta de respaldo no es pública, ¡verifique e intente de nuevo!" ErrBackupPublic: "Se detectó que esta cuenta de respaldo no es pública, verifique e intente de nuevo"
ErrOSSConn: "No se pudo obtener la última versión, por favor revise la conectividad de red externa del servidor." ErrOSSConn: "No se pudo obtener la última versión, por favor revise la conectividad de red externa del servidor."
#license #license
LicenseCheck: 'Comprobar si la licencia está disponible' LicenseCheck: 'Comprobar si la licencia está disponible'
ErrLicenseInUsed: 'La licencia ya está vinculada. ¡Verifique e intente de nuevo!' ErrLicenseInUsed: 'La licencia ya está vinculada. Verifique e intente de nuevo'
ErrLicenseExpired: 'La licencia ha expirado. ¡Verifique e intente de nuevo!' ErrLicenseExpired: 'La licencia ha expirado. Verifique e intente de nuevo'
ErrLicense: "Error en el formato de la licencia, ¡verifique y reintente!" ErrLicense: "Error en el formato de la licencia, verifique y reintente"
ErrLicenseCheck: "Validación de licencia fallida, ¡verifique y reintente!" ErrLicenseCheck: "Validación de licencia fallida, verifique y reintente"
ErrXpackVersion: "Validación de licencia fallida, esta licencia está limitada por versión, no se puede importar, ¡verifique y reintente!" ErrXpackVersion: "Validación de licencia fallida, esta licencia está limitada por versión, no se puede importar, verifique y reintente"
ErrLicenseSave: "Error al guardar la información de la licencia, error {{ .err }}, ¡reintente!" ErrLicenseSave: "Error al guardar la información de la licencia, error {{ .err }}, reintente"
ErrLicenseSync: "Sincronización de licencia fallida, ¡no se detectó información de licencia en la base de datos!" ErrLicenseSync: "Sincronización de licencia fallida, no se detectó información de licencia en la base de datos"
ErrLicenseExist: "Este registro de licencia ya existe. Puede ir directamente a la página de licencia para la vinculación del nodo." ErrLicenseExist: "Este registro de licencia ya existe. Puede ir directamente a la página de licencia para la vinculación del nodo."
ErrXpackNotFound: "Esta sección es para la edición profesional, importe la licencia en Panel > Ajustes > Licencia" ErrXpackNotFound: "Esta sección es para la edición profesional, importe la licencia en Panel > Ajustes > Licencia"
ErrXpackExceptional: "Esta sección es para la edición profesional, sincronice el estado de la licencia en Panel > Ajustes > Licencia" ErrXpackExceptional: "Esta sección es para la edición profesional, sincronice el estado de la licencia en Panel > Ajustes > Licencia"
ErrXpackOutOfDate: "La licencia actual ha expirado, importe nuevamente la licencia en Panel > Ajustes > Licencia" ErrXpackOutOfDate: "La licencia actual ha expirado, importe nuevamente la licencia en Panel > Ajustes > Licencia"
ErrXpackLost: "La licencia ha alcanzado el número máximo de reintentos, vaya a [Ajustes del Panel] [Licencia] y haga clic en el botón de sincronización manualmente para asegurar el funcionamiento correcto de las funciones profesionales" ErrXpackLost: "La licencia ha alcanzado el número máximo de reintentos, vaya a [Ajustes del Panel] [Licencia] y haga clic en el botón de sincronización manualmente para asegurar el funcionamiento correcto de las funciones profesionales"
ErrDeviceLost: "Faltan archivos necesarios para la verificación de licencia, ¡verifique e intente de nuevo!" ErrDeviceLost: "Faltan archivos necesarios para la verificación de licencia, verifique e intente de nuevo"
ErrDeviceErr: "El entorno actual no coincide con el entorno de importación de la licencia. ¡Edite la licencia e impórtela de nuevo!" ErrDeviceErr: "El entorno actual no coincide con el entorno de importación de la licencia. Edite la licencia e impórtela de nuevo"
ErrXpackTimeout: "Tiempo de espera de la solicitud, puede que la conexión de red sea inestable, ¡intente más tarde!" ErrXpackTimeout: "Tiempo de espera de la solicitud, puede que la conexión de red sea inestable, intente más tarde"
ErrUnbindMaster: "Se detectaron nodos en la gestión de nodos, no se puede desvincular la licencia actual, elimine los nodos primero e intente de nuevo!" ErrUnbindMaster: "Se detectaron nodos en la gestión de nodos, no se puede desvincular la licencia actual, elimine los nodos primero e intente de nuevo"
ErrFreeNodeLimit: "Se alcanzó el límite de nodos en la versión comunitaria, ¡vaya a www.lxware.cn/1panel para comprar y reintentar!" ErrFreeNodeLimit: "Se alcanzó el límite de nodos en la versión comunitaria, vaya a www.lxware.cn/1panel para comprar y reintentar"
ErrNodeBound: "Esta licencia está vinculada a otro nodo, ¡verifique e intente de nuevo!" ErrNodeBound: "Esta licencia está vinculada a otro nodo, verifique e intente de nuevo"
ErrNodeBoundDelete: "Esta licencia está vinculada y no admite operaciones de eliminación. ¡Verifique e intente de nuevo!" ErrNodeBoundDelete: "Esta licencia está vinculada y no admite operaciones de eliminación. Verifique e intente de nuevo"
ErrNodeBoundLimit: "El nodo gratuito actual ha alcanzado su límite, ¡verifique e intente de nuevo!" ErrNodeBoundLimit: "El nodo gratuito actual ha alcanzado su límite, verifique e intente de nuevo"
ErrLicenseFree: "Los nodos gratuitos solo pueden usarse si la licencia está correctamente vinculada a un nodo. ¡Verifique e intente de nuevo!" ErrLicenseFree: "Los nodos gratuitos solo pueden usarse si la licencia está correctamente vinculada a un nodo. Verifique e intente de nuevo"
ErrLicenseUnbind: "Se detectaron nodos de la Edición Comunitaria para esta licencia. ¡Desvincule en [Panel > Ajustes > Licencia] y vuelva a intentarlo!" ErrLicenseUnbind: "Se detectaron nodos de la Edición Comunitaria para esta licencia. Desvincule en [Panel > Ajustes > Licencia] y vuelva a intentarlo"
ErrNoSuchNode: "Información del nodo no encontrada, ¡verifique e intente de nuevo!" ErrNoSuchNode: "Información del nodo no encontrada, verifique e intente de nuevo"
ErrNodeUnbind: "Este nodo no está dentro del rango de vinculación de la licencia, ¡verifique e intente de nuevo!" ErrNodeUnbind: "Este nodo no está dentro del rango de vinculación de la licencia, verifique e intente de nuevo"
ErrNodeBind: "Este nodo ya está vinculado a una licencia, ¡verifique e intente de nuevo!" ErrNodeBind: "Este nodo ya está vinculado a una licencia, verifique e intente de nuevo"
ErrNodeLocalRollback: "El nodo principal no admite la reversión directa. ¡Ejecute manualmente el comando '1pctl restore' para revertir!" ErrNodeLocalRollback: "El nodo principal no admite la reversión directa. Ejecute manualmente el comando '1pctl restore' para revertir"
ErrIntlLicense: "La versión actual aún no admite importar licencias de la edición internacional. Próximamente"
InvalidRequestBodyType: "Formato del cuerpo de la solicitud no válido, por favor revisa y asegúrate de que el contenido cumpla con el formato requerido antes de reintentar." InvalidRequestBodyType: "Formato del cuerpo de la solicitud no válido, por favor revisa y asegúrate de que el contenido cumpla con el formato requerido antes de reintentar."
InvalidLicenseCodeType: "Formato de código de licencia no válido, por favor revisa e inténtalo de nuevo." InvalidLicenseCodeType: "Formato de código de licencia no válido, por favor revisa e inténtalo de nuevo."
LicenseNotFoundType: "Licencia no encontrada, no existe ningún registro coincidente en el sistema para la licencia proporcionada. Por favor revisa e inténtalo de nuevo." LicenseNotFoundType: "Licencia no encontrada, no existe ningún registro coincidente en el sistema para la licencia proporcionada. Por favor revisa e inténtalo de nuevo."
@@ -97,7 +98,7 @@ LicenseUsageNotFoundType: "No se encontraron registros de uso. Esta licencia no
LicenseUsageLimitExceededType: "Esta licencia ya está vinculada a otro nodo. Por favor revisa e inténtalo de nuevo." LicenseUsageLimitExceededType: "Esta licencia ya está vinculada a otro nodo. Por favor revisa e inténtalo de nuevo."
# alert # alert
ErrAlertSync: "Error al sincronizar la información de alertas, ¡verifique e intente de nuevo!" ErrAlertSync: "Error al sincronizar la información de alertas, verifique e intente de nuevo"
# task # task
TaskStart: "Tarea {{ .name }} iniciada [INICIO]" TaskStart: "Tarea {{ .name }} iniciada [INICIO]"
@@ -122,7 +123,7 @@ Skip: "Omitir errores y continuar..."
#script #script
ScriptLibrary: "Biblioteca de scripts" ScriptLibrary: "Biblioteca de scripts"
RemoteScriptLibrary: "Biblioteca de Scripts Remota" RemoteScriptLibrary: "Biblioteca de Scripts Remota"
ScriptSyncSkip: "¡La biblioteca de scripts ya está en la última versión!" ScriptSyncSkip: "La biblioteca de scripts ya está en la última versión"
DownloadData: "Descargando archivo de datos de la biblioteca de scripts data.yaml" DownloadData: "Descargando archivo de datos de la biblioteca de scripts data.yaml"
DownloadPackage: "Descargando paquete de la biblioteca de scripts" DownloadPackage: "Descargando paquete de la biblioteca de scripts"
AnalyticCompletion: "Análisis completado, sincronizando con la base de datos..." AnalyticCompletion: "Análisis completado, sincronizando con la base de datos..."
@@ -134,13 +135,14 @@ SyncPackageData: "Sincronizar datos del paquete [{{ .detail }}]"
SyncPackageEncrypt: "Encriptación del paquete de datos" SyncPackageEncrypt: "Encriptación del paquete de datos"
SyncRequest: "Solicitar API de sincronización de nodos" SyncRequest: "Solicitar API de sincronización de nodos"
SyncFailedRetry: "Tiempo de espera en la sincronización de datos del nodo (intento {{ .index }}), reintentando..." SyncFailedRetry: "Tiempo de espera en la sincronización de datos del nodo (intento {{ .index }}), reintentando..."
SyncFailed: "¡La sincronización falló, sincronice manualmente en la lista de nodos!" SyncFailed: "La sincronización falló, sincronice manualmente en la lista de nodos"
SyncSystemProxy: "Configuración del proxy del sistema" SyncSystemProxy: "Configuración del proxy del sistema"
SyncScripts: "Biblioteca de scripts" SyncScripts: "Biblioteca de scripts"
SyncBackupAccounts: "Cuentas de copia de seguridad" SyncBackupAccounts: "Cuentas de copia de seguridad"
SyncAlertSetting: "Configuración de alertas" SyncAlertSetting: "Configuración de alertas"
SyncCustomApp: "Aplicación personalizada" SyncCustomApp: "Aplicación personalizada"
SyncLanguage: "Idioma del sistema" SyncLanguage: "Idioma del sistema"
SyncEdition: "Región"
#upgrade node #upgrade node
NodeUpgrade: "Actualizar nodo {{ .name }}" NodeUpgrade: "Actualizar nodo {{ .name }}"
@@ -179,14 +181,14 @@ AppCreateFileErr: "Error al crear el archivo {{ .name }} {{ .err }}"
AppCreateDirErr: "Error al crear la carpeta {{ .name }} {{ .err }}" AppCreateDirErr: "Error al crear la carpeta {{ .name }} {{ .err }}"
AppMissKey: "Falta la clave de la app, use -k para especificar" AppMissKey: "Falta la clave de la app, use -k para especificar"
AppMissVersion: "Falta la versión de la app, use -v para especificar" AppMissVersion: "Falta la versión de la app, use -v para especificar"
AppVersionExist: "¡La versión ya existe!" AppVersionExist: "La versión ya existe"
AppCreateSuccessful: "¡Creación finalizada con éxito!" AppCreateSuccessful: "Creación finalizada con éxito"
AppWriteErr: "Error al escribir el archivo {{ .name }} {{ .err }}" AppWriteErr: "Error al escribir el archivo {{ .name }} {{ .err }}"
SudoHelper: "Por favor use {{ .cmd }} o cambie al usuario root" SudoHelper: "Por favor use {{ .cmd }} o cambie al usuario root"
ListenIPCommands: "Cambiar ip de escucha" ListenIPCommands: "Cambiar ip de escucha"
ListenIPv4: "Escuchar en IPv4" ListenIPv4: "Escuchar en IPv4"
ListenIPv6: "Escuchar en IPv6" ListenIPv6: "Escuchar en IPv6"
ListenChangeSuccessful: "¡Cambio exitoso! Ahora escuchando en {{ .value }}" ListenChangeSuccessful: "Cambio exitoso Ahora escuchando en {{ .value }}"
ResetCommands: "Restablecer información del sistema" ResetCommands: "Restablecer información del sistema"
ResetMFA: "Cancelar autenticación de dos factores de 1Panel" ResetMFA: "Cancelar autenticación de dos factores de 1Panel"
ResetHttps: "Cancelar inicio de sesión https de 1Panel" ResetHttps: "Cancelar inicio de sesión https de 1Panel"
@@ -201,28 +203,28 @@ RestoreStep2: "(2/5) Reversión de binarios de 1Panel finalizada con éxito"
RestoreStep3: "(3/5) Reversión de scripts de 1Panel finalizada con éxito" RestoreStep3: "(3/5) Reversión de scripts de 1Panel finalizada con éxito"
RestoreStep4: "(4/5) Reversión de servicio de 1Panel finalizada con éxito" RestoreStep4: "(4/5) Reversión de servicio de 1Panel finalizada con éxito"
RestoreStep5: "(5/5) Reversión de datos de 1Panel finalizada con éxito" RestoreStep5: "(5/5) Reversión de datos de 1Panel finalizada con éxito"
RestoreSuccessful: "¡Reversión exitosa! Revertido a {{ .version }}, reiniciando servicio, espere por favor..." RestoreSuccessful: "Reversión exitosa Revertido a {{ .version }}, reiniciando servicio, espere por favor..."
UpdateCommands: "Actualizar información del panel" UpdateCommands: "Actualizar información del panel"
UpdateUser: "Actualizar usuario del panel" UpdateUser: "Actualizar usuario del panel"
UpdatePassword: "Actualizar contraseña del panel" UpdatePassword: "Actualizar contraseña del panel"
UpdatePort: "Actualizar puerto del panel" UpdatePort: "Actualizar puerto del panel"
UpdateUserNull: "Error: ¡el usuario del panel está vacío!" UpdateUserNull: "Error: el usuario del panel está vacío"
UpdateUserBlank: "Error: ¡el usuario del panel contiene espacios!" UpdateUserBlank: "Error: el usuario del panel contiene espacios"
UpdateUserFormat: "Error: ¡formato de usuario del panel inválido! Solo admite inglés, chino, números y _, longitud 3-30" UpdateUserFormat: "Error: formato de usuario del panel inválido Solo admite inglés, chino, números y _, longitud 3-30"
UpdateUserErr: "Error: Fallo al actualizar usuario del panel, {{ .err }}" UpdateUserErr: "Error: Fallo al actualizar usuario del panel, {{ .err }}"
UpdateSuccessful: "¡Actualización finalizada con éxito!" UpdateSuccessful: "Actualización finalizada con éxito"
UpdateUserResult: "Usuario del panel: {{ .name }}" UpdateUserResult: "Usuario del panel: {{ .name }}"
UpdatePasswordRead: "Error: Fallo al leer información de la contraseña del panel, {{ .err }}" UpdatePasswordRead: "Error: Fallo al leer información de la contraseña del panel, {{ .err }}"
UpdatePasswordNull: "Error: ¡la contraseña del panel está vacía!" UpdatePasswordNull: "Error: la contraseña del panel está vacía"
UpdateUPasswordBlank: "Error: ¡la contraseña del panel contiene espacios!" UpdateUPasswordBlank: "Error: la contraseña del panel contiene espacios"
UpdatePasswordFormat: "Error: ¡La contraseña solo admite letras, números y los caracteres especiales !@#$%*_,.?, longitud 8-30!" UpdatePasswordFormat: "Error: La contraseña del panel solo admite letras, números y caracteres especiales (@#$%*_,.?), con una longitud de 8-30."
UpdatePasswordLen: "Error: ¡Ingrese una contraseña mayor a 6 caracteres!" UpdatePasswordLen: "Error: Ingrese una contraseña mayor a 6 caracteres"
UpdatePasswordRe: "Confirmar contraseña:" UpdatePasswordRe: "Confirmar contraseña:"
UpdatePasswordErr: "Error: Fallo al actualizar la contraseña del panel, {{ .err }}" UpdatePasswordErr: "Error: Fallo al actualizar la contraseña del panel, {{ .err }}"
UpdatePasswordSame: "Error: Las dos contraseñas no coinciden, ¡verifique e intente de nuevo!" UpdatePasswordSame: "Error: Las dos contraseñas no coinciden, verifique e intente de nuevo"
UpdatePasswordResult: "Contraseña del panel: {{ .name }}" UpdatePasswordResult: "Contraseña del panel: {{ .name }}"
UpdatePortFormat: "Error: ¡El puerto debe estar entre 1 y 65535!" UpdatePortFormat: "Error: El puerto debe estar entre 1 y 65535"
UpdatePortUsed: "Error: ¡El puerto ya está en uso, verifique e intente de nuevo!" UpdatePortUsed: "Error: El puerto ya está en uso, verifique e intente de nuevo"
UpdatePortErr: "Error: Fallo al actualizar el puerto del panel, {{ .err }}" UpdatePortErr: "Error: Fallo al actualizar el puerto del panel, {{ .err }}"
UpdatePortResult: "Puerto del panel: {{ .name }}" UpdatePortResult: "Puerto del panel: {{ .name }}"
UpdatePortFirewallAdd: "Fallo al agregar la regla de puerto al firewall, {{ .err }}, agregue manualmente el puerto {{ .name }} al firewall." UpdatePortFirewallAdd: "Fallo al agregar la regla de puerto al firewall, {{ .err }}, agregue manualmente el puerto {{ .name }} al firewall."
+44 -42
View File
@@ -1,21 +1,21 @@
ErrInvalidParams: "リクエストパラメータが無効です: {{ .detail }}" ErrInvalidParams: '不正なリクエスト: {{ .detail }}'
ErrTokenParse: "トークン生成エラー: {{ .detail }}" ErrTokenParse: 'トークンエラー: {{ .detail }}'
ErrInitialPassword: "初期パスワードが間違っています" ErrInitialPassword: '元のパスワードが違います'
ErrInternalServer: "サーバー内部エラー: {{ .detail }}" ErrInternalServer: '内部エラー: {{ .detail }}'
ErrRecordExist: "レコードはすでに存在します" ErrRecordExist: 'レコードが既に存在します'
ErrRecordNotFound: "レコードが見つかりません" ErrRecordNotFound: 'レコードが見つかりません'
ErrStructTransform: "型変換に失敗しました: {{ .detail }}" ErrStructTransform: '型変換エラー: {{ .err }}'
ErrNotLogin: "ユーザーがログインしていません: {{ .detail }}" ErrNotLogin: 'ログインしていません: {{ .detail }}'
ErrSessionDataNotFound: "現在のセッションは期限切れです!" ErrSessionDataNotFound: "現在のセッションは期限切れです!"
ErrSessionDataFormat: "現在のセッションデータ形式が異常です!" ErrSessionDataFormat: "現在のセッションデータ形式が異常です!"
ErrPasswordExpired: "現在のパスワードの有効期限が切れています: {{ .detail }}" ErrPasswordExpired: 'パスワード期限切れ: {{ .detail }}'
ErrNotSupportType: "現在のタイプはサポートされていません: {{ .detail }}" ErrNotSupportType: '未対応のタイプ: {{ .name }}'
ErrProxy: "リクエストエラー、このノードの状態を確認してください: {{ .detail }}" ErrProxy: 'リクエストに失敗しました: {{ .detail }}'
ErrApiConfigStatusInvalid: "APIアクセスは禁止されています: {{ .detail }}" ErrApiConfigStatusInvalid: 'API利用不可: {{ .detail }}'
ErrApiConfigKeyInvalid: "APIキーが無効です: {{ .detail }}" ErrApiConfigKeyInvalid: 'APIキーが無効です: {{ .detail }}'
ErrApiConfigIPInvalid: "APIリクエストIPがホワイトリストにありません: {{ .detail }}" ErrApiConfigIPInvalid: 'IPが許可されていません: {{ .detail }}'
ErrApiConfigDisable: "このインターフェースはAPI呼び出しを禁止しています: {{ .detail }}" ErrApiConfigDisable: 'APIは無効です: {{ .detail }}'
ErrApiConfigKeyTimeInvalid: "APIタイムスタンプエラー: {{ .detail }}" ErrApiConfigKeyTimeInvalid: 'タイムスタンプが無効です: {{ .detail }}'
# request # request
ErrNoSuchHost: "要求されたサーバーが見つかりません {{ .err }}" ErrNoSuchHost: "要求されたサーバーが見つかりません {{ .err }}"
@@ -27,8 +27,8 @@ ErrProxySetting: "プロキシサーバー情報が利用できません {{ .err
ErrEntranceFormat: "セキュリティエントランス {{ .name }} は現在サポートされていません。確認して再試行してください!" ErrEntranceFormat: "セキュリティエントランス {{ .name }} は現在サポートされていません。確認して再試行してください!"
# common # common
ErrDemoEnvironment: "デモサーバーではこの操作は許可されていません!" ErrDemoEnvironment: 'デモ環境では利用できません'
ErrCmdTimeout: "コマンドの実行がタイムアウトしました!" ErrCmdTimeout: 'コマンドがタイムアウトしました'
ErrEntrance: "セキュリティ情報エラー、再確認してください!" ErrEntrance: "セキュリティ情報エラー、再確認してください!"
ErrGroupIsDefault: "デフォルトグループの削除はできません" ErrGroupIsDefault: "デフォルトグループの削除はできません"
ErrGroupIsInUse: "グループは使用中のため、削除できません。" ErrGroupIsInUse: "グループは使用中のため、削除できません。"
@@ -47,8 +47,8 @@ AppInstall: 'ノード {{ .targetNode }} にアプリケーション {{ .name }}
AppInstallCheck: 'アプリケーションインストール環境を確認' AppInstallCheck: 'アプリケーションインストール環境を確認'
# backup # backup
ErrBackupInUsed: "このバックアップアカウントはスケジュールタスクで使用されており、削除できません" ErrBackupInUsed: 'バックアップアカウントがスケジュールで使用中'
ErrBackupCheck: "バックアップアカウントの接続テストが失敗しました {{ .err }}" ErrBackupCheck: '接続テストに失敗しました: {{ .err }}'
ErrBackupLocal: "ローカルサーバーバックアップアカウントはこの操作をサポートしていません!" ErrBackupLocal: "ローカルサーバーバックアップアカウントはこの操作をサポートしていません!"
ErrBackupPublic: "このバックアップアカウントが公開されていないと検出されました。再確認してください!" ErrBackupPublic: "このバックアップアカウントが公開されていないと検出されました。再確認してください!"
ErrOSSConn: "最新バージョンを取得できません。外部ネットワーク接続を確認してください。" ErrOSSConn: "最新バージョンを取得できません。外部ネットワーク接続を確認してください。"
@@ -58,39 +58,40 @@ ErrOSSConn: "最新バージョンを取得できません。外部ネットワ
LicenseCheck: 'ライセンスが利用可能か確認する' LicenseCheck: 'ライセンスが利用可能か確認する'
ErrLicenseInUsed: 'このライセンスは既に紐付けられています。確認して再試行してください!' ErrLicenseInUsed: 'このライセンスは既に紐付けられています。確認して再試行してください!'
ErrLicenseExpired: 'このライセンスは期限切れです。確認して再試行してください!' ErrLicenseExpired: 'このライセンスは期限切れです。確認して再試行してください!'
ErrLicense: "ライセンスフォーマットエラー、確認して再試行してください!" ErrLicense: "ライセンスフォーマットエラー、確認して再試行してください"
ErrLicenseCheck: "ライセンスの確認に失敗しました、確認して再試行してください!" ErrLicenseCheck: "ライセンスの確認に失敗しました、確認して再試行してください"
ErrXpackVersion: "ライセンスの確認に失敗しました、このライセンスはバージョン制限があり、正常にインポートできません、確認して再試行してください!" ErrXpackVersion: "ライセンスの確認に失敗しました、このライセンスはバージョン制限があり、正常にインポートできません、確認して再試行してください"
ErrLicenseSave: "ライセンス情報の保存に失敗しました、エラー {{ .err }}、再試行してください!" ErrLicenseSave: "ライセンス情報の保存に失敗しました、エラー {{ .err }}、再試行してください"
ErrLicenseSync: "ライセンス情報の同期に失敗しました、データベースにライセンス情報が検出されませんでした!" ErrLicenseSync: "ライセンス情報の同期に失敗しました、データベースにライセンス情報が検出されませんでした"
ErrLicenseExist: "このライセンス記録は既に存在します。ライセンスページで直接ノードの紐付けが可能です。" ErrLicenseExist: "このライセンス記録は既に存在します。ライセンスページで直接ノードの紐付けが可能です。"
ErrXpackNotFound: "この部分はプロフェッショナル版機能です、まず「パネル設定-ライセンス」画面でライセンスをインポートしてください" ErrXpackNotFound: "この部分はプロフェッショナル版機能です、まず「パネル設定-ライセンス」画面でライセンスをインポートしてください"
ErrXpackExceptional: "この部分はプロフェッショナル版機能です、まず「パネル設定-ライセンス」画面でライセンス状態を同期してください" ErrXpackExceptional: "この部分はプロフェッショナル版機能です、まず「パネル設定-ライセンス」画面でライセンス状態を同期してください"
ErrXpackLost: "ライセンスの最大試行回数に達しました、「パネル設定」「ライセンス」ページに移動し、手動で同期ボタンをクリックして、プロフェッショナル版機能が正常に使用できることを確認してください" ErrXpackLost: "ライセンスの最大試行回数に達しました、「パネル設定」「ライセンス」ページに移動し、手動で同期ボタンをクリックして、プロフェッショナル版機能が正常に使用できることを確認してください"
ErrDeviceLost: "ライセンス検証に必要なファイルが失われました。確認して再試行してください!" ErrDeviceLost: "ライセンス検証に必要なファイルが失われました。確認して再試行してください!"
ErrDeviceErr: "現在の環境とライセンスのインポート環境が一致しません。ライセンスを編集して再度インポートしてください!" ErrDeviceErr: "現在の環境とライセンスのインポート環境が一致しません。ライセンスを編集して再度インポートしてください!"
ErrXpackTimeout: "リクエストタイムアウト、ネットワーク接続が不安定な可能性があります。後で再試行してください!" ErrXpackTimeout: "リクエストタイムアウト、ネットワーク接続が不安定な可能性があります。後で再試行してください"
ErrUnbindMaster: "ノード管理にノードが存在するため、現在のライセンスを解除できません。ノードを削除してから再試行してください!" ErrUnbindMaster: "ノード管理にノードが存在するため、現在のライセンスを解除できません。ノードを削除してから再試行してください"
ErrFreeNodeLimit: "コミュニティ版のノード数が無料上限に達しました、www.lxware.cn/1panel で購入して再試行してください!" ErrFreeNodeLimit: "コミュニティ版のノード数が無料上限に達しました、www.lxware.cn/1panel で購入して再試行してください"
ErrNodeBound: "このライセンスは他のノードにバインドされています、確認して再試行してください!" ErrNodeBound: "このライセンスは他のノードにバインドされています、確認して再試行してください"
ErrNodeBoundDelete: "このライセンスはバインドされており、削除操作はサポートされていません。確認して再試行してください!" ErrNodeBoundDelete: "このライセンスはバインドされており、削除操作はサポートされていません。確認して再試行してください!"
ErrNodeBoundLimit: "現在の無料ノードは上限に達しました。確認して再試行してください!" ErrNodeBoundLimit: "現在の無料ノードは上限に達しました。確認して再試行してください!"
ErrLicenseFree: "ライセンスがノードに正常にバインドされている場合のみ、その無料ノードを使用できます。確認して再試行してください!" ErrLicenseFree: "ライセンスがノードに正常にバインドされている場合のみ、その無料ノードを使用できます。確認して再試行してください!"
ErrLicenseUnbind: "このライセンスにコミュニティ版ノードが存在します。[パネル設定 - ライセンス]でバインド解除してから再試行してください!" ErrLicenseUnbind: "このライセンスにコミュニティ版ノードが存在します。[パネル設定 - ライセンス]でバインド解除してから再試行してください!"
ErrNoSuchNode: "そのノード情報が見つかりませんでした、確認して再試行してください!" ErrNoSuchNode: "そのノード情報が見つかりませんでした、確認して再試行してください"
ErrNodeUnbind: "そのノードはライセンスのバインド範囲内ではありません、確認して再試行してください!" ErrNodeUnbind: "そのノードはライセンスのバインド範囲内ではありません、確認して再試行してください"
ErrNodeBind: "そのノードはライセンスにバインドされています、確認して再試行してください!" ErrNodeBind: "そのノードはライセンスにバインドされています、確認して再試行してください"
ErrNodeLocalRollback: "マスターノードは直接ロールバックをサポートしていません。手動で「1pctl restore」コマンドを実行してロールバックしてください!" ErrNodeLocalRollback: "マスターノードは直接ロールバックをサポートしていません。手動で「1pctl restore」コマンドを実行してロールバックしてください!"
ErrIntlLicense: "現在のバージョンでは国際版ライセンスのインポートはまだサポートされていません。しばらくお待ちください!"
InvalidRequestBodyType: "リクエストボディの形式が無効です。内容が要求された形式に準拠しているか確認してから再試行してください!" InvalidRequestBodyType: "リクエストボディの形式が無効です。内容が要求された形式に準拠しているか確認してから再試行してください!"
InvalidLicenseCodeType: "提供されたライセンスコードの形式が無効です。確認してから再試行してください!" InvalidLicenseCodeType: "提供されたライセンスコードの形式が無効です。確認してから再試行してください!"
LicenseNotFoundType: "ライセンスが見つかりません。提供されたライセンスに一致する記録がシステム内に存在しません。確認してから再試行してください!" LicenseNotFoundType: "ライセンスが見つかりません。提供されたライセンスに一致する記録がシステム内に存在しません。確認してから再試行してください!"
LicenseRevokedType: "リクエストされたライセンスは廃止されており、使用できません。確認してから再試行してください!" LicenseRevokedType: "リクエストされたライセンスは廃止されており、使用できません。確認してから再試行してください!"
LicenseExpiredType: "ライセンスの有効期限が切れています。更新するか、パネル設定 - ライセンス 画面で再インポートしてから再試行してください!" LicenseExpiredType: "ライセンスの有効期限が切れています。更新するか、パネル設定 - ライセンス 画面で再インポートしてから再試行してください!"
LicenseProductMismatchType: "ライセンスがリクエストされた製品またはサービスと一致しません!" LicenseProductMismatchType: "ライセンスがリクエストされた製品またはサービスと一致しません!"
InvalidAssigneeType: "ライセンス割り当ての対象ユーザーまたはデバイス情報が無効です。確認してから再試行してください!" InvalidAssigneeType: "ライセンス割り当ての対象ユーザーまたはデバイス情報が無効です。確認してから再試行してください!"
LicenseUsageNotFoundType: "使用記録がありません。このライセンスはまだ有効化または使用されていません。確認してから再試行してください!" LicenseUsageNotFoundType: "使用記録がありません。このライセンスはまだ有効化または使用されていません。確認してから再試行してください!"
LicenseUsageLimitExceededType: "このライセンスは既に他のノードにバインドされています。確認してから再試行してください!" LicenseUsageLimitExceededType: "このライセンスは既に他のノードにバインドされています。確認してから再試行してください!"
# alert # alert
ErrAlertSync: "アラート情報の同期エラーです。後で再試行してください!" ErrAlertSync: "アラート情報の同期エラーです。後で再試行してください!"
@@ -142,6 +143,7 @@ SyncBackupAccounts: "バックアップアカウント"
SyncAlertSetting: "アラート設定" SyncAlertSetting: "アラート設定"
SyncCustomApp: "カスタムアプリ" SyncCustomApp: "カスタムアプリ"
SyncLanguage: "システム言語" SyncLanguage: "システム言語"
SyncEdition: "実行リージョン"
#upgrade node #upgrade node
NodeUpgrade: "{{ .name }} ノードのアップグレード" NodeUpgrade: "{{ .name }} ノードのアップグレード"
@@ -216,7 +218,7 @@ UpdateUserResult: "パネルユーザー: {{ .name }}"
UpdatePasswordRead: "エラー: パネルパスワード情報の読み取りに失敗しました、{{ .err }}" UpdatePasswordRead: "エラー: パネルパスワード情報の読み取りに失敗しました、{{ .err }}"
UpdatePasswordNull: "エラー: パネルパスワードは空です!" UpdatePasswordNull: "エラー: パネルパスワードは空です!"
UpdateUPasswordBlank: "エラー: パスワードにはスペースが含まれています!" UpdateUPasswordBlank: "エラー: パスワードにはスペースが含まれています!"
UpdatePasswordFormat: "エラー: パネルパスワードは、文字、数字、特殊文字のみをサポートします!@#$%*_、。、、長さ8-30!" UpdatePasswordFormat: "エラー: パネルパスワードは英字、数字、特殊文字(@#$%*_,.?)のみ使用でき、長さは8〜30文字です。"
UpdatePasswordLen: "エラー: 6文字より長くパスワードを入力してください!" UpdatePasswordLen: "エラー: 6文字より長くパスワードを入力してください!"
UpdatePasswordRe: "パスワードを認証する: " UpdatePasswordRe: "パスワードを認証する: "
UpdatePasswordErr: "エラー: {{ .err }}のパスワードの更新に失敗しました" UpdatePasswordErr: "エラー: {{ .err }}のパスワードの更新に失敗しました"

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