feat: Create and delete runtime environments, and add task logs. (#13081)

This commit is contained in:
CityFun
2026-06-18 18:46:32 +08:00
committed by GitHub
parent efd84b1e1b
commit 868f1db4c5
54 changed files with 731 additions and 990 deletions
+5 -2
View File
@@ -21,6 +21,7 @@ type RuntimeCreate struct {
Source string `json:"source"`
CodeDir string `json:"codeDir"`
Remark string `json:"remark"`
TaskID string `json:"taskID"`
Params map[string]interface{} `json:"params"`
NodeConfig
@@ -58,8 +59,10 @@ type ExtraHost struct {
}
type RuntimeDelete struct {
ID uint `json:"id"`
ForceDelete bool `json:"forceDelete"`
ID uint `json:"id"`
ForceDelete bool `json:"forceDelete"`
DeleteImage bool `json:"deleteImage"`
TaskID string `json:"taskID"`
}
type RuntimeUpdate struct {
+281 -46
View File
@@ -29,6 +29,7 @@ import (
"github.com/1Panel-dev/1Panel/agent/buserr"
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/i18n"
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
"github.com/1Panel-dev/1Panel/agent/utils/compose"
"github.com/1Panel-dev/1Panel/agent/utils/docker"
@@ -82,6 +83,47 @@ func NewRuntimeService() IRuntimeService {
return &RuntimeService{}
}
var pullRuntimeComposeImages = compose.PullComposeImages
var downRuntimeCompose = compose.Down
type runtimeTaskMeta struct {
resourceName string
operate string
scope string
taskID string
resourceID uint
}
func buildRuntimeCreateTaskMeta(create request.RuntimeCreate, runtimeID uint) runtimeTaskMeta {
return runtimeTaskMeta{
resourceName: create.Name,
operate: task.TaskCreate,
scope: task.TaskScopeRuntime,
taskID: create.TaskID,
resourceID: runtimeID,
}
}
func buildRuntimeDeleteTaskMeta(deleteReq request.RuntimeDelete, runtime *model.Runtime) runtimeTaskMeta {
return runtimeTaskMeta{
resourceName: runtime.Name,
operate: task.TaskDelete,
scope: task.TaskScopeRuntime,
taskID: deleteReq.TaskID,
resourceID: deleteReq.ID,
}
}
func runtimeCreateInitialStatus(create request.RuntimeCreate) string {
if create.Type == constant.RuntimePHP {
if create.Resource == constant.ResourceLocal {
return constant.StatusNormal
}
return constant.StatusBuilding
}
return constant.StatusCreating
}
func (r *RuntimeService) Create(create request.RuntimeCreate) (*model.Runtime, error) {
var (
opts []repo.DBOption
@@ -104,20 +146,29 @@ func (r *RuntimeService) Create(create request.RuntimeCreate) (*model.Runtime, e
return nil, err
}
}
if create.Type == constant.RuntimePHP && create.Resource == constant.ResourceLocal {
runtime := &model.Runtime{
Name: create.Name,
Resource: create.Resource,
Type: create.Type,
Version: create.Version,
Status: runtimeCreateInitialStatus(create),
Remark: create.Remark,
}
if err := runtimeRepo.Create(context.Background(), runtime); err != nil {
return nil, err
}
if err := startRuntimeCreateTask(create, runtime, model.App{}, model.AppDetail{}, ""); err != nil {
runtime.Status = constant.StatusError
runtime.Message = err.Error()
_ = runtimeRepo.Save(runtime)
return nil, err
}
return runtime, nil
}
var hostPorts []string
switch create.Type {
case constant.RuntimePHP:
if create.Resource == constant.ResourceLocal {
runtime := &model.Runtime{
Name: create.Name,
Resource: create.Resource,
Type: create.Type,
Version: create.Version,
Status: constant.StatusNormal,
Remark: create.Remark,
}
return nil, runtimeRepo.Create(context.Background(), runtime)
}
exist, _ = runtimeRepo.GetFirst(context.Background(), runtimeRepo.WithImage(create.Image))
if exist != nil {
return nil, buserr.New("ErrImageExist")
@@ -160,11 +211,6 @@ func (r *RuntimeService) Create(create request.RuntimeCreate) (*model.Runtime, e
}
appVersionDir := filepath.Join(app.GetAppResourcePath(), appDetail.Version)
if !fileOp.Stat(appVersionDir) {
if err = downloadApp(app, appDetail, nil, nil); err != nil {
return nil, err
}
}
runtime := &model.Runtime{
Name: create.Name,
@@ -176,24 +222,92 @@ func (r *RuntimeService) Create(create request.RuntimeCreate) (*model.Runtime, e
ContainerName: containerName.(string),
Port: strings.Join(hostPorts, ","),
Remark: create.Remark,
}
switch create.Type {
case constant.RuntimePHP:
if err = handlePHP(create, runtime, fileOp, appVersionDir); err != nil {
return nil, err
}
case constant.RuntimeNode, constant.RuntimeJava, constant.RuntimeGo, constant.RuntimePython, constant.RuntimeDotNet:
if err = handleRuntime(create, runtime, fileOp, appVersionDir); err != nil {
return nil, err
}
Status: runtimeCreateInitialStatus(create),
}
if err := runtimeRepo.Create(context.Background(), runtime); err != nil {
return nil, err
}
if err := startRuntimeCreateTask(create, runtime, app, appDetail, appVersionDir); err != nil {
runtime.Status = constant.StatusError
runtime.Message = err.Error()
_ = runtimeRepo.Save(runtime)
return nil, err
}
return runtime, nil
}
func startRuntimeCreateTask(create request.RuntimeCreate, runtime *model.Runtime, app model.App, appDetail model.AppDetail, appVersionDir string) error {
meta := buildRuntimeCreateTaskMeta(create, runtime.ID)
createTask, err := task.NewTaskWithOps(meta.resourceName, meta.operate, meta.scope, meta.taskID, meta.resourceID)
if err != nil {
return err
}
createTask.AddSubTask(task.GetTaskName(create.Name, task.TaskCreate, task.TaskScopeRuntime), func(t *task.Task) error {
return executeRuntimeCreateTask(create, runtime, app, appDetail, appVersionDir, t)
}, nil)
go func() {
_ = createTask.Execute()
}()
return nil
}
func executeRuntimeCreateTask(create request.RuntimeCreate, runtime *model.Runtime, app model.App, appDetail model.AppDetail, appVersionDir string, taskItem *task.Task) error {
if create.Type == constant.RuntimePHP && create.Resource == constant.ResourceLocal {
runtime.Status = constant.StatusNormal
runtime.Message = ""
return runtimeRepo.Save(runtime)
}
if err := downloadApp(app, appDetail, nil, taskItem.Logger); err != nil {
return markRuntimeCreateFailed(runtime, err)
}
go func() {
RequestDownloadCallBack(appDetail.DownloadCallBackUrl)
}()
fileOp := files.NewFileOp()
var err error
switch create.Type {
case constant.RuntimePHP:
err = handlePHP(create, runtime, fileOp, appVersionDir)
case constant.RuntimeNode, constant.RuntimeJava, constant.RuntimeGo, constant.RuntimePython, constant.RuntimeDotNet:
err = handleRuntime(create, runtime, fileOp, appVersionDir)
}
if err != nil {
return markRuntimeCreateFailed(runtime, err)
}
if err = runtimeRepo.Save(runtime); err != nil {
return err
}
switch create.Type {
case constant.RuntimePHP:
return buildRuntimeWithResult(runtime, "", "", false)
case constant.RuntimeNode, constant.RuntimeJava, constant.RuntimeGo, constant.RuntimePython, constant.RuntimeDotNet:
if err := pullRuntimeImagesBeforeStart(create, runtime, taskItem); err != nil {
return markRuntimeCreateFailed(runtime, err)
}
return startRuntimeWithResult(runtime)
}
return nil
}
func pullRuntimeImagesBeforeStart(create request.RuntimeCreate, runtime *model.Runtime, taskItem *task.Task) error {
switch create.Type {
case constant.RuntimeNode, constant.RuntimeJava, constant.RuntimeGo, constant.RuntimePython, constant.RuntimeDotNet:
return pullRuntimeComposeImages(runtime.GetComposePath(), false, taskItem)
default:
return nil
}
}
func markRuntimeCreateFailed(runtime *model.Runtime, err error) error {
runtime.Status = constant.StatusError
runtime.Message = err.Error()
_ = runtimeRepo.Save(runtime)
return err
}
func (r *RuntimeService) Page(req request.RuntimeSearch) (int64, []response.RuntimeDTO, error) {
var (
opts []repo.DBOption
@@ -272,31 +386,37 @@ func (r *RuntimeService) Delete(runtimeDelete request.RuntimeDelete) error {
if website.ID > 0 {
return buserr.New("ErrDelWithWebsite")
}
return startRuntimeDeleteTask(runtimeDelete, runtime)
}
func startRuntimeDeleteTask(runtimeDelete request.RuntimeDelete, runtime *model.Runtime) error {
meta := buildRuntimeDeleteTaskMeta(runtimeDelete, runtime)
deleteTask, err := task.NewTaskWithOps(meta.resourceName, meta.operate, meta.scope, meta.taskID, meta.resourceID)
if err != nil {
return err
}
deleteTask.AddSubTask(task.GetTaskName(runtime.Name, task.TaskDelete, task.TaskScopeRuntime), func(t *task.Task) error {
return executeRuntimeDeleteTask(runtimeDelete, runtime, t)
}, nil)
go func() {
_ = deleteTask.Execute()
}()
return nil
}
func executeRuntimeDeleteTask(runtimeDelete request.RuntimeDelete, runtime *model.Runtime, taskItem *task.Task) error {
if runtime.Resource != constant.ResourceAppstore {
if runtimeDelete.DeleteImage {
deleteRuntimeImages(runtime, taskItem)
}
return runtimeRepo.DeleteBy(repo.WithByID(runtimeDelete.ID))
}
projectDir := runtime.GetPath()
if out, err := compose.Down(runtime.GetComposePath()); err != nil && !runtimeDelete.ForceDelete {
if out != "" {
return errors.New(out)
}
if err := stopRuntimeBeforeDelete(runtime, runtimeDelete.ForceDelete, taskItem); err != nil {
return err
}
if runtime.Type == constant.RuntimePHP {
client, err := docker.NewClient()
if err != nil {
return err
}
defer client.Close()
imageID, err := client.GetImageIDByName(runtime.Image)
if err != nil {
return err
}
if imageID != "" {
if err := client.DeleteImage(imageID); err != nil {
global.LOG.Errorf("delete image id [%s] error %v", imageID, err)
}
}
if runtimeDelete.DeleteImage {
deleteRuntimeImages(runtime, taskItem)
}
if err := files.NewFileOp().DeleteDir(projectDir); err != nil && !runtimeDelete.ForceDelete {
return err
@@ -304,6 +424,121 @@ func (r *RuntimeService) Delete(runtimeDelete request.RuntimeDelete) error {
return runtimeRepo.DeleteBy(repo.WithByID(runtimeDelete.ID))
}
func getRuntimeStopLog() string {
logStr := i18n.GetMsgByKey("Stop") + i18n.GetMsgByKey("Runtime")
if strings.TrimSpace(logStr) == "" {
return "StopRuntime"
}
return logStr
}
func stopRuntimeBeforeDelete(runtime *model.Runtime, forceDelete bool, taskItem *task.Task) error {
logStr := getRuntimeStopLog()
if taskItem != nil {
taskItem.Log(logStr)
}
out, err := downRuntimeCompose(runtime.GetComposePath())
if err != nil && !forceDelete {
if out != "" {
err = errors.New(out)
}
if taskItem != nil {
taskItem.LogFailedWithErr(logStr, err)
}
return err
}
if taskItem != nil {
taskItem.LogSuccess(logStr)
}
return nil
}
func getRuntimeDeleteImages(runtime *model.Runtime) ([]string, error) {
var images []string
imageMap := make(map[string]struct{})
appendImage := func(image string) {
image = strings.TrimSpace(image)
if image == "" {
return
}
if _, ok := imageMap[image]; ok {
return
}
imageMap[image] = struct{}{}
images = append(images, image)
}
appendImage(runtime.Image)
if runtime.DockerCompose != "" {
composeImages, err := docker.GetImagesFromDockerCompose([]byte(runtime.Env), []byte(runtime.DockerCompose))
if err != nil {
return nil, err
}
for _, image := range composeImages {
appendImage(image)
}
}
return images, nil
}
func deleteRuntimeImages(runtime *model.Runtime, taskItem *task.Task) {
logPrefix := i18n.GetMsgByKey("TaskDelete") + i18n.GetMsgByKey("Image")
images, err := getRuntimeDeleteImages(runtime)
if err != nil {
global.LOG.Errorf("get runtime [%s] delete images error %v", runtime.Name, err)
if taskItem != nil {
taskItem.LogFailedWithErr(logPrefix, err)
}
return
}
if len(images) == 0 {
if taskItem != nil {
taskItem.LogFailedWithErr(logPrefix, errors.New(i18n.GetWithName("ErrImageNotExist", runtime.Name)))
}
return
}
client, err := docker.NewClient()
if err != nil {
global.LOG.Errorf("delete runtime images [%s] error %v", runtime.Name, err)
if taskItem != nil {
taskItem.LogFailedWithErr(logPrefix, err)
}
return
}
defer client.Close()
for _, imageName := range images {
logStr := logPrefix + imageName
if taskItem != nil {
taskItem.Log(logStr)
}
imageID, err := client.GetImageIDByName(imageName)
if err != nil {
global.LOG.Errorf("get runtime image [%s] error %v", imageName, err)
if taskItem != nil {
taskItem.LogFailedWithErr(logStr, err)
}
continue
}
if imageID == "" {
if taskItem != nil {
taskItem.LogFailedWithErr(logStr, errors.New(i18n.GetWithName("ErrImageNotExist", imageName)))
}
continue
}
if err := client.DeleteImage(imageID); err != nil {
global.LOG.Errorf("delete image id [%s] error %v", imageID, err)
if taskItem != nil {
taskItem.LogFailedWithErr(logStr, err)
}
continue
}
if taskItem != nil {
taskItem.LogSuccess(logStr)
}
}
}
func (r *RuntimeService) Get(id uint) (*response.RuntimeDTO, error) {
runtime, err := runtimeRepo.GetFirst(context.Background(), repo.WithByID(id))
if err != nil {
+30 -36
View File
@@ -65,17 +65,6 @@ func handleRuntime(create request.RuntimeCreate, runtime *model.Runtime, fileOp
runtime.Env = string(envContent)
runtime.Status = constant.StatusCreating
runtime.CodeDir = create.CodeDir
nodeDetail, err := appDetailRepo.GetFirst(repo.WithByID(runtime.AppDetailID))
if err != nil {
return err
}
go func() {
RequestDownloadCallBack(nodeDetail.DownloadCallBackUrl)
}()
go startRuntime(runtime)
return
}
@@ -129,32 +118,28 @@ func handlePHP(create request.RuntimeCreate, runtime *model.Runtime, fileOp file
runtime.Env = string(envContent)
runtime.Params = string(forms)
runtime.Status = constant.StatusBuilding
go func() {
appDetail, err := appDetailRepo.GetFirst(repo.WithByID(runtime.AppDetailID))
if err == nil {
RequestDownloadCallBack(appDetail.DownloadCallBackUrl)
}
}()
go buildRuntime(runtime, "", "", false)
return
}
func startRuntime(runtime *model.Runtime) {
_ = startRuntimeWithResult(runtime)
}
func startRuntimeWithResult(runtime *model.Runtime) error {
if err := runComposeCmdWithLog("up", runtime.GetComposePath(), runtime.GetLogPath()); err != nil {
runtime.Status = constant.StatusError
runtime.Message = err.Error()
_ = runtimeRepo.Save(runtime)
return
return err
}
if err := SyncRuntimeContainerStatus(runtime); err != nil {
runtime.Status = constant.StatusError
runtime.Message = err.Error()
_ = runtimeRepo.Save(runtime)
return
return err
}
return nil
}
func reCreateRuntime(runtime *model.Runtime) {
@@ -326,6 +311,10 @@ func deleteImageByID(oldImageID, imageName string, client docker.Client) {
}
func buildRuntime(runtime *model.Runtime, oldImageID string, oldEnv string, rebuild bool) {
_ = buildRuntimeWithResult(runtime, oldImageID, oldEnv, rebuild)
}
func buildRuntimeWithResult(runtime *model.Runtime, oldImageID string, oldEnv string, rebuild bool) error {
runtimePath := runtime.GetPath()
composePath := runtime.GetComposePath()
logPath := path.Join(runtimePath, "build.log")
@@ -333,11 +322,17 @@ func buildRuntime(runtime *model.Runtime, oldImageID string, oldEnv string, rebu
logFile, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, constant.FilePerm)
if err != nil {
global.LOG.Errorf("failed to open log file: %v", err)
return
runtime.Status = constant.StatusError
runtime.Message = err.Error()
_ = runtimeRepo.Save(runtime)
return err
}
defer func() {
_ = logFile.Close()
}()
defer func() {
_ = runtimeRepo.Save(runtime)
}()
newPHPVersion := getRuntimeEnv(runtime.Env, "PHP_VERSION")
oldPHPVersion := getRuntimeEnv(oldEnv, "PHP_VERSION")
@@ -369,16 +364,19 @@ func buildRuntime(runtime *model.Runtime, oldImageID string, oldEnv string, rebu
} else {
runtime.Message = buserr.New("ErrImageBuildErr").Error() + ":" + stderrBuf.String()
}
_ = runtimeRepo.Save(runtime)
return
return err
}
if err = runComposeCmdWithLog(constant.RuntimeDown, runtime.GetComposePath(), runtime.GetLogPath()); err != nil {
return
runtime.Status = constant.StatusError
runtime.Message = err.Error()
return err
}
client, err := docker.NewClient()
if err != nil {
_, _ = logFile.WriteString(fmt.Sprintf("failed to connect to docker client: %v", err))
return
runtime.Status = constant.StatusError
runtime.Message = err.Error()
return err
}
runtime.Message = ""
if rebuild && runtime.ID > 0 {
@@ -404,14 +402,10 @@ func buildRuntime(runtime *model.Runtime, oldImageID string, oldEnv string, rebu
}
}
defer func() {
_ = runtimeRepo.Save(runtime)
}()
if out, err := compose.Up(composePath); err != nil {
runtime.Status = constant.StatusStartErr
runtime.Message = out
return
return err
}
deleteImageID := ""
extensions := getRuntimeEnv(runtime.Env, "PHP_EXTENSIONS")
@@ -421,14 +415,14 @@ func buildRuntime(runtime *model.Runtime, oldImageID string, oldEnv string, rebu
if err = cmdMgr.Run("docker", "exec", "-i", runtime.ContainerName, "install-ext", extensions); err != nil {
runtime.Status = constant.StatusError
runtime.Message = buserr.New("ErrImageBuildErr").Error() + ":" + err.Error()
return
return err
}
commitMgr := cmd2.NewCommandMgr(cmd2.WithTimeout(10*time.Minute), cmd2.WithOutputFile(logPath))
err = commitMgr.Run("docker", "commit", runtime.ContainerName, runtime.Image)
if err != nil {
runtime.Status = constant.StatusError
runtime.Message = buserr.New("ErrImageBuildErr").Error() + ":" + err.Error()
return
return err
}
}
if oldImageID != "" {
@@ -441,10 +435,10 @@ func buildRuntime(runtime *model.Runtime, oldImageID string, oldEnv string, rebu
if out, err := compose.DownAndUp(composePath); err != nil {
runtime.Status = constant.StatusStartErr
runtime.Message = out
return
return err
}
runtime.Status = constant.StatusRunning
_ = runtimeRepo.Save(runtime)
return nil
}
func handleParams(create request.RuntimeCreate, projectDir string) (composeContent []byte, envContent []byte, forms []byte, err error) {
+1 -1
View File
@@ -610,4 +610,4 @@ ErrAIProxyModelMapInvalid: 'Model mapping must be a valid JSON object: {{ .err }
ErrAIProxyModelMapEmpty: 'Model mapping cannot be empty'
ErrAIProxyModelMapEmptyExternalModel: 'Model mapping contains an empty request model'
ErrAIProxyModelMapEmptyUpstreamModel: 'Upstream model for {{ .model }} cannot be empty'
AIProxyUserFallback: 'User {{ .id }}'
AIProxyUserFallback: 'Deleted user (ID: {{ .id }})'
+1 -1
View File
@@ -72,7 +72,7 @@ ErrAIProxyModelMapInvalid: 'El mapeo de modelos debe ser un objeto JSON válido:
ErrAIProxyModelMapEmpty: 'El mapeo de modelos no puede estar vacío'
ErrAIProxyModelMapEmptyExternalModel: 'El mapeo de modelos contiene un modelo solicitado vacío'
ErrAIProxyModelMapEmptyUpstreamModel: 'El modelo upstream de {{ .model }} no puede estar vacío'
AIProxyUserFallback: 'Usuario {{ .id }}'
AIProxyUserFallback: 'Usuario eliminado (ID: {{ .id }})'
Localhost: 'Máquina local'
ErrBackupInUsed: 'Cuenta de respaldo en uso por tarea programada'
ErrBackupCheck: 'Conexión de respaldo falló: {{ .err }}'
+1 -1
View File
@@ -72,7 +72,7 @@ ErrAIProxyModelMapInvalid: 'モデルマッピングは有効な JSON オブジ
ErrAIProxyModelMapEmpty: 'モデルマッピングは空にできません'
ErrAIProxyModelMapEmptyExternalModel: 'モデルマッピングに空のリクエストモデルがあります'
ErrAIProxyModelMapEmptyUpstreamModel: '{{ .model }} の上流モデルは空にできません'
AIProxyUserFallback: 'ユーザー {{ .id }}'
AIProxyUserFallback: '削除済みユーザー (ID: {{ .id }})'
Localhost: 'ローカルマシン'
ErrBackupInUsed: 'バックアップアカウントがスケジュールで使用中'
ErrBackupCheck: '接続テストに失敗しました: {{ .err }}'
+1 -1
View File
@@ -72,7 +72,7 @@ ErrAIProxyModelMapInvalid: '모델 매핑은 유효한 JSON 객체여야 합니
ErrAIProxyModelMapEmpty: '모델 매핑은 비워 둘 수 없습니다'
ErrAIProxyModelMapEmptyExternalModel: '모델 매핑에 빈 요청 모델이 있습니다'
ErrAIProxyModelMapEmptyUpstreamModel: '{{ .model }}의 업스트림 모델은 비워 둘 수 없습니다'
AIProxyUserFallback: '사용자 {{ .id }}'
AIProxyUserFallback: '삭제된 사용자 (ID: {{ .id }})'
Localhost: '로컬 머신'
ErrBackupInUsed: '백업 계정이 예약에 사용 중'
ErrBackupCheck: '연결 테스트 실패: {{ .err }}'
+1 -1
View File
@@ -72,7 +72,7 @@ ErrAIProxyModelMapInvalid: 'Pemetaan model mestilah objek JSON yang sah: {{ .err
ErrAIProxyModelMapEmpty: 'Pemetaan model tidak boleh kosong'
ErrAIProxyModelMapEmptyExternalModel: 'Pemetaan model mengandungi model permintaan kosong'
ErrAIProxyModelMapEmptyUpstreamModel: 'Model upstream untuk {{ .model }} tidak boleh kosong'
AIProxyUserFallback: 'Pengguna {{ .id }}'
AIProxyUserFallback: 'Pengguna dipadam (ID: {{ .id }})'
Localhost: 'Mesin Tempatan'
ErrBackupInUsed: 'Akaun sandaran sedang digunakan oleh tugas'
ErrBackupCheck: 'Ujian sambungan gagal: {{ .err }}'
+1 -1
View File
@@ -72,7 +72,7 @@ ErrAIProxyModelMapInvalid: 'O mapeamento de modelos deve ser um objeto JSON vál
ErrAIProxyModelMapEmpty: 'O mapeamento de modelos não pode estar vazio'
ErrAIProxyModelMapEmptyExternalModel: 'O mapeamento de modelos contém um modelo solicitado vazio'
ErrAIProxyModelMapEmptyUpstreamModel: 'O modelo upstream de {{ .model }} não pode estar vazio'
AIProxyUserFallback: 'Usuário {{ .id }}'
AIProxyUserFallback: 'Usuário excluído (ID: {{ .id }})'
Localhost: 'Máquina Local'
ErrBackupInUsed: 'Conta de backup em uso por tarefa'
ErrBackupCheck: 'Teste de conexão falhou: {{ .err }}'
+1 -1
View File
@@ -72,7 +72,7 @@ ErrAIProxyModelMapInvalid: 'Сопоставление моделей должн
ErrAIProxyModelMapEmpty: 'Сопоставление моделей не может быть пустым'
ErrAIProxyModelMapEmptyExternalModel: 'Сопоставление моделей содержит пустую запрошенную модель'
ErrAIProxyModelMapEmptyUpstreamModel: 'Upstream-модель для {{ .model }} не может быть пустой'
AIProxyUserFallback: 'Пользователь {{ .id }}'
AIProxyUserFallback: 'Удаленный пользователь (ID: {{ .id }})'
Localhost: 'Локальная машина'
ErrBackupInUsed: 'Аккаунт бэкапа занят задачей'
ErrBackupCheck: 'Проверка подключения не удалась: {{ .err }}'
+1 -1
View File
@@ -72,7 +72,7 @@ ErrAIProxyModelMapInvalid: 'Model eşlemesi geçerli bir JSON nesnesi olmalıdı
ErrAIProxyModelMapEmpty: 'Model eşlemesi boş olamaz'
ErrAIProxyModelMapEmptyExternalModel: 'Model eşlemesi boş bir istek modeli içeriyor'
ErrAIProxyModelMapEmptyUpstreamModel: '{{ .model }} için upstream model boş olamaz'
AIProxyUserFallback: 'Kullanıcı {{ .id }}'
AIProxyUserFallback: 'Silinen kullanıcı (ID: {{ .id }})'
Localhost: 'Yerel Makine'
ErrBackupInUsed: 'Yedek hesabı görevde kullanılıyor'
ErrBackupCheck: 'Bağlantı testi başarısız: {{ .err }}'
+1 -1
View File
@@ -72,7 +72,7 @@ ErrAIProxyModelMapInvalid: '模型映射必須是合法的 JSON 物件:{{ .err
ErrAIProxyModelMapEmpty: '模型映射不能為空'
ErrAIProxyModelMapEmptyExternalModel: '模型映射中存在空的請求模型'
ErrAIProxyModelMapEmptyUpstreamModel: '模型 {{ .model }} 的上游模型不能為空'
AIProxyUserFallback: '使用者 {{ .id }}'
AIProxyUserFallback: '已刪除使用者 (ID: {{ .id }})'
Localhost: '本機'
ErrBackupInUsed: '此備份帳號已在排程任務中使用,無法刪除'
ErrBackupCheck: '備份帳號測試連線失敗{{ .err }}'
+1 -1
View File
@@ -610,4 +610,4 @@ ErrAIProxyModelMapInvalid: "模型映射必须是合法的 JSON 对象:{{ .err
ErrAIProxyModelMapEmpty: "模型映射不能为空"
ErrAIProxyModelMapEmptyExternalModel: "模型映射中存在空的请求模型"
ErrAIProxyModelMapEmptyUpstreamModel: "模型 {{ .model }} 的上游模型不能为空"
AIProxyUserFallback: "用户 {{ .id }}"
AIProxyUserFallback: "已删除用户 (ID: {{ .id }})"
+5 -1
View File
@@ -49,7 +49,7 @@ func Up(filePath string) (string, 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
}
base, extra := getComposeBaseCmd()
@@ -58,6 +58,10 @@ func UpWithTask(filePath string, task *task.Task, forcePull bool) error {
return cmd.NewCommandMgr(cmd.WithTask(*task), cmd.WithTimeout(20*time.Minute)).Run(base, args...)
}
func PullComposeImages(filePath string, forcePull bool, task *task.Task) error {
return pullComposeImages(filePath, forcePull, task)
}
func pullComposeImages(filePath string, forcePull bool, task *task.Task) error {
images, err := GetComposeImages(filePath)
if err != nil {
+3
View File
@@ -60,6 +60,7 @@ export namespace Runtime {
source?: string;
codeDir?: string;
port?: number;
taskID?: string;
exposedPorts?: ExposedPort[];
environments?: Environment[];
volumes?: Volume[];
@@ -103,6 +104,8 @@ export namespace Runtime {
export interface RuntimeDelete {
id: number;
forceDelete: boolean;
deleteImage?: boolean;
taskID?: string;
}
export interface RuntimeOperate {
+15 -69
View File
@@ -681,47 +681,21 @@ const message = {
account: 'Model Account',
batchOperation: 'Batch Operation',
operationType: 'Operation Type',
batchInstall: 'Batch Install',
batchUpgrade: 'Batch Upgrade',
batchSkillInstall: 'Batch Distribute Skill',
batchStart: 'Batch Start',
batchStop: 'Batch Stop',
batchRestart: 'Batch Restart',
batchDelete: 'Batch Delete',
batchInstallAgent: 'Batch install agent',
dispatchAgentInstallTasks: 'Dispatch agent install tasks',
batchUpgradeAgent: 'Batch upgrade agent',
dispatchAgentUpgradeTasks: 'Dispatch agent upgrade tasks',
batchInstallAgentSkill: 'Batch distribute Skill',
dispatchAgentSkillInstallTasks: 'Dispatch Skill install tasks',
batchStartAgent: 'Batch start agent',
dispatchAgentStartTasks: 'Dispatch agent start tasks',
batchStopAgent: 'Batch stop agent',
dispatchAgentStopTasks: 'Dispatch agent stop tasks',
batchRestartAgent: 'Batch restart agent',
dispatchAgentRestartTasks: 'Dispatch agent restart tasks',
batchDeleteAgent: 'Batch delete agent',
dispatchAgentDeleteTasks: 'Dispatch agent delete tasks',
batchAction: 'Batch {0}',
installSkillAction: 'Distribute Skill',
batchAgentTask: 'Batch {0} agent',
dispatchAgentTask: 'Dispatch agent {0} tasks',
dispatchTask: 'Dispatch {0} tasks',
taskSubmitted: '{0} task has been submitted',
allNodes: 'All Nodes',
targetVersion: 'Target Version',
skill: 'Skill',
skillSource: 'Skill Source',
skillKeyword: 'Skill Keyword',
clawHubSkillPlaceholder: 'Search and select a Skill first',
batchInstallTaskSubmitted: 'Batch install task has been submitted',
batchUpgradeTaskSubmitted: 'Batch upgrade task has been submitted',
batchSkillInstallTaskSubmitted: 'Batch Skill distribution task has been submitted',
batchStartTaskSubmitted: 'Batch start task has been submitted',
batchStopTaskSubmitted: 'Batch stop task has been submitted',
batchRestartTaskSubmitted: 'Batch restart task has been submitted',
batchDeleteTaskSubmitted: 'Batch delete task has been submitted',
noAccountHint: 'Choose an existing model account or add a new one.',
accountCount: '{0} model accounts',
syncAgents: 'Sync related agents',
syncAgentsHelper: 'Update openclaw.json for agents using this model account',
openclawType: 'OpenClaw',
copawType: 'QwenPaw',
hermesType: 'Hermes Agent',
appVersion: 'App Version',
webuiPort: 'WebUI Port',
allowedOrigins: 'Access Addresses',
@@ -738,7 +712,6 @@ const message = {
fallbackModelsEmpty: 'No fallback models configured',
modelInputTypes: 'Input Types',
reasoning: 'Reasoning Model',
manualModel: 'Manual input',
verified: 'Verified',
verifySkipped: 'No verification',
skillsTab: 'Skills',
@@ -765,7 +738,6 @@ const message = {
skillsMarketSourceOfficial: 'Official',
versionUnsupportedTitle: 'This feature is not supported in the current version',
versionUnsupportedHelper: 'Please upgrade OpenClaw to version {0} or later.',
skillsStatusDisabled: 'Disabled',
skillsGroupBuiltIn: 'Built-in',
skillsGroupExternal: 'External',
skillsGroupWorkspace: 'Workspace',
@@ -802,7 +774,6 @@ const message = {
'Delete it after the ritual is complete.',
],
},
bindings: 'Bindings',
duplicateBinding: 'The channel and account ID combination must be unique',
accountIdOptional: 'Account ID (Optional)',
saveAllMd: 'Save All',
@@ -829,7 +800,6 @@ const message = {
hermesChatDeleteConfirm: 'Delete session {0}?',
hermesChatDeleteSuccess: 'Session deleted',
weixin: 'Weixin',
qq: 'QQ',
wecom: 'WeCom',
dingtalk: 'DingTalk',
feishu: 'Feishu',
@@ -850,16 +820,14 @@ const message = {
accountId: 'Account ID',
accountIdPlaceholder: 'A unique ID used to distinguish bots and for later config and routing.',
setDefaultBot: 'Set as Default',
botDuplicateAccountId: 'Account ID already exists',
botDuplicateField: '{field} already exists',
botRequired: 'Add at least one bot',
botId: 'Bot ID',
allowFrom: 'DM Allowlist',
allowFromHelper: 'One sender ID per line. Used only when DM Policy is Allowlist.',
allowFromPlaceholder: 'One sender ID per line',
allowlistPolicyHelper: '{0}. Used only when {1} is Allowlist.',
systemPrompt: 'System Prompt',
groupAllowFrom: 'Group Allowlist',
groupAllowFromHelper: 'One group ID per line. Used only when Group Policy is Allowlist.',
groupAllowFromPlaceholder: 'One group ID per line',
separateSessionByConversation: 'Separate Session By Conversation',
groupSessionScope: 'Group Session Scope',
@@ -875,25 +843,22 @@ const message = {
streamingBlock: 'Blocking',
streamingProgress: 'Progress',
allowFromRequired: 'Enter at least one allowlist entry',
saveAndRestartGateway: 'Save and restart gateway',
pairingCode: 'Pairing Code',
pairingCodePlaceholder: 'Enter pairing code',
approvePairing: 'Approve Pairing',
saveSuccess: 'Saved successfully',
saveAndRestartSuccess: 'Saved successfully. The container is restarting automatically.',
successAndRestart: '{0}. The container is restarting automatically.',
pairingApproveSuccess: 'Pairing approved successfully',
scanConnect: 'Scan to Connect',
scanConnectHelper:
'Click to start the QR login task. The QR code will appear in the task log, and the container will restart automatically after the scan succeeds.',
channelAutoRestartHelper: 'Saving will automatically restart the container so the changes take effect.',
channelDeleteConfirm: 'Delete the {0} channel configuration?',
deleteAndRestartSuccess: 'Deleted successfully. The container is restarting automatically.',
customProviderHelper: 'Custom model providers do not validate whether the account is available.',
},
model: {
model: 'Models',
localModel: 'Local Models',
create: 'Add Model',
create_helper: 'Pull "{0}"',
ollama_doc: 'You can visit the Ollama official website to search and find more models.',
container_conn_helper: 'Use this address for inter-container access or connection',
@@ -911,14 +876,12 @@ const message = {
manualDownload: 'Manual Download',
modelSource: 'Model source',
repoID: 'Repository ID',
modelScopeEndpoint: 'ModelScope endpoint',
modelScopeToken: 'ModelScope Token (optional)',
hfToken: 'HF Token (optional)',
hfEndpoint: 'HuggingFace acceleration endpoint',
endpointLabel: '{0} endpoint',
acceleratedEndpointLabel: '{0} acceleration endpoint',
tokenOptionalLabel: '{0} Token (optional)',
searchSource: 'Search {0}',
hfEndpointHelper:
'Configure an acceleration endpoint when HuggingFace access is unstable. Search, details, and downloads will use it.',
searchModelScope: 'Search ModelScope',
searchHuggingFace: 'Search HuggingFace',
sortTrending: 'Trending',
sortLikes: 'Most liked',
sortDownloads: 'Most downloaded',
@@ -930,7 +893,6 @@ const message = {
progress: 'Progress',
localDownloaded: 'Downloaded',
modelInfo: 'Model Details',
modelCard: 'Model Card',
downloading: 'Downloading',
canceled: 'Canceled',
downloadQueued: 'Added to the download queue',
@@ -962,7 +924,6 @@ const message = {
failureCount: 'Failures',
lastError: 'Last Error',
modelMap: 'Model Mapping',
apiKeyReset: 'Reset API Key (leave empty to keep unchanged)',
qpsLimit: 'QPS Limit',
tokenLimit: 'Token Limit',
tokenUsed: 'Used Tokens',
@@ -986,7 +947,6 @@ const message = {
lbPolicyFailover: 'Failover',
lbPolicyFailoverDesc:
'Use the highest-priority model account first, then switch to the next available account after failure or cooldown.',
productionProtection: 'Production Protection',
maxConcurrency: 'Max Concurrency',
queueSize: 'Queue Size',
queueTimeoutSeconds: 'Queue Wait Timeout (s)',
@@ -994,16 +954,10 @@ const message = {
streamIdleTimeoutSeconds: 'Stream Idle Timeout (s)',
maxBodyMb: 'Max Body Size (MB)',
runtimeRefreshSeconds: 'Runtime Refresh Interval (s)',
logRetention: 'Log Retention',
usageRetentionDays: 'Usage Statistics Retention (days)',
contentAuditRetentionDays: 'Content Compliance Audit Retention (days)',
logCleanupIntervalHours: 'Log Cleanup Interval (hours)',
requestBodyLog: 'Request Body Log',
requestBodyLogEsEndpoint: 'Elasticsearch Endpoint',
requestBodyLogEsAuthMethod: 'Elasticsearch Authentication',
requestBodyLogEsUsername: 'Elasticsearch Username',
requestBodyLogEsPassword: 'Elasticsearch Password',
requestBodyLogEsApiKey: 'Elasticsearch API Key',
requestBodyLogIndexPrefix: 'Index Prefix',
requestBodyLogRetentionDays: 'Request Body Log Retention (days)',
requestBodyLogMaxBodyKb: 'Max Request Body Size (KB)',
@@ -1028,11 +982,9 @@ const message = {
esLogCircuitOpen: 'Circuit Open',
esLogCircuitUntil: 'ES Circuit Until',
serviceOperateConfirm: 'Confirm to {0} the AI Gateway service?',
deleteBackendConfirm: 'Delete model account {0}?',
deleteTargetConfirm: 'Delete {0} {1}?',
deleteBackendTitle: 'Delete Model Account',
deleteUserConfirm: 'Delete API Key {0}?',
deleteGroupConfirm: 'Delete user group {0}?',
userFallback: 'User {0}',
userFallback: 'Deleted user (ID: {0})',
requestModel: 'Request Model',
upstreamModel: 'Upstream Model',
requestModelPlaceholder: 'e.g. qwen2.5-coder',
@@ -1041,10 +993,8 @@ const message = {
overview: 'Overview',
distribution: 'Distribution',
usageTrend: 'Usage Trend',
providerDistribution: 'Provider Distribution',
distributionBy: '{0} Distribution',
unmatched: 'Unmatched',
modelDistribution: 'Model Distribution',
accountDistribution: 'Model Account Distribution',
modelAccount: 'Model Account',
serviceProvider: 'Provider',
tokenUsage: 'Token Usage',
@@ -1053,8 +1003,6 @@ const message = {
rank: 'Rank',
promptToken: 'Prompt Tokens',
completionToken: 'Completion Tokens',
inputTokens: 'Input Tokens',
outputTokens: 'Output Tokens',
totalToken: 'Total Tokens',
cachedToken: 'Cached Tokens',
cacheHitRate: 'Cache Hit Rate',
@@ -1082,7 +1030,6 @@ const message = {
modelGroupModels: 'Request Models',
modelGroupModelsPlaceholder: 'Select or enter request model names',
modelGroupModelCount: '{0} models',
deleteModelGroupConfirm: 'Delete model group {0}?',
contentCompliance: 'Content Compliance',
contentAction: 'Action',
actionBlock: 'Block',
@@ -1238,7 +1185,6 @@ const message = {
},
benchmark: {
title: 'Benchmark',
create: 'Create',
launchCommand: 'Launch Command',
retest: 'Retest',
statusRunning: 'Running',
+15 -82
View File
@@ -687,47 +687,21 @@ const message = {
account: 'Cuenta de modelo',
batchOperation: 'Operación por lotes',
operationType: 'Tipo de operación',
batchInstall: 'Instalación por lotes',
batchUpgrade: 'Actualización por lotes',
batchSkillInstall: 'Distribuir Skill por lotes',
batchStart: 'Inicio por lotes',
batchStop: 'Detención por lotes',
batchRestart: 'Reinicio por lotes',
batchDelete: 'Eliminación por lotes',
batchInstallAgent: 'Instalación masiva de agentes',
dispatchAgentInstallTasks: 'Enviar tareas de instalación de agentes',
batchUpgradeAgent: 'Actualización masiva de agentes',
dispatchAgentUpgradeTasks: 'Enviar tareas de actualización de agentes',
batchInstallAgentSkill: 'Distribuir Skill por lotes',
dispatchAgentSkillInstallTasks: 'Enviar tareas de instalación de Skill',
batchStartAgent: 'Inicio masivo de agentes',
dispatchAgentStartTasks: 'Enviar tareas de inicio de agentes',
batchStopAgent: 'Detención masiva de agentes',
dispatchAgentStopTasks: 'Enviar tareas de detención de agentes',
batchRestartAgent: 'Reinicio masivo de agentes',
dispatchAgentRestartTasks: 'Enviar tareas de reinicio de agentes',
batchDeleteAgent: 'Eliminación masiva de agentes',
dispatchAgentDeleteTasks: 'Enviar tareas de eliminación de agentes',
batchAction: '{0} por lotes',
installSkillAction: 'Distribuir Skill',
batchAgentTask: '{0} agentes por lotes',
dispatchAgentTask: 'Enviar tareas para {0} agentes',
dispatchTask: 'Enviar tareas de {0}',
taskSubmitted: 'Tarea de {0} enviada',
allNodes: 'Todos los nodos',
targetVersion: 'Versión de destino',
skill: 'Skill',
skillSource: 'Origen de Skill',
skillKeyword: 'Palabra clave de Skill',
clawHubSkillPlaceholder: 'Busque y seleccione una Skill primero',
batchInstallTaskSubmitted: 'Tarea de instalación por lotes enviada',
batchUpgradeTaskSubmitted: 'Tarea de actualización por lotes enviada',
batchSkillInstallTaskSubmitted: 'Tarea de distribución de Skill por lotes enviada',
batchStartTaskSubmitted: 'Tarea de inicio por lotes enviada',
batchStopTaskSubmitted: 'Tarea de detención por lotes enviada',
batchRestartTaskSubmitted: 'Tarea de reinicio por lotes enviada',
batchDeleteTaskSubmitted: 'Tarea de eliminación por lotes enviada',
noAccountHint: 'Selecciona una cuenta de modelo existente o agrega una nueva.',
accountCount: '{0} cuentas de modelo',
syncAgents: 'Sincronizar agentes vinculados',
syncAgentsHelper: 'Actualiza openclaw.json para los agentes que usan esta cuenta de modelo',
openclawType: 'OpenClaw',
copawType: 'QwenPaw',
hermesType: 'Hermes Agent',
appVersion: 'Versión de la app',
webuiPort: 'Puerto WebUI',
allowedOrigins: 'Direcciones de acceso',
@@ -744,7 +718,6 @@ const message = {
fallbackModelsEmpty: 'No hay modelos de respaldo configurados',
modelInputTypes: 'Tipos de entrada',
reasoning: 'Modelo de razonamiento',
manualModel: 'Entrada manual de modelo',
verified: 'Verificado',
verifySkipped: 'Sin verificación',
skillsTab: 'Habilidades',
@@ -771,7 +744,6 @@ const message = {
skillsMarketSourceOfficial: 'Oficial',
versionUnsupportedTitle: 'Esta función no es compatible con la versión actual',
versionUnsupportedHelper: 'Actualice OpenClaw a la versión {0} o posterior.',
skillsStatusDisabled: 'Deshabilitado',
skillsGroupBuiltIn: 'Integradas',
skillsGroupExternal: 'Externas',
skillsGroupWorkspace: 'Espacio de trabajo',
@@ -811,7 +783,6 @@ const message = {
'Elimínelo cuando el ritual se complete.',
],
},
bindings: 'Vinculaciones',
duplicateBinding: 'La combinacion de canal e ID de cuenta debe ser unica',
accountIdOptional: 'ID de cuenta (opcional)',
saveAllMd: 'Guardar todo',
@@ -838,7 +809,6 @@ const message = {
hermesChatDeleteConfirm: '¿Eliminar la sesión {0}?',
hermesChatDeleteSuccess: 'Sesión eliminada',
weixin: 'Weixin',
qq: 'QQ',
wecom: 'WeCom',
dingtalk: 'DingTalk',
feishu: 'Feishu',
@@ -860,17 +830,14 @@ const message = {
accountIdPlaceholder:
'Un ID único para distinguir bots y usarlo después en la configuración y el enrutamiento.',
setDefaultBot: 'Establecer como predeterminado',
botDuplicateAccountId: 'El ID de cuenta ya existe',
botDuplicateField: '{field} ya existe',
botRequired: 'Agregue al menos un bot',
botId: 'ID del bot',
allowFrom: 'Lista permitida de MD',
allowFromHelper: 'Un ID de remitente por línea. Solo se usa cuando la política de MD es Lista permitida.',
allowFromPlaceholder: 'Un ID de remitente por línea',
allowlistPolicyHelper: '{0}. Solo se usa cuando {1} es Lista permitida.',
systemPrompt: 'Prompt del sistema',
groupAllowFrom: 'Lista permitida de grupos',
groupAllowFromHelper:
'Un ID de grupo por línea. Solo se usa cuando la política de grupo es Lista permitida.',
groupAllowFromPlaceholder: 'Un ID de grupo por línea',
separateSessionByConversation: 'Sesión separada por conversación',
groupSessionScope: 'Ámbito de sesión de grupo',
@@ -886,12 +853,11 @@ const message = {
streamingBlock: 'Bloqueante',
streamingProgress: 'Progreso',
allowFromRequired: 'Introduzca al menos una entrada en la lista permitida',
saveAndRestartGateway: 'Guardar y reiniciar gateway',
pairingCode: 'Código de emparejamiento',
pairingCodePlaceholder: 'Introduzca el código de emparejamiento',
approvePairing: 'Aprobar emparejamiento',
saveSuccess: 'Guardado correctamente',
saveAndRestartSuccess: 'Guardado correctamente. El contenedor se está reiniciando automáticamente.',
successAndRestart: '{0}. El contenedor se está reiniciando automáticamente.',
pairingApproveSuccess: 'Emparejamiento aprobado correctamente',
scanConnect: 'Escanear para conectar',
scanConnectHelper:
@@ -899,13 +865,11 @@ const message = {
channelAutoRestartHelper:
'Al guardar, el contenedor se reiniciará automáticamente para que la configuración surta efecto.',
channelDeleteConfirm: '¿Eliminar la configuración del canal {0}?',
deleteAndRestartSuccess: 'Se eliminó correctamente. El contenedor se está reiniciando automáticamente.',
customProviderHelper: 'En el proveedor de modelo personalizado no se valida si la cuenta está disponible',
},
model: {
model: 'Modelo',
localModel: 'Modelos locales',
create: 'Agregar modelo',
create_helper: 'Descargar "{0}"',
ollama_doc: 'Puede visitar el sitio oficial de Ollama para buscar y encontrar más modelos.',
container_conn_helper: 'Utilice esta dirección para el acceso o conexión entre contenedores',
@@ -924,14 +888,12 @@ const message = {
manualDownload: 'Descarga manual',
modelSource: 'Fuente del modelo',
repoID: 'ID del repositorio',
modelScopeEndpoint: 'Endpoint de ModelScope',
modelScopeToken: 'Token de ModelScope (opcional)',
hfToken: 'HF Token (opcional)',
hfEndpoint: 'Endpoint de aceleración de HuggingFace',
endpointLabel: 'Endpoint de {0}',
acceleratedEndpointLabel: 'Endpoint de aceleración de {0}',
tokenOptionalLabel: 'Token de {0} (opcional)',
searchSource: 'Buscar en {0}',
hfEndpointHelper:
'Configure un endpoint de aceleración cuando el acceso a HuggingFace sea inestable. La búsqueda, los detalles y las descargas lo utilizarán.',
searchModelScope: 'Buscar en ModelScope',
searchHuggingFace: 'Buscar en HuggingFace',
sortTrending: 'Tendencias',
sortLikes: 'Más valorados',
sortDownloads: 'Más descargados',
@@ -943,7 +905,6 @@ const message = {
progress: 'Progreso',
localDownloaded: 'Descargados',
modelInfo: 'Detalles del modelo',
modelCard: 'Tarjeta del modelo',
downloading: 'Descargando',
canceled: 'Cancelado',
downloadQueued: 'Agregado a la cola de descargas',
@@ -1001,7 +962,6 @@ const message = {
lbPolicyFailover: 'Conmutación por error',
lbPolicyFailoverDesc:
'Usa primero la cuenta de modelo con mayor prioridad y cambia a la siguiente disponible tras un fallo o periodo de enfriamiento.',
productionProtection: 'Protección de producción',
maxConcurrency: 'Concurrencia máxima',
queueSize: 'Tamaño de cola',
queueTimeoutSeconds: 'Tiempo de espera en cola (s)',
@@ -1009,16 +969,10 @@ const message = {
streamIdleTimeoutSeconds: 'Timeout de inactividad streaming (s)',
maxBodyMb: 'Tamaño máximo del cuerpo (MB)',
runtimeRefreshSeconds: 'Intervalo de actualización runtime (s)',
logRetention: 'Retención de logs',
usageRetentionDays: 'Retención de estadísticas de uso (días)',
contentAuditRetentionDays: 'Retención de auditoría de cumplimiento de contenido (días)',
logCleanupIntervalHours: 'Intervalo de limpieza de logs (horas)',
requestBodyLog: 'Log del cuerpo de solicitud',
requestBodyLogEsEndpoint: 'Endpoint de Elasticsearch',
requestBodyLogEsAuthMethod: 'Autenticación de Elasticsearch',
requestBodyLogEsUsername: 'Usuario de Elasticsearch',
requestBodyLogEsPassword: 'Contraseña de Elasticsearch',
requestBodyLogEsApiKey: 'Elasticsearch API Key',
requestBodyLogIndexPrefix: 'Prefijo del índice',
requestBodyLogRetentionDays: 'Retención del log del cuerpo de solicitud (días)',
requestBodyLogMaxBodyKb: 'Tamaño máximo del cuerpo de solicitud (KB)',
@@ -1043,10 +997,9 @@ const message = {
esLogCircuitOpen: 'Circuito abierto',
esLogCircuitUntil: 'Circuito ES hasta',
serviceOperateConfirm: '¿Confirmar {0} el servicio de gateway de IA?',
deleteBackendConfirm: '¿Eliminar la cuenta de modelo {0}?',
deleteTargetConfirm: '¿Eliminar {0} {1}?',
deleteBackendTitle: 'Eliminar cuenta de modelo',
deleteUserConfirm: '¿Eliminar el usuario {0}?',
userFallback: 'Usuario {0}',
userFallback: 'Usuario eliminado (ID: {0})',
requestModel: 'Modelo solicitado',
upstreamModel: 'Modelo upstream',
requestModelPlaceholder: 'p. ej. qwen2.5-coder',
@@ -1055,10 +1008,8 @@ const message = {
overview: 'Resumen',
distribution: 'Distribución',
usageTrend: 'Tendencia de uso',
providerDistribution: 'Distribución por proveedor',
distributionBy: 'Distribución por {0}',
unmatched: 'Sin coincidencia',
modelDistribution: 'Distribución por modelo',
accountDistribution: 'Distribución por cuenta de modelo',
modelAccount: 'Cuenta de modelo',
serviceProvider: 'Proveedor',
tokenUsage: 'Uso de tokens',
@@ -1067,8 +1018,6 @@ const message = {
rank: 'Rango',
promptToken: 'Tokens de entrada',
completionToken: 'Tokens de salida',
inputTokens: 'Tokens de entrada',
outputTokens: 'Tokens de salida',
totalToken: 'Tokens totales',
cachedToken: 'Tokens en caché',
cacheHitRate: 'Tasa de acierto de caché',
@@ -1096,7 +1045,6 @@ const message = {
modelGroupModels: 'Modelos solicitados',
modelGroupModelsPlaceholder: 'Seleccione o ingrese nombres de modelos solicitados',
modelGroupModelCount: '{0} modelos',
deleteModelGroupConfirm: '¿Eliminar el grupo de modelos {0}?',
contentCompliance: 'Content Compliance',
contentAction: 'Action',
actionBlock: 'Block',
@@ -1114,9 +1062,7 @@ const message = {
matchedGroups: 'Matched groups',
importResult: 'Imported {0}, duplicated {1}, invalid {2}',
auditLogs: 'Audit Logs',
apiKeyReset: 'Restablecer',
apiKeyCount: 'Cantidad',
deleteGroupConfirm: '¿Eliminar el grupo{name}? Esta acción no se puede deshacer.',
},
skillsHub: {
title: 'Skills Hub',
@@ -1258,7 +1204,6 @@ const message = {
},
benchmark: {
title: 'Benchmark',
create: 'Crear',
launchCommand: 'Comando de inicio',
retest: 'Volver a probar',
statusRunning: 'En ejecución',
@@ -1283,8 +1228,6 @@ const message = {
firstTokenLatency: 'Latencia del primer token',
firstTokenLatencyHelper:
'Tiempo desde el envío de la solicitud hasta recibir el primer token. Un valor menor indica respuesta más rápida.',
inputTokens: 'Tokens de entrada',
outputTokens: 'Tokens de salida',
tokenValueHelper: 'Introduzca un entero positivo o valor con k, p. ej. 512, 1k, 32k',
numPrompts: 'Prompts',
concurrency: 'Concurrencia',
@@ -1295,17 +1238,7 @@ const message = {
requestRateCustom: 'QPS personalizado',
requestRateCustomPlaceholder: 'Solicitudes por segundo, p. ej. 2.5',
successfulRequests: 'Solicitudes correctas',
failedRequests: 'Solicitudes fallidas',
requestThroughput: 'Rendimiento de solicitudes',
ttftMean: 'TTFT promedio',
ttftMedian: 'TTFT mediana',
ttftP99: 'TTFT P99',
tpotMean: 'TPOT promedio',
tpotMedian: 'TPOT mediana',
tpotP99: 'TPOT P99',
itlMean: 'ITL promedio',
itlMedian: 'ITL mediana',
itlP99: 'ITL P99',
timeout: 'Tiempo de espera (segundos)',
image: 'Imagen vLLM',
ignoreEos: 'Ignorar EOS',
+16 -83
View File
@@ -10,7 +10,6 @@ const message = {
lingxia: 'LXware',
button: {
run: '実行',
create: '作成',
add: '追加',
save: '保存',
set: '設定',
@@ -87,6 +86,7 @@ const message = {
migrate: '移行',
prev: '前へ',
next: '次へ',
create: '作成',
setDefault: '既定値に戻す',
bind: 'バインド',
tip: 'ヒント',
@@ -682,47 +682,21 @@ const message = {
account: 'モデルアカウント',
batchOperation: '一括操作',
operationType: '操作タイプ',
batchInstall: '一括インストール',
batchUpgrade: '一括アップグレード',
batchSkillInstall: 'Skill 一括配布',
batchStart: '一括起動',
batchStop: '一括停止',
batchRestart: '一括再起動',
batchDelete: '一括削除',
batchInstallAgent: 'エージェントの一括インストール',
dispatchAgentInstallTasks: 'エージェントインストールタスクを配信',
batchUpgradeAgent: 'エージェントの一括アップグレード',
dispatchAgentUpgradeTasks: 'エージェントアップグレードタスクを配信',
batchInstallAgentSkill: 'Skill 一括配布',
dispatchAgentSkillInstallTasks: 'Skill インストールタスクを配信',
batchStartAgent: 'エージェントの一括起動',
dispatchAgentStartTasks: 'エージェント起動タスクを配信',
batchStopAgent: 'エージェントの一括停止',
dispatchAgentStopTasks: 'エージェント停止タスクを配信',
batchRestartAgent: 'エージェントの一括再起動',
dispatchAgentRestartTasks: 'エージェント再起動タスクを配信',
batchDeleteAgent: 'エージェントの一括削除',
dispatchAgentDeleteTasks: 'エージェント削除タスクを配信',
batchAction: '一括{0}',
installSkillAction: 'Skill 配布',
batchAgentTask: 'エージェントを一括{0}',
dispatchAgentTask: 'エージェント{0}タスクを配信',
dispatchTask: '{0}タスクを配信',
taskSubmitted: '{0}タスクを送信しました',
allNodes: 'すべてのノード',
targetVersion: 'ターゲットバージョン',
skill: 'Skill',
skillSource: 'Skill ソース',
skillKeyword: 'Skill キーワード',
clawHubSkillPlaceholder: '先に Skill を検索して選択してください',
batchInstallTaskSubmitted: '一括インストールタスクを送信しました',
batchUpgradeTaskSubmitted: '一括アップグレードタスクを送信しました',
batchSkillInstallTaskSubmitted: 'Skill 一括配布タスクを送信しました',
batchStartTaskSubmitted: '一括起動タスクを送信しました',
batchStopTaskSubmitted: '一括停止タスクを送信しました',
batchRestartTaskSubmitted: '一括再起動タスクを送信しました',
batchDeleteTaskSubmitted: '一括削除タスクを送信しました',
noAccountHint: '既存のモデルアカウントを選択するか新規に追加してください',
accountCount: 'モデルアカウント {0} ',
syncAgents: '関連エージェントを同期',
syncAgentsHelper: 'このモデルアカウントを使用するエージェントの openclaw.json を更新',
openclawType: 'OpenClaw',
copawType: 'QwenPaw',
hermesType: 'Hermes Agent',
appVersion: 'アプリバージョン',
webuiPort: 'WebUI ポート',
allowedOrigins: 'アクセスアドレス',
@@ -739,7 +713,6 @@ const message = {
fallbackModelsEmpty: 'フォールバックモデルは未設定です',
modelInputTypes: '入力タイプ',
reasoning: '推論モデル',
manualModel: '手動入力',
verified: '検証済み',
verifySkipped: '検証なし',
skillsTab: '技能',
@@ -766,7 +739,6 @@ const message = {
skillsMarketSourceOfficial: '公式',
versionUnsupportedTitle: '現在のバージョンではこの機能はサポートされていません',
versionUnsupportedHelper: 'OpenClaw をバージョン {0} 以降にアップグレードしてください',
skillsStatusDisabled: '無効',
skillsGroupBuiltIn: '内蔵',
skillsGroupExternal: '外部',
skillsGroupWorkspace: 'ワークスペース',
@@ -806,7 +778,6 @@ const message = {
'儀式が完了したら削除してください',
],
},
bindings: 'バインディング',
duplicateBinding: 'チャネルとアカウント ID の組み合わせは一意である必要があります',
accountIdOptional: 'アカウント ID任意',
saveAllMd: 'すべて保存',
@@ -832,7 +803,6 @@ const message = {
hermesChatDeleteConfirm: 'セッション {0} を削除しますか',
hermesChatDeleteSuccess: 'セッションを削除しました',
weixin: 'Weixin',
qq: 'QQ',
wecom: 'WeCom',
dingtalk: 'DingTalk',
feishu: 'Feishu',
@@ -853,17 +823,14 @@ const message = {
accountId: 'アカウント ID',
accountIdPlaceholder: 'Bot を識別するための一意 ID です保存後は設定とルーティング識別に使用されます',
setDefaultBot: 'デフォルトに設定',
botDuplicateAccountId: 'アカウント ID は既に存在します',
botDuplicateField: '{field} は既に存在します',
botRequired: '少なくとも 1 つの Bot を追加してください',
botId: 'Bot ID',
allowFrom: 'DM 許可リスト',
allowFromHelper: '1 行に 1 つの送信者 ID を入力しますDM ポリシーが許可リストの場合のみ使用されます',
allowFromPlaceholder: '1 行に 1 つの送信者 ID',
allowlistPolicyHelper: '{0}{1}が許可リストの場合のみ使用されます',
systemPrompt: 'システムプロンプト',
groupAllowFrom: 'グループ許可リスト',
groupAllowFromHelper:
'1 行に 1 つのグループ ID を入力しますグループポリシーが許可リストの場合のみ使用されます',
groupAllowFromPlaceholder: '1 行に 1 つのグループ ID',
separateSessionByConversation: '会話ごとにセッションを分離',
groupSessionScope: 'グループセッション範囲',
@@ -879,25 +846,22 @@ const message = {
streamingBlock: 'ブロッキング',
streamingProgress: '進捗出力',
allowFromRequired: '少なくとも 1 件の許可リスト項目を入力してください',
saveAndRestartGateway: '保存して gateway を再起動',
pairingCode: 'ペアリングコード',
pairingCodePlaceholder: 'ペアリングコードを入力',
approvePairing: 'ペアリングを承認',
saveSuccess: '保存しました',
saveAndRestartSuccess: '保存しましたコンテナを自動で再起動しています',
successAndRestart: '{0}コンテナを自動で再起動しています',
pairingApproveSuccess: 'ペアリングに成功しました',
scanConnect: 'スキャンして接続',
scanConnectHelper:
'クリックして QR ログインタスクを開始しますQR コードはタスクログに表示されスキャン成功後にコンテナが自動で再起動されます',
channelAutoRestartHelper: '保存後設定を反映するためにコンテナが自動で再起動されます',
channelDeleteConfirm: '{0} チャンネルの設定を削除しますか',
deleteAndRestartSuccess: '削除に成功しましたコンテナは自動的に再起動しています',
customProviderHelper: 'カスタムモデルプロバイダーではアカウントの有効性を検証しません',
},
model: {
model: 'モデル',
localModel: 'ローカルモデル',
create: 'モデルを追加',
create_helper: 'を取得 "{0}"',
ollama_doc: 'Ollama の公式ウェブサイトを訪れてさらに多くのモデルを検索して見つけることができます',
container_conn_helper: 'コンテナ間のアクセスまたは接続にこのアドレスを使用',
@@ -915,14 +879,12 @@ const message = {
manualDownload: '手動ダウンロード',
modelSource: 'モデルソース',
repoID: 'リポジトリ ID',
modelScopeEndpoint: 'ModelScope エンドポイント',
modelScopeToken: 'ModelScope Token任意',
hfToken: 'HF Token任意',
hfEndpoint: 'HuggingFace アクセラレーションエンドポイント',
endpointLabel: '{0} エンドポイント',
acceleratedEndpointLabel: '{0} アクセラレーションエンドポイント',
tokenOptionalLabel: '{0} Token任意',
searchSource: '{0} を検索',
hfEndpointHelper:
'HuggingFace へのアクセスが不安定な場合はアクセラレーションエンドポイントを設定してください検索詳細ダウンロードで使用されます',
searchModelScope: 'ModelScope を検索',
searchHuggingFace: 'HuggingFace を検索',
sortTrending: 'トレンド',
sortLikes: 'いいね順',
sortDownloads: 'ダウンロード数順',
@@ -934,7 +896,6 @@ const message = {
progress: '進捗',
localDownloaded: 'ダウンロード済み',
modelInfo: 'モデル詳細',
modelCard: 'モデルカード',
downloading: 'ダウンロード中',
canceled: 'キャンセル済み',
downloadQueued: 'ダウンロードキューに追加しました',
@@ -991,7 +952,6 @@ const message = {
lbPolicyFailover: 'フェイルオーバー',
lbPolicyFailoverDesc:
'優先度が最も高いモデルアカウントを先に使用し失敗またはクールダウン後に次の利用可能なアカウントへ切り替えます',
productionProtection: '本番保護',
maxConcurrency: '最大同時実行数',
queueSize: 'キューサイズ',
queueTimeoutSeconds: 'キュー待機タイムアウト',
@@ -999,16 +959,10 @@ const message = {
streamIdleTimeoutSeconds: 'ストリーミングアイドルタイムアウト',
maxBodyMb: '最大リクエスト本文MB',
runtimeRefreshSeconds: 'Runtime 更新間隔',
logRetention: 'ログ保持',
usageRetentionDays: '使用統計保持日数',
contentAuditRetentionDays: 'コンテンツコンプライアンス監査ログ保持日数',
logCleanupIntervalHours: 'ログクリーンアップ間隔時間',
requestBodyLog: 'リクエスト本文ログ',
requestBodyLogEsEndpoint: 'Elasticsearch エンドポイント',
requestBodyLogEsAuthMethod: 'Elasticsearch 認証方式',
requestBodyLogEsUsername: 'Elasticsearch ユーザー名',
requestBodyLogEsPassword: 'Elasticsearch パスワード',
requestBodyLogEsApiKey: 'Elasticsearch API Key',
requestBodyLogIndexPrefix: 'インデックスプレフィックス',
requestBodyLogRetentionDays: 'リクエスト本文ログ保持日数',
requestBodyLogMaxBodyKb: '最大リクエスト本文サイズKB',
@@ -1033,10 +987,9 @@ const message = {
esLogCircuitOpen: 'サーキットオープン',
esLogCircuitUntil: 'ES サーキット終了時刻',
serviceOperateConfirm: 'AI ゲートウェイサービスを {0} しますか',
deleteBackendConfirm: 'モデルアカウント {0} を削除しますか',
deleteTargetConfirm: '{0} {1} を削除しますか',
deleteBackendTitle: 'モデルアカウントを削除',
deleteUserConfirm: 'ユーザー {0} を削除しますか',
userFallback: 'ユーザー {0}',
userFallback: '削除済みユーザー (ID: {0})',
requestModel: 'リクエストモデル',
upstreamModel: '上流モデル',
requestModelPlaceholder: ': qwen2.5-coder',
@@ -1045,10 +998,8 @@ const message = {
overview: '概要',
distribution: '分布',
usageTrend: '使用傾向',
providerDistribution: 'プロバイダー別分布',
distributionBy: '{0}別分布',
unmatched: '未一致',
modelDistribution: 'モデル別分布',
accountDistribution: 'モデルアカウント別分布',
modelAccount: 'モデルアカウント',
serviceProvider: 'プロバイダー',
tokenUsage: 'Token 使用量',
@@ -1057,8 +1008,6 @@ const message = {
rank: '順位',
promptToken: '入力 Token',
completionToken: '出力 Token',
inputTokens: '入力 Token',
outputTokens: '出力 Token',
totalToken: '合計 Token',
cachedToken: 'キャッシュ Token',
cacheHitRate: 'キャッシュヒット率',
@@ -1086,7 +1035,6 @@ const message = {
modelGroupModels: 'リクエストモデル',
modelGroupModelsPlaceholder: 'リクエストモデル名を選択または入力してください',
modelGroupModelCount: '{0} モデル',
deleteModelGroupConfirm: 'モデルグループ {0} を削除しますか',
contentCompliance: 'Content Compliance',
contentAction: 'Action',
actionBlock: 'Block',
@@ -1104,9 +1052,7 @@ const message = {
matchedGroups: 'Matched groups',
importResult: 'Imported {0}, duplicated {1}, invalid {2}',
auditLogs: 'Audit Logs',
apiKeyReset: 'リセット',
apiKeyCount: '数量',
deleteGroupConfirm: 'グループ{name}を削除しますかこの操作は元に戻せません',
},
skillsHub: {
title: 'Skills Hub',
@@ -1248,7 +1194,6 @@ const message = {
},
benchmark: {
title: 'ベンチマーク',
create: '作成',
launchCommand: '起動コマンド',
retest: '再テスト',
statusRunning: '実行中',
@@ -1271,8 +1216,6 @@ const message = {
totalThroughputHelper: '1 秒あたりに処理される入力と出力 Token の合計で全体性能の測定に使います',
firstTokenLatency: '初回 Token レイテンシ',
firstTokenLatencyHelper: 'リクエスト送信から最初の Token 受信までの時間です低いほど応答が速くなります',
inputTokens: '入力 Token',
outputTokens: '出力 Token',
tokenValueHelper: '正の整数または k 単位を入力してください: 5121k32k',
numPrompts: 'プロンプト数',
concurrency: '同時実行数',
@@ -1283,17 +1226,7 @@ const message = {
requestRateCustom: 'カスタム QPS',
requestRateCustomPlaceholder: '1 秒あたりのリクエスト数: 2.5',
successfulRequests: '成功リクエスト',
failedRequests: '失敗リクエスト',
requestThroughput: 'リクエストスループット',
ttftMean: '平均 TTFT',
ttftMedian: '中央値 TTFT',
ttftP99: 'P99 TTFT',
tpotMean: '平均 TPOT',
tpotMedian: '中央値 TPOT',
tpotP99: 'P99 TPOT',
itlMean: '平均 ITL',
itlMedian: '中央値 ITL',
itlP99: 'P99 ITL',
timeout: 'タイムアウト',
image: 'vLLM イメージ',
ignoreEos: 'EOS を無視',
+16 -82
View File
@@ -10,7 +10,6 @@ const message = {
lingxia: 'LXware',
button: {
run: '실행',
create: '생성',
add: '추가',
save: '저장',
set: '설정',
@@ -87,6 +86,7 @@ const message = {
migrate: '마이그레이션',
prev: '이전',
next: '다음',
create: '생성',
setDefault: '기본값 복원',
bind: '연결',
tip: '팁',
@@ -674,47 +674,21 @@ const message = {
account: '모델 계정',
batchOperation: '일괄 작업',
operationType: '작업 유형',
batchInstall: '일괄 설치',
batchUpgrade: '일괄 업그레이드',
batchSkillInstall: 'Skill 일괄 배포',
batchStart: '일괄 시작',
batchStop: '일괄 중지',
batchRestart: '일괄 재시작',
batchDelete: '일괄 삭제',
batchInstallAgent: '에이전트 일괄 설치',
dispatchAgentInstallTasks: '에이전트 설치 작업 배포',
batchUpgradeAgent: '에이전트 일괄 업그레이드',
dispatchAgentUpgradeTasks: '에이전트 업그레이드 작업 배포',
batchInstallAgentSkill: 'Skill 일괄 배포',
dispatchAgentSkillInstallTasks: 'Skill 설치 작업 배포',
batchStartAgent: '에이전트 일괄 시작',
dispatchAgentStartTasks: '에이전트 시작 작업 배포',
batchStopAgent: '에이전트 일괄 중지',
dispatchAgentStopTasks: '에이전트 중지 작업 배포',
batchRestartAgent: '에이전트 일괄 재시작',
dispatchAgentRestartTasks: '에이전트 재시작 작업 배포',
batchDeleteAgent: '에이전트 일괄 삭제',
dispatchAgentDeleteTasks: '에이전트 삭제 작업 배포',
batchAction: '일괄 {0}',
installSkillAction: 'Skill 배포',
batchAgentTask: '에이전트 일괄 {0}',
dispatchAgentTask: '에이전트 {0} 작업 배포',
dispatchTask: '{0} 작업 배포',
taskSubmitted: '{0} 작업이 전송되었습니다',
allNodes: '모든 노드',
targetVersion: '대상 버전',
skill: 'Skill',
skillSource: 'Skill 소스',
skillKeyword: 'Skill 키워드',
clawHubSkillPlaceholder: '먼저 Skill을 검색하고 선택하세요',
batchInstallTaskSubmitted: '일괄 설치 작업이 전송되었습니다',
batchUpgradeTaskSubmitted: '일괄 업그레이드 작업이 전송되었습니다',
batchSkillInstallTaskSubmitted: 'Skill 일괄 배포 작업이 전송되었습니다',
batchStartTaskSubmitted: '일괄 시작 작업이 전송되었습니다',
batchStopTaskSubmitted: '일괄 중지 작업이 전송되었습니다',
batchRestartTaskSubmitted: '일괄 재시작 작업이 전송되었습니다',
batchDeleteTaskSubmitted: '일괄 삭제 작업이 전송되었습니다',
noAccountHint: '기존 모델 계정을 선택하거나 새로 추가하세요.',
accountCount: '모델 계정 {0}',
syncAgents: '관련 에이전트 동기화',
syncAgentsHelper: ' 모델 계정을 사용하는 에이전트의 openclaw.json 업데이트',
openclawType: 'OpenClaw',
copawType: 'QwenPaw',
hermesType: 'Hermes Agent',
appVersion: ' 버전',
webuiPort: 'WebUI 포트',
allowedOrigins: '접속 주소',
@@ -730,7 +704,6 @@ const message = {
fallbackModelsEmpty: '구성된 폴백 모델이 없습니다',
modelInputTypes: '입력 유형',
reasoning: '추론 모델',
manualModel: '수동 입력',
verified: '검증됨',
verifySkipped: '검증 ',
skillsTab: '기술',
@@ -757,7 +730,6 @@ const message = {
skillsMarketSourceOfficial: '공식',
versionUnsupportedTitle: '현재 버전에서는 기능을 지원하지 않습니다',
versionUnsupportedHelper: 'OpenClaw 버전 {0} 이상으로 업그레이드하세요.',
skillsStatusDisabled: '비활성화됨',
skillsGroupBuiltIn: '내장',
skillsGroupExternal: '외부',
skillsGroupWorkspace: '워크스페이스',
@@ -791,7 +763,6 @@ const message = {
'절차가 끝나면 삭제하세요.',
],
},
bindings: '바인딩',
duplicateBinding: '채널과 계정 ID 조합은 중복될 없습니다',
accountIdOptional: '계정 ID (선택 사항)',
saveAllMd: '모두 저장',
@@ -817,7 +788,6 @@ const message = {
hermesChatDeleteConfirm: '세션 {0}() 삭제하시겠습니까?',
hermesChatDeleteSuccess: '세션이 삭제되었습니다',
weixin: 'Weixin',
qq: 'QQ',
wecom: 'WeCom',
dingtalk: 'DingTalk',
feishu: 'Feishu',
@@ -838,16 +808,14 @@ const message = {
accountId: '계정 ID',
accountIdPlaceholder: '봇을 구분하는 고유 ID이며 저장 설정과 라우팅 식별에 사용됩니다.',
setDefaultBot: '기본값으로 설정',
botDuplicateAccountId: '계정 ID가 이미 존재합니다',
botDuplicateField: '{field}() 이미 존재합니다',
botRequired: '봇을 하나 이상 추가하세요',
botId: ' ID',
allowFrom: 'DM 허용 목록',
allowFromHelper: ' 줄에 하나의 발신자 ID를 입력하세요. DM 정책이 허용 목록일 때만 사용됩니다.',
allowFromPlaceholder: ' 줄에 하나의 발신자 ID',
allowlistPolicyHelper: '{0}. {1}() 허용 목록일 때만 사용됩니다.',
systemPrompt: '시스템 프롬프트',
groupAllowFrom: '그룹 허용 목록',
groupAllowFromHelper: ' 줄에 하나의 그룹 ID를 입력하세요. 그룹 정책이 허용 목록일 때만 사용됩니다.',
groupAllowFromPlaceholder: ' 줄에 하나의 그룹 ID',
separateSessionByConversation: '대화별 세션 분리',
groupSessionScope: '그룹 세션 범위',
@@ -863,25 +831,22 @@ const message = {
streamingBlock: '블로킹 출력',
streamingProgress: '진행 출력',
allowFromRequired: '허용 목록 항목을 하나 이상 입력하세요',
saveAndRestartGateway: '저장 gateway 재시작',
pairingCode: '페어링 코드',
pairingCodePlaceholder: '페어링 코드를 입력하세요',
approvePairing: '페어링 승인',
saveSuccess: '저장되었습니다',
saveAndRestartSuccess: '저장되었습니다. 컨테이너를 자동으로 재시작하는 중입니다.',
successAndRestart: '{0}. 컨테이너를 자동으로 재시작하는 중입니다.',
pairingApproveSuccess: '페어링이 승인되었습니다',
scanConnect: '스캔하여 연결',
scanConnectHelper:
'클릭하여 QR 로그인 작업을 시작하세요. QR 코드는 작업 로그에 표시되며 스캔이 완료되면 컨테이너가 자동으로 재시작됩니다.',
channelAutoRestartHelper: '저장하면 설정 적용을 위해 컨테이너가 자동으로 재시작됩니다.',
channelDeleteConfirm: '{0} 채널 구성을 삭제하시겠습니까?',
deleteAndRestartSuccess: '삭제되었습니다. 컨테이너가 자동으로 다시 시작되고 있습니다.',
customProviderHelper: '사용자 정의 모델 공급자는 계정 사용 가능 여부를 검증하지 않습니다',
},
model: {
model: '모델',
localModel: '로컬 모델',
create: '모델 추가',
create_helper: '가져오기 "{0}"',
ollama_doc: 'Ollama 공식 웹사이트를 방문하여 많은 모델을 검색하고 찾을 있습니다.',
container_conn_helper: '컨테이너 접근 또는 연결에 주소를 사용',
@@ -899,14 +864,12 @@ const message = {
manualDownload: '수동 다운로드',
modelSource: '모델 소스',
repoID: '저장소 ID',
modelScopeEndpoint: 'ModelScope 엔드포인트',
modelScopeToken: 'ModelScope Token (선택)',
hfToken: 'HF Token (선택 사항)',
hfEndpoint: 'HuggingFace 가속 엔드포인트',
endpointLabel: '{0} 엔드포인트',
acceleratedEndpointLabel: '{0} 가속 엔드포인트',
tokenOptionalLabel: '{0} Token (선택 사항)',
searchSource: '{0} 검색',
hfEndpointHelper:
'HuggingFace 접속이 불안정할 가속 엔드포인트를 설정하세요. 검색, 상세 정보, 다운로드에 사용됩니다.',
searchModelScope: 'ModelScope 검색',
searchHuggingFace: 'HuggingFace 검색',
sortTrending: '인기 트렌드',
sortLikes: '좋아요 많은 ',
sortDownloads: '다운로드 많은 ',
@@ -918,7 +881,6 @@ const message = {
progress: '진행률',
localDownloaded: '다운로드됨',
modelInfo: '모델 상세 정보',
modelCard: '모델 카드',
downloading: '다운로드 ',
canceled: '취소됨',
downloadQueued: '다운로드 대기열에 추가되었습니다',
@@ -975,7 +937,6 @@ const message = {
lbPolicyFailover: '장애 조치',
lbPolicyFailoverDesc:
'우선순위가 가장 높은 모델 계정을 먼저 사용하고, 실패 또는 쿨다운 다음 사용 가능한 계정으로 전환합니다.',
productionProtection: '프로덕션 보호',
maxConcurrency: '최대 동시성',
queueSize: '대기열 크기',
queueTimeoutSeconds: '대기열 대기 시간 초과()',
@@ -983,16 +944,10 @@ const message = {
streamIdleTimeoutSeconds: '스트리밍 유휴 시간 초과()',
maxBodyMb: '최대 요청 본문(MB)',
runtimeRefreshSeconds: 'Runtime 새로고침 간격()',
logRetention: '로그 보관',
usageRetentionDays: '사용 통계 보관 일수',
contentAuditRetentionDays: '콘텐츠 컴플라이언스 감사 로그 보관 일수',
logCleanupIntervalHours: '로그 정리 간격(시간)',
requestBodyLog: '요청 본문 로그',
requestBodyLogEsEndpoint: 'Elasticsearch 엔드포인트',
requestBodyLogEsAuthMethod: 'Elasticsearch 인증 방식',
requestBodyLogEsUsername: 'Elasticsearch 사용자 이름',
requestBodyLogEsPassword: 'Elasticsearch 비밀번호',
requestBodyLogEsApiKey: 'Elasticsearch API Key',
requestBodyLogIndexPrefix: '인덱스 접두사',
requestBodyLogRetentionDays: '요청 본문 로그 보관 일수',
requestBodyLogMaxBodyKb: '최대 요청 본문 크기(KB)',
@@ -1017,10 +972,9 @@ const message = {
esLogCircuitOpen: '서킷 오픈',
esLogCircuitUntil: 'ES 서킷 종료 시간',
serviceOperateConfirm: 'AI 게이트웨이 서비스를 {0}하시겠습니까?',
deleteBackendConfirm: '모델 계정 {0}() 삭제하시겠습니까?',
deleteTargetConfirm: '{0} {1}() 삭제하시겠습니까?',
deleteBackendTitle: '모델 계정 삭제',
deleteUserConfirm: '사용자 {0}() 삭제하시겠습니까?',
userFallback: '사용자 {0}',
userFallback: '삭제된 사용자 (ID: {0})',
requestModel: '요청 모델',
upstreamModel: '업스트림 모델',
requestModelPlaceholder: ': qwen2.5-coder',
@@ -1029,10 +983,8 @@ const message = {
overview: '개요',
distribution: '분포',
usageTrend: '사용 추세',
providerDistribution: '제공자 분포',
distributionBy: '{0} 분포',
unmatched: '미일치',
modelDistribution: '모델별 분포',
accountDistribution: '모델 계정별 분포',
modelAccount: '모델 계정',
serviceProvider: '제공자',
tokenUsage: 'Token 사용량',
@@ -1041,8 +993,6 @@ const message = {
rank: '순위',
promptToken: '입력 Token',
completionToken: '출력 Token',
inputTokens: '입력 Token',
outputTokens: '출력 Token',
totalToken: ' Token',
cachedToken: '캐시 Token',
cacheHitRate: '캐시 적중률',
@@ -1070,7 +1020,6 @@ const message = {
modelGroupModels: '요청 모델',
modelGroupModelsPlaceholder: '요청 모델 이름을 선택하거나 입력하세요',
modelGroupModelCount: '{0} 모델',
deleteModelGroupConfirm: '모델 그룹 {0}() 삭제하시겠습니까?',
contentCompliance: 'Content Compliance',
contentAction: 'Action',
actionBlock: 'Block',
@@ -1088,9 +1037,7 @@ const message = {
matchedGroups: 'Matched groups',
importResult: 'Imported {0}, duplicated {1}, invalid {2}',
auditLogs: 'Audit Logs',
apiKeyReset: '초기화',
apiKeyCount: '数量',
deleteGroupConfirm: '그룹{name}() 삭제하시겠습니까? 작업은 되돌릴 없습니다.',
},
skillsHub: {
title: 'Skills Hub',
@@ -1230,7 +1177,6 @@ const message = {
},
benchmark: {
title: '벤치마크',
create: '생성',
launchCommand: '시작 명령',
retest: '다시 테스트',
statusRunning: '실행 ',
@@ -1253,8 +1199,6 @@ const message = {
totalThroughputHelper: '초당 처리된 입력 출력 Token 수로 전체 처리 능력을 측정합니다.',
firstTokenLatency: ' Token 지연 시간',
firstTokenLatencyHelper: '요청 전송부터 Token 수신까지의 시간입니다. 낮을수록 응답이 빠릅니다.',
inputTokens: '입력 Token',
outputTokens: '출력 Token',
tokenValueHelper: '양의 정수 또는 k 값을 입력하세요. : 512, 1k, 32k',
numPrompts: '프롬프트 ',
concurrency: '동시성',
@@ -1265,17 +1209,7 @@ const message = {
requestRateCustom: '사용자 지정 QPS',
requestRateCustomPlaceholder: '초당 요청 , : 2.5',
successfulRequests: '성공한 요청',
failedRequests: '실패한 요청',
requestThroughput: '요청 처리량',
ttftMean: '평균 TTFT',
ttftMedian: '중앙값 TTFT',
ttftP99: 'P99 TTFT',
tpotMean: '평균 TPOT',
tpotMedian: '중앙값 TPOT',
tpotP99: 'P99 TPOT',
itlMean: '평균 ITL',
itlMedian: '중앙값 ITL',
itlP99: 'P99 ITL',
timeout: '시간 초과()',
image: 'vLLM 이미지',
ignoreEos: 'EOS 무시',
+16 -84
View File
@@ -10,7 +10,6 @@ const message = {
lingxia: 'LXware',
button: {
run: 'Jalankan',
create: 'Cipta',
add: 'Tambah',
save: 'Simpan',
set: 'Tetapan',
@@ -87,6 +86,7 @@ const message = {
migrate: 'Migrasi',
prev: 'Sebelumnya',
next: 'Seterusnya',
create: 'Cipta',
setDefault: 'Pulihkan lalai',
bind: 'Pautkan',
tip: 'Tip',
@@ -689,47 +689,21 @@ const message = {
account: 'Akaun model',
batchOperation: 'Operasi pukal',
operationType: 'Jenis operasi',
batchInstall: 'Pemasangan pukal',
batchUpgrade: 'Naik taraf pukal',
batchSkillInstall: 'Hantar Skill secara pukal',
batchStart: 'Mula pukal',
batchStop: 'Henti pukal',
batchRestart: 'Mula semula pukal',
batchDelete: 'Padam pukal',
batchInstallAgent: 'Pasang ejen secara pukal',
dispatchAgentInstallTasks: 'Hantar tugas pemasangan ejen',
batchUpgradeAgent: 'Naik taraf ejen secara pukal',
dispatchAgentUpgradeTasks: 'Hantar tugas naik taraf ejen',
batchInstallAgentSkill: 'Hantar Skill secara pukal',
dispatchAgentSkillInstallTasks: 'Hantar tugas pemasangan Skill',
batchStartAgent: 'Mula ejen secara pukal',
dispatchAgentStartTasks: 'Hantar tugas mula ejen',
batchStopAgent: 'Henti ejen secara pukal',
dispatchAgentStopTasks: 'Hantar tugas henti ejen',
batchRestartAgent: 'Mula semula ejen secara pukal',
dispatchAgentRestartTasks: 'Hantar tugas mula semula ejen',
batchDeleteAgent: 'Padam ejen secara pukal',
dispatchAgentDeleteTasks: 'Hantar tugas padam ejen',
batchAction: '{0} pukal',
installSkillAction: 'Hantar Skill',
batchAgentTask: '{0} ejen secara pukal',
dispatchAgentTask: 'Hantar tugas untuk {0} ejen',
dispatchTask: 'Hantar tugas {0}',
taskSubmitted: 'Tugas {0} telah dihantar',
allNodes: 'Semua nod',
targetVersion: 'Versi sasaran',
skill: 'Skill',
skillSource: 'Sumber Skill',
skillKeyword: 'Kata kunci Skill',
clawHubSkillPlaceholder: 'Cari dan pilih Skill dahulu',
batchInstallTaskSubmitted: 'Tugas pemasangan pukal telah dihantar',
batchUpgradeTaskSubmitted: 'Tugas naik taraf pukal telah dihantar',
batchSkillInstallTaskSubmitted: 'Tugas penghantaran Skill pukal telah dihantar',
batchStartTaskSubmitted: 'Tugas mula pukal telah dihantar',
batchStopTaskSubmitted: 'Tugas henti pukal telah dihantar',
batchRestartTaskSubmitted: 'Tugas mula semula pukal telah dihantar',
batchDeleteTaskSubmitted: 'Tugas padam pukal telah dihantar',
noAccountHint: 'Pilih akaun model sedia ada atau tambah yang baharu.',
accountCount: 'Akaun model {0}',
syncAgents: 'Segerakkan agen berkaitan',
syncAgentsHelper: 'Kemas kini openclaw.json untuk agen yang menggunakan akaun model ini',
openclawType: 'OpenClaw',
copawType: 'QwenPaw',
hermesType: 'Hermes Agent',
appVersion: 'Versi aplikasi',
webuiPort: 'Port WebUI',
allowedOrigins: 'Alamat akses',
@@ -746,7 +720,6 @@ const message = {
fallbackModelsEmpty: 'Tiada model fallback dikonfigurasikan',
modelInputTypes: 'Jenis input',
reasoning: 'Model penaakulan',
manualModel: 'Input manual',
verified: 'Disahkan',
verifySkipped: 'Tanpa pengesahan',
skillsTab: 'Kemahiran',
@@ -773,7 +746,6 @@ const message = {
skillsMarketSourceOfficial: 'Rasmi',
versionUnsupportedTitle: 'Ciri ini tidak disokong dalam versi semasa',
versionUnsupportedHelper: 'Sila naik taraf OpenClaw ke versi {0} atau lebih baharu.',
skillsStatusDisabled: 'Dilumpuhkan',
skillsGroupBuiltIn: 'Terbina dalam',
skillsGroupExternal: 'Luaran',
skillsGroupWorkspace: 'Ruang kerja',
@@ -810,7 +782,6 @@ const message = {
'Padam selepas ritual selesai.',
],
},
bindings: 'Ikatan',
duplicateBinding: 'Gabungan saluran dan ID akaun mesti unik',
accountIdOptional: 'ID akaun (pilihan)',
saveAllMd: 'Simpan semua',
@@ -837,7 +808,6 @@ const message = {
hermesChatDeleteConfirm: 'Padam sesi {0}?',
hermesChatDeleteSuccess: 'Sesi berjaya dipadam',
weixin: 'Weixin',
qq: 'QQ',
wecom: 'WeCom',
dingtalk: 'DingTalk',
feishu: 'Feishu',
@@ -859,18 +829,14 @@ const message = {
accountIdPlaceholder:
'ID unik untuk membezakan bot dan digunakan untuk konfigurasi serta penghalaan selepas disimpan.',
setDefaultBot: 'Tetapkan sebagai lalai',
botDuplicateAccountId: 'ID akaun sudah wujud',
botDuplicateField: '{field} sudah wujud',
botRequired: 'Tambah sekurang-kurangnya satu bot',
botId: 'ID bot',
allowFrom: 'Senarai benarkan DM',
allowFromHelper:
'Satu ID penghantar setiap baris. Hanya digunakan apabila dasar DM ialah Senarai benarkan.',
allowFromPlaceholder: 'Satu ID penghantar setiap baris',
allowlistPolicyHelper: '{0}. Hanya digunakan apabila {1} ialah Senarai benarkan.',
systemPrompt: 'Prompt sistem',
groupAllowFrom: 'Senarai benarkan kumpulan',
groupAllowFromHelper:
'Satu ID kumpulan setiap baris. Hanya digunakan apabila dasar kumpulan ialah Senarai benarkan.',
groupAllowFromPlaceholder: 'Satu ID kumpulan setiap baris',
separateSessionByConversation: 'Asingkan sesi mengikut perbualan',
groupSessionScope: 'Skop sesi kumpulan',
@@ -886,12 +852,11 @@ const message = {
streamingBlock: 'Sekat',
streamingProgress: 'Kemajuan',
allowFromRequired: 'Masukkan sekurang-kurangnya satu entri senarai benarkan',
saveAndRestartGateway: 'Simpan dan mulakan semula gateway',
pairingCode: 'Kod pasangan',
pairingCodePlaceholder: 'Masukkan kod pasangan',
approvePairing: 'Luluskan pasangan',
saveSuccess: 'Berjaya disimpan',
saveAndRestartSuccess: 'Berjaya disimpan. Bekas sedang dimulakan semula secara automatik.',
successAndRestart: '{0}. Bekas sedang dimulakan semula secara automatik.',
pairingApproveSuccess: 'Pasangan berjaya diluluskan',
scanConnect: 'Imbas untuk sambung',
scanConnectHelper:
@@ -899,13 +864,11 @@ const message = {
channelAutoRestartHelper:
'Menyimpan akan memulakan semula bekas secara automatik supaya konfigurasi berkuat kuasa.',
channelDeleteConfirm: 'Padam konfigurasi saluran {0}?',
deleteAndRestartSuccess: 'Berjaya dipadam. Bekas sedang dimulakan semula secara automatik.',
customProviderHelper: 'Penyedia model tersuai tidak mengesahkan sama ada akaun boleh digunakan',
},
model: {
model: 'Model',
localModel: 'Model Tempatan',
create: 'Tambah Model',
create_helper: 'Tarik "{0}"',
ollama_doc: 'Anda boleh melawat laman web rasmi Ollama untuk mencari dan menemui lebih banyak model.',
container_conn_helper: 'Gunakan alamat ini untuk akses atau sambungan antara kontena',
@@ -924,14 +887,12 @@ const message = {
manualDownload: 'Muat Turun Manual',
modelSource: 'Sumber model',
repoID: 'ID Repositori',
modelScopeEndpoint: 'Endpoint ModelScope',
modelScopeToken: 'Token ModelScope (pilihan)',
hfToken: 'HF Token (pilihan)',
hfEndpoint: 'Titik akhir pecutan HuggingFace',
endpointLabel: 'Endpoint {0}',
acceleratedEndpointLabel: 'Titik akhir pecutan {0}',
tokenOptionalLabel: 'Token {0} (pilihan)',
searchSource: 'Cari {0}',
hfEndpointHelper:
'Konfigurasikan titik akhir pecutan apabila akses HuggingFace tidak stabil. Carian, butiran dan muat turun akan menggunakannya.',
searchModelScope: 'Cari ModelScope',
searchHuggingFace: 'Cari HuggingFace',
sortTrending: 'Trend popular',
sortLikes: 'Paling disukai',
sortDownloads: 'Paling banyak dimuat turun',
@@ -943,7 +904,6 @@ const message = {
progress: 'Kemajuan',
localDownloaded: 'Dimuat turun',
modelInfo: 'Butiran Model',
modelCard: 'Kad Model',
downloading: 'Sedang memuat turun',
canceled: 'Dibatalkan',
downloadQueued: 'Ditambah ke baris gilir muat turun',
@@ -1000,7 +960,6 @@ const message = {
lbPolicyFailover: 'Failover',
lbPolicyFailoverDesc:
'Gunakan akaun model berkeutamaan tertinggi dahulu, kemudian tukar ke akaun tersedia seterusnya selepas gagal atau cooldown.',
productionProtection: 'Perlindungan produksi',
maxConcurrency: 'Keserentakan maksimum',
queueSize: 'Saiz baris gilir',
queueTimeoutSeconds: 'Tamat masa menunggu baris gilir (s)',
@@ -1008,16 +967,10 @@ const message = {
streamIdleTimeoutSeconds: 'Tamat masa melahu penstriman (s)',
maxBodyMb: 'Saiz badan maksimum (MB)',
runtimeRefreshSeconds: 'Selang segar semula runtime (s)',
logRetention: 'Pengekalan Log',
usageRetentionDays: 'Pengekalan Statistik Penggunaan (hari)',
contentAuditRetentionDays: 'Pengekalan Audit Pematuhan Kandungan (hari)',
logCleanupIntervalHours: 'Selang Pembersihan Log (jam)',
requestBodyLog: 'Log Badan Permintaan',
requestBodyLogEsEndpoint: 'Endpoint Elasticsearch',
requestBodyLogEsAuthMethod: 'Pengesahan Elasticsearch',
requestBodyLogEsUsername: 'Nama Pengguna Elasticsearch',
requestBodyLogEsPassword: 'Kata Laluan Elasticsearch',
requestBodyLogEsApiKey: 'Elasticsearch API Key',
requestBodyLogIndexPrefix: 'Awalan Indeks',
requestBodyLogRetentionDays: 'Pengekalan Log Badan Permintaan (hari)',
requestBodyLogMaxBodyKb: 'Saiz Maksimum Badan Permintaan (KB)',
@@ -1042,10 +995,9 @@ const message = {
esLogCircuitOpen: 'Litar terbuka',
esLogCircuitUntil: 'Litar ES hingga',
serviceOperateConfirm: 'Sahkan untuk {0} perkhidmatan gateway AI?',
deleteBackendConfirm: 'Padam akaun model {0}?',
deleteTargetConfirm: 'Padam {0} {1}?',
deleteBackendTitle: 'Padam akaun model',
deleteUserConfirm: 'Padam pengguna {0}?',
userFallback: 'Pengguna {0}',
userFallback: 'Pengguna dipadam (ID: {0})',
requestModel: 'Model permintaan',
upstreamModel: 'Model upstream',
requestModelPlaceholder: 'cth. qwen2.5-coder',
@@ -1054,10 +1006,8 @@ const message = {
overview: 'Gambaran keseluruhan',
distribution: 'Taburan',
usageTrend: 'Trend penggunaan',
providerDistribution: 'Taburan mengikut penyedia',
distributionBy: 'Taburan mengikut {0}',
unmatched: 'Tidak sepadan',
modelDistribution: 'Taburan mengikut model',
accountDistribution: 'Taburan mengikut akaun model',
modelAccount: 'Akaun model',
serviceProvider: 'Penyedia',
tokenUsage: 'Penggunaan Token',
@@ -1066,8 +1016,6 @@ const message = {
rank: 'Kedudukan',
promptToken: 'Token input',
completionToken: 'Token output',
inputTokens: 'Token input',
outputTokens: 'Token output',
totalToken: 'Jumlah Token',
cachedToken: 'Token cache',
cacheHitRate: 'Kadar hit cache',
@@ -1095,7 +1043,6 @@ const message = {
modelGroupModels: 'Model Permintaan',
modelGroupModelsPlaceholder: 'Pilih atau masukkan nama model permintaan',
modelGroupModelCount: '{0} model',
deleteModelGroupConfirm: 'Padam kumpulan model {0}?',
contentCompliance: 'Content Compliance',
contentAction: 'Action',
actionBlock: 'Block',
@@ -1113,9 +1060,7 @@ const message = {
matchedGroups: 'Matched groups',
importResult: 'Imported {0}, duplicated {1}, invalid {2}',
auditLogs: 'Audit Logs',
apiKeyReset: 'Tetapkan semula',
apiKeyCount: 'Kuantiti',
deleteGroupConfirm: 'Padam kumpulan{name}? Tindakan ini tidak boleh dibatalkan.',
},
skillsHub: {
title: 'Skills Hub',
@@ -1257,7 +1202,6 @@ const message = {
},
benchmark: {
title: 'Penanda Aras',
create: 'Cipta',
launchCommand: 'Arahan Pelancaran',
retest: 'Uji Semula',
statusRunning: 'Sedang berjalan',
@@ -1282,8 +1226,6 @@ const message = {
firstTokenLatency: 'Latensi Token Pertama',
firstTokenLatencyHelper:
'Masa dari menghantar permintaan hingga menerima token pertama. Lebih rendah bermaksud respons lebih pantas.',
inputTokens: 'Token Input',
outputTokens: 'Token Output',
tokenValueHelper: 'Masukkan integer positif atau nilai k, cth. 512, 1k, 32k',
numPrompts: 'Prompt',
concurrency: 'Keserentakan',
@@ -1294,17 +1236,7 @@ const message = {
requestRateCustom: 'QPS tersuai',
requestRateCustomPlaceholder: 'Permintaan sesaat, cth. 2.5',
successfulRequests: 'Permintaan berjaya',
failedRequests: 'Permintaan gagal',
requestThroughput: 'Throughput Permintaan',
ttftMean: 'Purata TTFT',
ttftMedian: 'Median TTFT',
ttftP99: 'P99 TTFT',
tpotMean: 'Purata TPOT',
tpotMedian: 'Median TPOT',
tpotP99: 'P99 TPOT',
itlMean: 'Purata ITL',
itlMedian: 'Median ITL',
itlP99: 'P99 ITL',
timeout: 'Tamat Masa (saat)',
image: 'Imej vLLM',
ignoreEos: 'Abaikan EOS',
+16 -84
View File
@@ -10,7 +10,6 @@ const message = {
lingxia: 'LXware',
button: {
run: 'Executar',
create: 'Criar',
add: 'Adicionar',
save: 'Salvar',
set: 'Configurações',
@@ -87,6 +86,7 @@ const message = {
migrate: 'Migrar',
prev: 'Anterior',
next: 'Próximo',
create: 'Criar',
setDefault: 'Restaurar padrões',
bind: 'Vincular',
tip: 'Dica',
@@ -683,47 +683,21 @@ const message = {
account: 'Conta de modelo',
batchOperation: 'Operação em lote',
operationType: 'Tipo de operação',
batchInstall: 'Instalação em lote',
batchUpgrade: 'Atualização em lote',
batchSkillInstall: 'Distribuir Skill em lote',
batchStart: 'Iniciar em lote',
batchStop: 'Parar em lote',
batchRestart: 'Reiniciar em lote',
batchDelete: 'Excluir em lote',
batchInstallAgent: 'Instalar agentes em lote',
dispatchAgentInstallTasks: 'Distribuir tarefas de instalação de agentes',
batchUpgradeAgent: 'Atualizar agentes em lote',
dispatchAgentUpgradeTasks: 'Distribuir tarefas de atualização de agentes',
batchInstallAgentSkill: 'Distribuir Skill em lote',
dispatchAgentSkillInstallTasks: 'Distribuir tarefas de instalação de Skill',
batchStartAgent: 'Iniciar agentes em lote',
dispatchAgentStartTasks: 'Distribuir tarefas de início de agentes',
batchStopAgent: 'Parar agentes em lote',
dispatchAgentStopTasks: 'Distribuir tarefas de parada de agentes',
batchRestartAgent: 'Reiniciar agentes em lote',
dispatchAgentRestartTasks: 'Distribuir tarefas de reinício de agentes',
batchDeleteAgent: 'Excluir agentes em lote',
dispatchAgentDeleteTasks: 'Distribuir tarefas de exclusão de agentes',
batchAction: '{0} em lote',
installSkillAction: 'Distribuir Skill',
batchAgentTask: '{0} agentes em lote',
dispatchAgentTask: 'Distribuir tarefas para {0} agentes',
dispatchTask: 'Distribuir tarefas de {0}',
taskSubmitted: 'Tarefa de {0} enviada',
allNodes: 'Todos os nós',
targetVersion: 'Versão de destino',
skill: 'Skill',
skillSource: 'Origem da Skill',
skillKeyword: 'Palavra-chave da Skill',
clawHubSkillPlaceholder: 'Pesquise e selecione uma Skill primeiro',
batchInstallTaskSubmitted: 'Tarefa de instalação em lote enviada',
batchUpgradeTaskSubmitted: 'Tarefa de atualização em lote enviada',
batchSkillInstallTaskSubmitted: 'Tarefa de distribuição de Skill enviada',
batchStartTaskSubmitted: 'Tarefa de início em lote enviada',
batchStopTaskSubmitted: 'Tarefa de parada em lote enviada',
batchRestartTaskSubmitted: 'Tarefa de reinício em lote enviada',
batchDeleteTaskSubmitted: 'Tarefa de exclusão em lote enviada',
noAccountHint: 'Selecione uma conta de modelo existente ou adicione uma nova.',
accountCount: '{0} contas de modelo',
syncAgents: 'Sincronizar agentes vinculados',
syncAgentsHelper: 'Atualize o openclaw.json para agentes que usam esta conta de modelo',
openclawType: 'OpenClaw',
copawType: 'QwenPaw',
hermesType: 'Hermes Agent',
appVersion: 'Versão do app',
webuiPort: 'Porta WebUI',
allowedOrigins: 'Endereços de acesso',
@@ -740,7 +714,6 @@ const message = {
fallbackModelsEmpty: 'Nenhum modelo de fallback configurado',
modelInputTypes: 'Tipos de entrada',
reasoning: 'Modelo de raciocínio',
manualModel: 'Entrada manual',
verified: 'Verificado',
verifySkipped: 'Sem verificação',
skillsTab: 'Habilidades',
@@ -767,7 +740,6 @@ const message = {
skillsMarketSourceOfficial: 'Oficial',
versionUnsupportedTitle: 'Este recurso não é compatível com a versão atual',
versionUnsupportedHelper: 'Atualize o OpenClaw para a versão {0} ou superior.',
skillsStatusDisabled: 'Desativado',
skillsGroupBuiltIn: 'Integradas',
skillsGroupExternal: 'Externas',
skillsGroupWorkspace: 'Espaço de trabalho',
@@ -807,7 +779,6 @@ const message = {
'Exclua após o ritual ser concluído.',
],
},
bindings: 'Vínculos',
duplicateBinding: 'A combinacao de canal e ID da conta deve ser unica',
accountIdOptional: 'ID da conta (opcional)',
saveAllMd: 'Salvar tudo',
@@ -834,7 +805,6 @@ const message = {
hermesChatDeleteConfirm: 'Excluir a sessão {0}?',
hermesChatDeleteSuccess: 'Sessão excluída',
weixin: 'Weixin',
qq: 'QQ',
wecom: 'WeCom',
dingtalk: 'DingTalk',
feishu: 'Feishu',
@@ -855,18 +825,14 @@ const message = {
accountId: 'ID da conta',
accountIdPlaceholder: 'Um ID único para diferenciar bots e usá-los depois na configuração e no roteamento.',
setDefaultBot: 'Definir como padrão',
botDuplicateAccountId: 'O ID da conta existe',
botDuplicateField: '{field} existe',
botRequired: 'Adicione pelo menos um bot',
botId: 'ID do bot',
allowFrom: 'Lista de permissões de DM',
allowFromHelper:
'Um ID de remetente por linha. Usado apenas quando a Política de DM é Lista de permissões.',
allowFromPlaceholder: 'Um ID de remetente por linha',
allowlistPolicyHelper: '{0}. Usado apenas quando {1} é Lista de permissões.',
systemPrompt: 'Prompt do sistema',
groupAllowFrom: 'Lista de permissões de grupo',
groupAllowFromHelper:
'Um ID de grupo por linha. Usado apenas quando a Política de grupo é Lista de permissões.',
groupAllowFromPlaceholder: 'Um ID de grupo por linha',
separateSessionByConversation: 'Separar sessão por conversa',
groupSessionScope: 'Escopo da sessão em grupo',
@@ -882,12 +848,11 @@ const message = {
streamingBlock: 'Bloqueante',
streamingProgress: 'Progresso',
allowFromRequired: 'Digite pelo menos uma entrada na lista de permissões',
saveAndRestartGateway: 'Salvar e reiniciar gateway',
pairingCode: 'Código de pareamento',
pairingCodePlaceholder: 'Digite o código de pareamento',
approvePairing: 'Aprovar pareamento',
saveSuccess: 'Salvo com sucesso',
saveAndRestartSuccess: 'Salvo com sucesso. O contêiner está sendo reiniciado automaticamente.',
successAndRestart: '{0}. O contêiner está sendo reiniciado automaticamente.',
pairingApproveSuccess: 'Pareamento aprovado com sucesso',
scanConnect: 'Escanear para conectar',
scanConnectHelper:
@@ -895,13 +860,11 @@ const message = {
channelAutoRestartHelper:
'Ao salvar, o contêiner será reiniciado automaticamente para que a configuração entre em vigor.',
channelDeleteConfirm: 'Excluir a configuração do canal {0}?',
deleteAndRestartSuccess: 'Excluído com sucesso. O contêiner está sendo reiniciado automaticamente.',
customProviderHelper: 'Provedores de modelo personalizados não validam se a conta está disponível',
},
model: {
model: 'Modelo',
localModel: 'Modelos locais',
create: 'Adicionar Modelo',
create_helper: 'Puxar "{0}"',
ollama_doc: 'Você pode visitar o site oficial da Ollama para pesquisar e encontrar mais modelos.',
container_conn_helper: 'Use este endereço para acesso ou conexão entre contêineres',
@@ -920,14 +883,12 @@ const message = {
manualDownload: 'Download manual',
modelSource: 'Fonte do modelo',
repoID: 'ID do repositório',
modelScopeEndpoint: 'Endpoint do ModelScope',
modelScopeToken: 'Token do ModelScope (opcional)',
hfToken: 'HF Token (opcional)',
hfEndpoint: 'Endpoint de aceleração do HuggingFace',
endpointLabel: 'Endpoint do {0}',
acceleratedEndpointLabel: 'Endpoint de aceleração do {0}',
tokenOptionalLabel: 'Token do {0} (opcional)',
searchSource: 'Pesquisar no {0}',
hfEndpointHelper:
'Configure um endpoint de aceleração quando o acesso ao HuggingFace estiver instável. A pesquisa, os detalhes e os downloads usarão esse endereço.',
searchModelScope: 'Pesquisar no ModelScope',
searchHuggingFace: 'Pesquisar no HuggingFace',
sortTrending: 'Tendências',
sortLikes: 'Mais curtidos',
sortDownloads: 'Mais baixados',
@@ -939,7 +900,6 @@ const message = {
progress: 'Progresso',
localDownloaded: 'Baixados',
modelInfo: 'Detalhes do modelo',
modelCard: 'Cartão do modelo',
downloading: 'Baixando',
canceled: 'Cancelado',
downloadQueued: 'Adicionado à fila de downloads',
@@ -996,7 +956,6 @@ const message = {
lbPolicyFailover: 'Failover',
lbPolicyFailoverDesc:
'Usa primeiro a conta de modelo de maior prioridade e muda para a próxima disponível após falha ou cooldown.',
productionProtection: 'Proteção de produção',
maxConcurrency: 'Concorrência máxima',
queueSize: 'Tamanho da fila',
queueTimeoutSeconds: 'Timeout de espera na fila (s)',
@@ -1004,16 +963,10 @@ const message = {
streamIdleTimeoutSeconds: 'Timeout de inatividade do streaming (s)',
maxBodyMb: 'Tamanho máximo do corpo (MB)',
runtimeRefreshSeconds: 'Intervalo de atualização do runtime (s)',
logRetention: 'Retenção de logs',
usageRetentionDays: 'Retenção de estatísticas de uso (dias)',
contentAuditRetentionDays: 'Retenção de auditoria de conformidade de conteúdo (dias)',
logCleanupIntervalHours: 'Intervalo de limpeza de logs (horas)',
requestBodyLog: 'Log do corpo da requisição',
requestBodyLogEsEndpoint: 'Endpoint do Elasticsearch',
requestBodyLogEsAuthMethod: 'Autenticação do Elasticsearch',
requestBodyLogEsUsername: 'Usuário do Elasticsearch',
requestBodyLogEsPassword: 'Senha do Elasticsearch',
requestBodyLogEsApiKey: 'Elasticsearch API Key',
requestBodyLogIndexPrefix: 'Prefixo do índice',
requestBodyLogRetentionDays: 'Retenção do log do corpo da requisição (dias)',
requestBodyLogMaxBodyKb: 'Tamanho máximo do corpo da requisição (KB)',
@@ -1038,10 +991,9 @@ const message = {
esLogCircuitOpen: 'Circuito aberto',
esLogCircuitUntil: 'Circuito ES até',
serviceOperateConfirm: 'Confirmar {0} o serviço de gateway de IA?',
deleteBackendConfirm: 'Excluir conta de modelo {0}?',
deleteTargetConfirm: 'Excluir {0} {1}?',
deleteBackendTitle: 'Excluir conta de modelo',
deleteUserConfirm: 'Excluir usuário {0}?',
userFallback: 'Usuário {0}',
userFallback: 'Usuário excluído (ID: {0})',
requestModel: 'Modelo solicitado',
upstreamModel: 'Modelo upstream',
requestModelPlaceholder: 'ex.: qwen2.5-coder',
@@ -1050,10 +1002,8 @@ const message = {
overview: 'Visão geral',
distribution: 'Distribuição',
usageTrend: 'Tendência de uso',
providerDistribution: 'Distribuição por provedor',
distributionBy: 'Distribuição por {0}',
unmatched: 'Sem correspondência',
modelDistribution: 'Distribuição por modelo',
accountDistribution: 'Distribuição por conta de modelo',
modelAccount: 'Conta de modelo',
serviceProvider: 'Provedor',
tokenUsage: 'Uso de Token',
@@ -1062,8 +1012,6 @@ const message = {
rank: 'Posição',
promptToken: 'Token de entrada',
completionToken: 'Token de saída',
inputTokens: 'Token de entrada',
outputTokens: 'Token de saída',
totalToken: 'Total de Token',
cachedToken: 'Tokens em cache',
cacheHitRate: 'Taxa de acerto do cache',
@@ -1091,7 +1039,6 @@ const message = {
modelGroupModels: 'Modelos solicitados',
modelGroupModelsPlaceholder: 'Selecione ou informe nomes de modelos solicitados',
modelGroupModelCount: '{0} modelos',
deleteModelGroupConfirm: 'Excluir grupo de modelos {0}?',
contentCompliance: 'Content Compliance',
contentAction: 'Action',
actionBlock: 'Block',
@@ -1109,9 +1056,7 @@ const message = {
matchedGroups: 'Matched groups',
importResult: 'Imported {0}, duplicated {1}, invalid {2}',
auditLogs: 'Audit Logs',
apiKeyReset: 'Redefinir',
apiKeyCount: 'Quantidade',
deleteGroupConfirm: 'Excluir o grupo{name}? Esta ação não pode ser desfeita.',
},
skillsHub: {
title: 'Skills Hub',
@@ -1253,7 +1198,6 @@ const message = {
},
benchmark: {
title: 'Benchmark',
create: 'Criar',
launchCommand: 'Comando de inicialização',
retest: 'Testar novamente',
statusRunning: 'Executando',
@@ -1278,8 +1222,6 @@ const message = {
firstTokenLatency: 'Latência do primeiro token',
firstTokenLatencyHelper:
'Tempo entre enviar a requisição e receber o primeiro token. Quanto menor, mais rápida a resposta.',
inputTokens: 'Tokens de entrada',
outputTokens: 'Tokens de saída',
tokenValueHelper: 'Informe um inteiro positivo ou valor com k, ex.: 512, 1k, 32k',
numPrompts: 'Prompts',
concurrency: 'Concorrência',
@@ -1290,17 +1232,7 @@ const message = {
requestRateCustom: 'QPS personalizado',
requestRateCustomPlaceholder: 'Requisições por segundo, ex.: 2.5',
successfulRequests: 'Requisições bem-sucedidas',
failedRequests: 'Requisições com falha',
requestThroughput: 'Throughput de requisições',
ttftMean: 'TTFT médio',
ttftMedian: 'TTFT mediano',
ttftP99: 'TTFT P99',
tpotMean: 'TPOT médio',
tpotMedian: 'TPOT mediano',
tpotP99: 'TPOT P99',
itlMean: 'ITL médio',
itlMedian: 'ITL mediano',
itlP99: 'ITL P99',
timeout: 'Timeout (segundos)',
image: 'Imagem vLLM',
ignoreEos: 'Ignorar EOS',
+16 -83
View File
@@ -10,7 +10,6 @@ const message = {
lingxia: 'LXware',
button: {
run: 'Запустить',
create: 'Создать',
add: 'Добавить',
save: 'Сохранить',
set: 'Настройки',
@@ -87,6 +86,7 @@ const message = {
migrate: 'Мигрировать',
prev: 'Назад',
next: 'Далее',
create: 'Создать',
setDefault: 'Сбросить по умолчанию',
bind: 'Привязать',
tip: 'Подсказка',
@@ -681,47 +681,21 @@ const message = {
account: 'Аккаунт модели',
batchOperation: 'Пакетная операция',
operationType: 'Тип операции',
batchInstall: 'Пакетная установка',
batchUpgrade: 'Пакетное обновление',
batchSkillInstall: 'Пакетная отправка Skill',
batchStart: 'Пакетный запуск',
batchStop: 'Пакетная остановка',
batchRestart: 'Пакетный перезапуск',
batchDelete: 'Пакетное удаление',
batchInstallAgent: 'Пакетная установка агентов',
dispatchAgentInstallTasks: 'Отправить задачи установки агентов',
batchUpgradeAgent: 'Пакетное обновление агентов',
dispatchAgentUpgradeTasks: 'Отправить задачи обновления агентов',
batchInstallAgentSkill: 'Пакетная отправка Skill',
dispatchAgentSkillInstallTasks: 'Отправить задачи установки Skill',
batchStartAgent: 'Пакетный запуск агентов',
dispatchAgentStartTasks: 'Отправить задачи запуска агентов',
batchStopAgent: 'Пакетная остановка агентов',
dispatchAgentStopTasks: 'Отправить задачи остановки агентов',
batchRestartAgent: 'Пакетный перезапуск агентов',
dispatchAgentRestartTasks: 'Отправить задачи перезапуска агентов',
batchDeleteAgent: 'Пакетное удаление агентов',
dispatchAgentDeleteTasks: 'Отправить задачи удаления агентов',
batchAction: 'Пакетно {0}',
installSkillAction: 'Отправить Skill',
batchAgentTask: 'Пакетно {0} агентов',
dispatchAgentTask: 'Отправить задачи для действия {0} агентов',
dispatchTask: 'Отправить задачи {0}',
taskSubmitted: 'Задача {0} отправлена',
allNodes: 'Все узлы',
targetVersion: 'Целевая версия',
skill: 'Skill',
skillSource: 'Источник Skill',
skillKeyword: 'Ключевое слово Skill',
clawHubSkillPlaceholder: 'Сначала найдите и выберите Skill',
batchInstallTaskSubmitted: 'Задача пакетной установки отправлена',
batchUpgradeTaskSubmitted: 'Задача пакетного обновления отправлена',
batchSkillInstallTaskSubmitted: 'Задача пакетной отправки Skill отправлена',
batchStartTaskSubmitted: 'Задача пакетного запуска отправлена',
batchStopTaskSubmitted: 'Задача пакетной остановки отправлена',
batchRestartTaskSubmitted: 'Задача пакетного перезапуска отправлена',
batchDeleteTaskSubmitted: 'Задача пакетного удаления отправлена',
noAccountHint: 'Выберите существующий аккаунт модели или добавьте новый.',
accountCount: '{0} аккаунтов модели',
syncAgents: 'Синхронизировать связанные агенты',
syncAgentsHelper: 'Обновите openclaw.json для агентов, использующих этот аккаунт модели',
openclawType: 'OpenClaw',
copawType: 'QwenPaw',
hermesType: 'Hermes Agent',
appVersion: 'Версия приложения',
webuiPort: 'Порт WebUI',
allowedOrigins: 'Адреса доступа',
@@ -737,7 +711,6 @@ const message = {
fallbackModelsEmpty: 'Резервные модели не настроены',
modelInputTypes: 'Типы ввода',
reasoning: 'Модель рассуждений',
manualModel: 'Ручной ввод',
verified: 'Проверено',
verifySkipped: 'Без проверки',
skillsTab: 'Навыки',
@@ -764,7 +737,6 @@ const message = {
skillsMarketSourceOfficial: 'Официальный',
versionUnsupportedTitle: 'Эта функция не поддерживается в текущей версии',
versionUnsupportedHelper: 'Пожалуйста, обновите OpenClaw до версии {0} или выше.',
skillsStatusDisabled: 'Отключено',
skillsGroupBuiltIn: 'Встроенные',
skillsGroupExternal: 'Внешние',
skillsGroupWorkspace: 'Рабочая область',
@@ -801,7 +773,6 @@ const message = {
'Удалите после завершения ритуала.',
],
},
bindings: 'Привязки',
duplicateBinding: 'Комбинация канала и ID аккаунта должна быть уникальной',
accountIdOptional: 'ID аккаунта (необязательно)',
saveAllMd: 'Сохранить все',
@@ -828,7 +799,6 @@ const message = {
hermesChatDeleteConfirm: 'Удалить сессию {0}?',
hermesChatDeleteSuccess: 'Сессия удалена',
weixin: 'Weixin',
qq: 'QQ',
wecom: 'WeCom',
dingtalk: 'DingTalk',
feishu: 'Feishu',
@@ -850,17 +820,14 @@ const message = {
accountIdPlaceholder:
'Уникальный ID для различения ботов, который после сохранения используется в настройке и маршрутизации.',
setDefaultBot: 'Сделать по умолчанию',
botDuplicateAccountId: 'ID аккаунта уже существует',
botDuplicateField: '{field} уже существует',
botRequired: 'Добавьте хотя бы одного бота',
botId: 'ID бота',
allowFrom: 'Белый список DM',
allowFromHelper: 'Один ID отправителя на строку. Используется только когда политика DM Белый список.',
allowFromPlaceholder: 'Один ID отправителя на строку',
allowlistPolicyHelper: '{0}. Используется только когда {1} Белый список.',
systemPrompt: 'Системный промпт',
groupAllowFrom: 'Белый список групп',
groupAllowFromHelper:
'Один ID группы на строку. Используется только когда групповая политика Белый список.',
groupAllowFromPlaceholder: 'Один ID группы на строку',
separateSessionByConversation: 'Разделять сессии по диалогам',
groupSessionScope: 'Область групповой сессии',
@@ -876,12 +843,11 @@ const message = {
streamingBlock: 'Блокирующий',
streamingProgress: 'Прогресс',
allowFromRequired: 'Введите хотя бы одну запись белого списка',
saveAndRestartGateway: 'Сохранить и перезапустить gateway',
pairingCode: 'Код сопряжения',
pairingCodePlaceholder: 'Введите код сопряжения',
approvePairing: 'Одобрить сопряжение',
saveSuccess: 'Успешно сохранено',
saveAndRestartSuccess: 'Успешно сохранено. Контейнер автоматически перезапускается.',
successAndRestart: '{0}. Контейнер автоматически перезапускается.',
pairingApproveSuccess: 'Сопряжение успешно одобрено',
scanConnect: 'Сканировать для подключения',
scanConnectHelper:
@@ -889,13 +855,11 @@ const message = {
channelAutoRestartHelper:
'После сохранения контейнер будет автоматически перезапущен, чтобы настройки вступили в силу.',
channelDeleteConfirm: 'Удалить конфигурацию канала {0}?',
deleteAndRestartSuccess: 'Удаление выполнено. Контейнер автоматически перезапускается.',
customProviderHelper: 'Для пользовательского провайдера модели доступность учетной записи не проверяется',
},
model: {
model: 'Модель',
localModel: 'Локальные модели',
create: 'Добавить модель',
create_helper: 'Загрузить "{0}"',
ollama_doc: 'Вы можете посетить официальный сайт Ollama, чтобы искать и находить больше моделей.',
container_conn_helper: 'Используйте этот адрес для доступа или подключения между контейнерами',
@@ -914,14 +878,12 @@ const message = {
manualDownload: 'Ручная загрузка',
modelSource: 'Источник модели',
repoID: 'ID репозитория',
modelScopeEndpoint: 'Endpoint ModelScope',
modelScopeToken: 'ModelScope Token (необязательно)',
hfToken: 'HF Token (необязательно)',
hfEndpoint: 'Endpoint ускорения HuggingFace',
endpointLabel: 'Endpoint {0}',
acceleratedEndpointLabel: 'Endpoint ускорения {0}',
tokenOptionalLabel: '{0} Token (необязательно)',
searchSource: 'Поиск в {0}',
hfEndpointHelper:
'Настройте endpoint ускорения, если доступ к HuggingFace нестабилен. Он будет использоваться для поиска, деталей и загрузок.',
searchModelScope: 'Поиск в ModelScope',
searchHuggingFace: 'Поиск в HuggingFace',
sortTrending: 'Популярное',
sortLikes: 'Больше всего лайков',
sortDownloads: 'Больше всего загрузок',
@@ -933,7 +895,6 @@ const message = {
progress: 'Прогресс',
localDownloaded: 'Загружено',
modelInfo: 'Сведения о модели',
modelCard: 'Карточка модели',
downloading: 'Загрузка',
canceled: 'Отменено',
downloadQueued: 'Добавлено в очередь загрузок',
@@ -990,7 +951,6 @@ const message = {
lbPolicyFailover: 'Failover',
lbPolicyFailoverDesc:
'Сначала использует аккаунт модели с наивысшим приоритетом, затем переключается на следующий доступный после ошибки или cooldown.',
productionProtection: 'Защита для production',
maxConcurrency: 'Максимальная параллельность',
queueSize: 'Размер очереди',
queueTimeoutSeconds: 'Тайм-аут ожидания в очереди (с)',
@@ -998,16 +958,10 @@ const message = {
streamIdleTimeoutSeconds: 'Тайм-аут простоя stream (с)',
maxBodyMb: 'Максимальный размер тела (MB)',
runtimeRefreshSeconds: 'Интервал обновления runtime (с)',
logRetention: 'Хранение журналов',
usageRetentionDays: 'Хранение статистики использования (дни)',
contentAuditRetentionDays: 'Хранение аудита соответствия контента (дни)',
logCleanupIntervalHours: 'Интервал очистки журналов (часы)',
requestBodyLog: 'Журнал тела запроса',
requestBodyLogEsEndpoint: 'Адрес Elasticsearch',
requestBodyLogEsAuthMethod: 'Аутентификация Elasticsearch',
requestBodyLogEsUsername: 'Имя пользователя Elasticsearch',
requestBodyLogEsPassword: 'Пароль Elasticsearch',
requestBodyLogEsApiKey: 'Elasticsearch API Key',
requestBodyLogIndexPrefix: 'Префикс индекса',
requestBodyLogRetentionDays: 'Хранение журнала тела запроса (дни)',
requestBodyLogMaxBodyKb: 'Максимальный размер тела запроса (KB)',
@@ -1032,10 +986,9 @@ const message = {
esLogCircuitOpen: 'Цепь разомкнута',
esLogCircuitUntil: 'ES разомкнута до',
serviceOperateConfirm: 'Подтвердить {0} сервис AI-шлюза?',
deleteBackendConfirm: 'Удалить аккаунт модели {0}?',
deleteTargetConfirm: 'Удалить {0} {1}?',
deleteBackendTitle: 'Удалить аккаунт модели',
deleteUserConfirm: 'Удалить пользователя {0}?',
userFallback: 'Пользователь {0}',
userFallback: 'Удаленный пользователь (ID: {0})',
requestModel: 'Запрошенная модель',
upstreamModel: 'Upstream-модель',
requestModelPlaceholder: 'например: qwen2.5-coder',
@@ -1044,10 +997,8 @@ const message = {
overview: 'Обзор',
distribution: 'Распределение',
usageTrend: 'Тренд использования',
providerDistribution: 'Распределение по провайдерам',
distributionBy: 'Распределение по {0}',
unmatched: 'Не сопоставлено',
modelDistribution: 'Распределение по моделям',
accountDistribution: 'Распределение по аккаунтам моделей',
modelAccount: 'Аккаунт модели',
serviceProvider: 'Провайдер',
tokenUsage: 'Использование Token',
@@ -1056,8 +1007,6 @@ const message = {
rank: 'Место',
promptToken: 'Входные Token',
completionToken: 'Выходные Token',
inputTokens: 'Входные Token',
outputTokens: 'Выходные Token',
totalToken: 'Всего Token',
cachedToken: 'Кэшированные Token',
cacheHitRate: 'Попадания в кэш',
@@ -1085,7 +1034,6 @@ const message = {
modelGroupModels: 'Запрошенные модели',
modelGroupModelsPlaceholder: 'Выберите или введите имена запрошенных моделей',
modelGroupModelCount: '{0} моделей',
deleteModelGroupConfirm: 'Удалить группу моделей {0}?',
contentCompliance: 'Content Compliance',
contentAction: 'Action',
actionBlock: 'Block',
@@ -1103,9 +1051,7 @@ const message = {
matchedGroups: 'Matched groups',
importResult: 'Imported {0}, duplicated {1}, invalid {2}',
auditLogs: 'Audit Logs',
apiKeyReset: 'Сбросить',
apiKeyCount: 'Количество',
deleteGroupConfirm: 'Удалить группу{name}? Это действие нельзя отменить.',
},
skillsHub: {
title: 'Skills Hub',
@@ -1247,7 +1193,6 @@ const message = {
},
benchmark: {
title: 'Бенчмарк',
create: 'Создать',
launchCommand: 'Команда запуска',
retest: 'Повторить тест',
statusRunning: 'Выполняется',
@@ -1273,8 +1218,6 @@ const message = {
firstTokenLatency: 'Задержка первого токена',
firstTokenLatencyHelper:
'Время от отправки запроса до получения первого токена. Чем ниже значение, тем быстрее ответ.',
inputTokens: 'Входные токены',
outputTokens: 'Выходные токены',
tokenValueHelper: 'Введите положительное целое число или значение с k, например 512, 1k, 32k',
numPrompts: 'Промпты',
concurrency: 'Параллелизм',
@@ -1285,17 +1228,7 @@ const message = {
requestRateCustom: 'Пользовательский QPS',
requestRateCustomPlaceholder: 'Запросов в секунду, например 2.5',
successfulRequests: 'Успешные запросы',
failedRequests: 'Неуспешные запросы',
requestThroughput: 'Пропускная способность запросов',
ttftMean: 'Средний TTFT',
ttftMedian: 'Медианный TTFT',
ttftP99: 'P99 TTFT',
tpotMean: 'Средний TPOT',
tpotMedian: 'Медианный TPOT',
tpotP99: 'P99 TPOT',
itlMean: 'Средний ITL',
itlMedian: 'Медианный ITL',
itlP99: 'P99 ITL',
timeout: 'Тайм-аут (секунды)',
image: 'Образ vLLM',
ignoreEos: 'Игнорировать EOS',
+15 -82
View File
@@ -685,47 +685,21 @@ const message = {
account: 'Model hesabı',
batchOperation: 'Toplu işlem',
operationType: 'İşlem türü',
batchInstall: 'Toplu kurulum',
batchUpgrade: 'Toplu yükseltme',
batchSkillInstall: 'Skill toplu dağıt',
batchStart: 'Toplu başlat',
batchStop: 'Toplu durdur',
batchRestart: 'Toplu yeniden başlat',
batchDelete: 'Toplu sil',
batchInstallAgent: 'Aracıları toplu kur',
dispatchAgentInstallTasks: 'Aracı kurulum görevlerini gönder',
batchUpgradeAgent: 'Aracıları toplu yükselt',
dispatchAgentUpgradeTasks: 'Aracı yükseltme görevlerini gönder',
batchInstallAgentSkill: 'Skill toplu dağıt',
dispatchAgentSkillInstallTasks: 'Skill kurulum görevlerini gönder',
batchStartAgent: 'Aracıları toplu başlat',
dispatchAgentStartTasks: 'Aracı başlatma görevlerini gönder',
batchStopAgent: 'Aracıları toplu durdur',
dispatchAgentStopTasks: 'Aracı durdurma görevlerini gönder',
batchRestartAgent: 'Aracıları toplu yeniden başlat',
dispatchAgentRestartTasks: 'Aracı yeniden başlatma görevlerini gönder',
batchDeleteAgent: 'Aracıları toplu sil',
dispatchAgentDeleteTasks: 'Aracı silme görevlerini gönder',
batchAction: 'Toplu {0}',
installSkillAction: 'Skill dağıt',
batchAgentTask: 'Aracıları toplu {0}',
dispatchAgentTask: 'Aracı {0} görevlerini gönder',
dispatchTask: '{0} görevlerini gönder',
taskSubmitted: '{0} görevi gönderildi',
allNodes: 'Tüm düğümler',
targetVersion: 'Hedef sürüm',
skill: 'Skill',
skillSource: 'Skill Kaynağı',
skillKeyword: 'Skill Anahtar Kelimesi',
clawHubSkillPlaceholder: 'Önce bir Skill arayın ve seçin',
batchInstallTaskSubmitted: 'Toplu kurulum görevi gönderildi',
batchUpgradeTaskSubmitted: 'Toplu yükseltme görevi gönderildi',
batchSkillInstallTaskSubmitted: 'Skill toplu dağıtım görevi gönderildi',
batchStartTaskSubmitted: 'Toplu başlatma görevi gönderildi',
batchStopTaskSubmitted: 'Toplu durdurma görevi gönderildi',
batchRestartTaskSubmitted: 'Toplu yeniden başlatma görevi gönderildi',
batchDeleteTaskSubmitted: 'Toplu silme görevi gönderildi',
noAccountHint: 'Mevcut bir model hesabını seçin veya yeni bir tane ekleyin.',
accountCount: '{0} model hesabı',
syncAgents: 'İlişkili ajanları senkronize et',
syncAgentsHelper: 'Bu model hesabını kullanan ajanlar için openclaw.json dosyasını güncelleyin',
openclawType: 'OpenClaw',
copawType: 'QwenPaw',
hermesType: 'Hermes Agent',
appVersion: 'Uygulama sürümü',
webuiPort: 'WebUI portu',
allowedOrigins: 'Erişim adresleri',
@@ -742,7 +716,6 @@ const message = {
fallbackModelsEmpty: 'Yapılandırılmış yedek model yok',
modelInputTypes: 'Girdi türleri',
reasoning: 'Akıl yürütme modeli',
manualModel: 'Manuel giriş',
verified: 'Doğrulandı',
verifySkipped: 'Doğrulama yok',
skillsTab: 'Yetenekler',
@@ -769,7 +742,6 @@ const message = {
skillsMarketSourceOfficial: 'Resmi',
versionUnsupportedTitle: 'Bu özellik mevcut sürümde desteklenmiyor',
versionUnsupportedHelper: 'Lütfen OpenClawı {0} veya üzeri bir sürüme yükseltin.',
skillsStatusDisabled: 'Devre dışı',
skillsGroupBuiltIn: 'Yerleşik',
skillsGroupExternal: 'Harici',
skillsGroupWorkspace: 'Çalışma alanı',
@@ -809,7 +781,6 @@ const message = {
'Ritüel tamamlandıktan sonra silin.',
],
},
bindings: 'Bağlamalar',
duplicateBinding: 'Kanal ve hesap kimligi kombinasyonu benzersiz olmalidir',
accountIdOptional: 'Hesap ID (İsteğe bağlı)',
saveAllMd: 'Tümünü kaydet',
@@ -836,7 +807,6 @@ const message = {
hermesChatDeleteConfirm: '{0} oturumu silinsin mi?',
hermesChatDeleteSuccess: 'Oturum silindi',
weixin: 'Weixin',
qq: 'QQ',
wecom: 'WeCom',
dingtalk: 'DingTalk',
feishu: 'Feishu',
@@ -858,17 +828,14 @@ const message = {
accountIdPlaceholder:
'Botlari ayirt etmek ve sonraki yapılandırma ile yönlendirme için kullanılan benzersiz kimlik.',
setDefaultBot: 'Varsayılan yap',
botDuplicateAccountId: 'Hesap ID zaten mevcut',
botDuplicateField: '{field} zaten mevcut',
botRequired: 'En az bir bot ekleyin',
botId: 'Bot ID',
allowFrom: 'DM izin listesi',
allowFromHelper: 'Her satıra bir gönderici ID yazın. Yalnızca DM İlkesi İzin listesi olduğunda kullanılır.',
allowFromPlaceholder: 'Her satıra bir gönderici ID',
allowlistPolicyHelper: '{0}. Yalnızca {1} İzin listesi olduğunda kullanılır.',
systemPrompt: 'Sistem istemi',
groupAllowFrom: 'Grup izin listesi',
groupAllowFromHelper:
'Her satıra bir grup ID yazın. Yalnızca Grup İlkesi İzin listesi olduğunda kullanılır.',
groupAllowFromPlaceholder: 'Her satıra bir grup ID',
separateSessionByConversation: 'Oturumu konuşmaya göre ayır',
groupSessionScope: 'Grup oturum kapsamı',
@@ -884,12 +851,11 @@ const message = {
streamingBlock: 'Bloklayıcı',
streamingProgress: 'İlerleme',
allowFromRequired: 'En az bir izin listesi girdisi girin',
saveAndRestartGateway: 'Kaydet ve gatewayi yeniden başlat',
pairingCode: 'Eşleştirme kodu',
pairingCodePlaceholder: 'Eşleştirme kodunu girin',
approvePairing: 'Eşleştirmeyi onayla',
saveSuccess: 'Başarıyla kaydedildi',
saveAndRestartSuccess: 'Başarıyla kaydedildi. Konteyner otomatik olarak yeniden başlatılıyor.',
successAndRestart: '{0}. Konteyner otomatik olarak yeniden başlatılıyor.',
pairingApproveSuccess: 'Eşleştirme başarıyla onaylandı',
scanConnect: 'Tara ve bağlan',
scanConnectHelper:
@@ -897,13 +863,11 @@ const message = {
channelAutoRestartHelper:
'Kaydettiğinizde ayarların etkili olması için konteyner otomatik olarak yeniden başlatılır.',
channelDeleteConfirm: '{0} kanal yapılandırması silinsin mi?',
deleteAndRestartSuccess: 'Başarıyla silindi. Konteyner otomatik olarak yeniden başlatılıyor.',
customProviderHelper: 'Özel model sağlayıcısında hesabın kullanılabilirliği doğrulanmaz',
},
model: {
model: 'Model',
localModel: 'Yerel Modeller',
create: 'Model Ekle',
create_helper: '"{0}" çek',
ollama_doc: 'Daha fazla model aramak ve bulmak için Ollama resmi web sitesini ziyaret edebilirsiniz.',
container_conn_helper: 'Konteynerler arası erişim veya bağlantı için bu adresi kullanın',
@@ -922,14 +886,12 @@ const message = {
manualDownload: 'Manuel indirme',
modelSource: 'Model kaynağı',
repoID: 'Depo ID',
modelScopeEndpoint: 'ModelScope endpointi',
modelScopeToken: 'ModelScope Token (isteğe bağlı)',
hfToken: 'HF Token (isteğe bağlı)',
hfEndpoint: 'HuggingFace hızlandırma endpointi',
endpointLabel: '{0} endpointi',
acceleratedEndpointLabel: '{0} hızlandırma endpointi',
tokenOptionalLabel: '{0} Token (isteğe bağlı)',
searchSource: '{0} ara',
hfEndpointHelper:
'HuggingFace erişimi kararsız olduğunda bir hızlandırma endpointi yapılandırın. Arama, ayrıntılar ve indirmeler bunu kullanır.',
searchModelScope: 'ModelScope ara',
searchHuggingFace: 'HuggingFace ara',
sortTrending: 'Popüler trendler',
sortLikes: 'En çok beğenilen',
sortDownloads: 'En çok indirilenler',
@@ -941,7 +903,6 @@ const message = {
progress: 'İlerleme',
localDownloaded: 'İndirilenler',
modelInfo: 'Model ayrıntıları',
modelCard: 'Model kartı',
downloading: 'İndiriliyor',
canceled: 'İptal edildi',
downloadQueued: 'İndirme kuyruğuna eklendi',
@@ -998,7 +959,6 @@ const message = {
lbPolicyFailover: 'Failover',
lbPolicyFailoverDesc:
'Önce en yüksek öncelikli model hesabını kullanır, hata veya cooldown sonrası bir sonraki kullanılabilir hesaba geçer.',
productionProtection: 'Üretim koruması',
maxConcurrency: 'Maksimum eşzamanlılık',
queueSize: 'Kuyruk boyutu',
queueTimeoutSeconds: 'Kuyruk bekleme zaman aşımı (sn)',
@@ -1006,16 +966,10 @@ const message = {
streamIdleTimeoutSeconds: 'Akış boşta zaman aşımı (sn)',
maxBodyMb: 'Maksimum gövde boyutu (MB)',
runtimeRefreshSeconds: 'Runtime yenileme aralığı (sn)',
logRetention: 'Log Saklama',
usageRetentionDays: 'Kullanım İstatistikleri Saklama (gün)',
contentAuditRetentionDays: 'İçerik Uyumluluğu Denetim Saklama (gün)',
logCleanupIntervalHours: 'Log Temizleme Aralığı (saat)',
requestBodyLog: 'İstek Gövdesi Logu',
requestBodyLogEsEndpoint: 'Elasticsearch Endpoint',
requestBodyLogEsAuthMethod: 'Elasticsearch Kimlik Doğrulama',
requestBodyLogEsUsername: 'Elasticsearch Kullanıcı Adı',
requestBodyLogEsPassword: 'Elasticsearch Parolası',
requestBodyLogEsApiKey: 'Elasticsearch API Key',
requestBodyLogIndexPrefix: 'İndeks Öneki',
requestBodyLogRetentionDays: 'İstek Gövdesi Log Saklama (gün)',
requestBodyLogMaxBodyKb: 'Maksimum İstek Gövdesi Boyutu (KB)',
@@ -1040,10 +994,9 @@ const message = {
esLogCircuitOpen: 'Devre açık',
esLogCircuitUntil: 'ES devresi şu zamana kadar',
serviceOperateConfirm: 'AI Geçidi servisini {0} onaylıyor musunuz?',
deleteBackendConfirm: 'Model hesabı {0} silinsin mi?',
deleteTargetConfirm: '{0} {1} silinsin mi?',
deleteBackendTitle: 'Model hesabını sil',
deleteUserConfirm: 'Kullanıcı {0} silinsin mi?',
userFallback: 'Kullanıcı {0}',
userFallback: 'Silinen kullanıcı (ID: {0})',
requestModel: 'İstek modeli',
upstreamModel: 'Upstream model',
requestModelPlaceholder: 'örn. qwen2.5-coder',
@@ -1052,10 +1005,8 @@ const message = {
overview: 'Genel bakış',
distribution: 'Dağılım',
usageTrend: 'Kullanım eğilimi',
providerDistribution: 'Sağlayıcı dağılımı',
distributionBy: '{0} dağılımı',
unmatched: 'Eşleşmedi',
modelDistribution: 'Model dağılımı',
accountDistribution: 'Model hesabı dağılımı',
modelAccount: 'Model hesabı',
serviceProvider: 'Sağlayıcı',
tokenUsage: 'Token kullanımı',
@@ -1064,8 +1015,6 @@ const message = {
rank: 'Sıra',
promptToken: 'Girdi Token',
completionToken: 'Çıktı Token',
inputTokens: 'Girdi Token',
outputTokens: 'Çıktı Token',
totalToken: 'Toplam Token',
cachedToken: 'Önbellek Token',
cacheHitRate: 'Önbellek İsabet Oranı',
@@ -1093,7 +1042,6 @@ const message = {
modelGroupModels: 'İstek Modelleri',
modelGroupModelsPlaceholder: 'İstek modeli adlarını seçin veya girin',
modelGroupModelCount: '{0} model',
deleteModelGroupConfirm: '{0} model grubu silinsin mi?',
contentCompliance: 'Content Compliance',
contentAction: 'Action',
actionBlock: 'Block',
@@ -1111,9 +1059,7 @@ const message = {
matchedGroups: 'Matched groups',
importResult: 'Imported {0}, duplicated {1}, invalid {2}',
auditLogs: 'Audit Logs',
apiKeyReset: 'Sıfırla',
apiKeyCount: 'Miktar',
deleteGroupConfirm: '"{name}" grubunu sil? Bu işlem geri alınamaz.',
},
skillsHub: {
title: 'Skills Hub',
@@ -1253,7 +1199,6 @@ const message = {
},
benchmark: {
title: 'Benchmark',
create: 'Oluştur',
launchCommand: 'Başlatma Komutu',
retest: 'Yeniden test et',
statusRunning: 'Çalışıyor',
@@ -1278,8 +1223,6 @@ const message = {
firstTokenLatency: 'İlk Token Gecikmesi',
firstTokenLatencyHelper:
'İsteğin gönderilmesinden ilk token alınana kadar geçen süre. Daha düşük değer daha hızlı yanıttır.',
inputTokens: 'Giriş Token',
outputTokens: 'Çıkış Token',
tokenValueHelper: 'Pozitif tam sayı veya k değeri girin, örn. 512, 1k, 32k',
numPrompts: 'Prompt',
concurrency: 'Eşzamanlılık',
@@ -1290,17 +1233,7 @@ const message = {
requestRateCustom: 'Özel QPS',
requestRateCustomPlaceholder: 'Saniye başına istek, örn. 2.5',
successfulRequests: 'Başarılı istekler',
failedRequests: 'Başarısız istekler',
requestThroughput: 'İstek Throughput',
ttftMean: 'Ortalama TTFT',
ttftMedian: 'Medyan TTFT',
ttftP99: 'P99 TTFT',
tpotMean: 'Ortalama TPOT',
tpotMedian: 'Medyan TPOT',
tpotP99: 'P99 TPOT',
itlMean: 'Ortalama ITL',
itlMedian: 'Medyan ITL',
itlP99: 'P99 ITL',
timeout: 'Zaman aşımı (saniye)',
image: 'vLLM İmajı',
ignoreEos: "EOS'u yok say",
+15 -81
View File
@@ -651,47 +651,21 @@ const message = {
account: '模型帳號',
batchOperation: '批量操作',
operationType: '操作類型',
batchInstall: '批量安裝',
batchUpgrade: '批量升級',
batchSkillInstall: '批量下發 Skill',
batchStart: '批量啟動',
batchStop: '批量停止',
batchRestart: '批量重啟',
batchDelete: '批量刪除',
batchInstallAgent: '批量安裝智能體',
dispatchAgentInstallTasks: '下發智能體安裝任務',
batchUpgradeAgent: '批量升級智能體',
dispatchAgentUpgradeTasks: '下發智能體升級任務',
batchInstallAgentSkill: '批量下發 Skill',
dispatchAgentSkillInstallTasks: '下發 Skill 安裝任務',
batchStartAgent: '批量啟動智能體',
dispatchAgentStartTasks: '下發智能體啟動任務',
batchStopAgent: '批量停止智能體',
dispatchAgentStopTasks: '下發智能體停止任務',
batchRestartAgent: '批量重啟智能體',
dispatchAgentRestartTasks: '下發智能體重啟任務',
batchDeleteAgent: '批量刪除智能體',
dispatchAgentDeleteTasks: '下發智能體刪除任務',
batchAction: '批量{0}',
installSkillAction: '下發 Skill',
batchAgentTask: '批量{0}智能體',
dispatchAgentTask: '下發智能體{0}任務',
dispatchTask: '下發{0}任務',
taskSubmitted: '{0}任務已下發',
allNodes: '所有節點',
targetVersion: '目標版本',
skill: 'Skill',
skillSource: 'Skill 來源',
skillKeyword: 'Skill 關鍵詞',
clawHubSkillPlaceholder: '請先搜尋並選擇 Skill',
batchInstallTaskSubmitted: '批量安裝任務已下發',
batchUpgradeTaskSubmitted: '批量升級任務已下發',
batchSkillInstallTaskSubmitted: '批量下發 Skill 任務已下發',
batchStartTaskSubmitted: '批量啟動任務已下發',
batchStopTaskSubmitted: '批量停止任務已下發',
batchRestartTaskSubmitted: '批量重啟任務已下發',
batchDeleteTaskSubmitted: '批量刪除任務已下發',
noAccountHint: '選擇已有模型帳號或直接建立',
accountCount: '模型帳號 {0} ',
syncAgents: '同步關聯智能體',
syncAgentsHelper: '更新使用該模型帳號的智能體 openclaw.json',
openclawType: 'OpenClaw',
copawType: 'QwenPaw',
hermesType: 'Hermes Agent',
appVersion: '應用版本',
webuiPort: 'WebUI ',
allowedOrigins: '訪問地址',
@@ -707,7 +681,6 @@ const message = {
fallbackModelsEmpty: '尚未配置備用模型',
modelInputTypes: '輸入類型',
reasoning: '推理模型',
manualModel: '手動輸入模型',
verified: '驗證狀態',
verifySkipped: '不驗證',
skillsTab: '技能',
@@ -732,7 +705,6 @@ const message = {
skillsMarketSourceOfficial: '官方',
versionUnsupportedTitle: '當前版本暫不支援該功能',
versionUnsupportedHelper: '請升級 OpenClaw {0} 或以上版本後使用',
skillsStatusDisabled: '已禁用',
skillsGroupBuiltIn: '內置',
skillsGroupExternal: '外部',
skillsGroupWorkspace: '工作區',
@@ -759,7 +731,6 @@ const message = {
],
'BOOTSTRAP.md': ['一次性的首次執行儀式', '只會在全新的 workspace 中建立', '儀式完成後請刪除它'],
},
bindings: '綁定',
duplicateBinding: '頻道和帳號 ID 不能重複',
accountIdOptional: '帳號 ID可選',
saveAllMd: '保存全部',
@@ -784,7 +755,6 @@ const message = {
hermesChatDeleteConfirm: '確認刪除會話 {0}',
hermesChatDeleteSuccess: '會話已刪除',
weixin: '微信',
qq: 'QQ',
wecom: '企業微信',
dingtalk: '釘釘',
feishu: '飛書',
@@ -805,16 +775,14 @@ const message = {
accountId: '帳戶 ID',
accountIdPlaceholder: '用於區分不同 Bot 的唯一標識儲存後用於配置和路由識別',
setDefaultBot: '設為預設 Bot',
botDuplicateAccountId: '帳戶 ID 不能重複',
botDuplicateField: '{field} 不能重複',
botRequired: '請至少新增一個 Bot',
botId: 'Bot ID',
allowFrom: '私聊白名單',
allowFromHelper: '一行一個發送方識別碼僅在私聊策略為白名單時生效',
allowFromPlaceholder: '一行一個發送方識別碼',
allowlistPolicyHelper: '{0}僅在{1}為白名單時生效',
systemPrompt: '系統提示詞',
groupAllowFrom: '群組白名單',
groupAllowFromHelper: '一行一個群組識別碼僅在群組策略為白名單時生效',
groupAllowFromPlaceholder: '一行一個群組識別碼',
separateSessionByConversation: '按會話隔離',
groupSessionScope: '群會話範圍',
@@ -830,24 +798,21 @@ const message = {
streamingBlock: '阻塞輸出',
streamingProgress: '進度輸出',
allowFromRequired: '請至少填寫一個白名單項',
saveAndRestartGateway: '保存並重新啟動網關',
pairingCode: '配對碼',
pairingCodePlaceholder: '請輸入配對碼',
approvePairing: '批准配對',
saveSuccess: '保存成功',
saveAndRestartSuccess: '保存成功容器正在自動重新啟動',
successAndRestart: '{0}容器正在自動重新啟動',
pairingApproveSuccess: '配對成功',
scanConnect: '掃碼對接',
scanConnectHelper: '點擊後將在任務日誌中顯示 QR Code掃碼確認成功後將自動重新啟動容器',
channelAutoRestartHelper: '保存後將自動重新啟動容器以使設定生效',
channelDeleteConfirm: '確認刪除 {0} 頻道設定',
deleteAndRestartSuccess: '刪除成功容器正在自動重新啟動',
customProviderHelper: '自訂模型供應商不驗證帳號是否可用',
},
model: {
model: '模型',
localModel: '本地模型',
create: '新增模型',
create_helper: '拉取 "{0}"',
ollama_doc: '您可以瀏覽 Ollama 官方網站搜尋並尋找更多模型',
container_conn_helper: '容器間瀏覽或連接使用此地址',
@@ -865,13 +830,11 @@ const message = {
manualDownload: '手動下載',
modelSource: '模型來源',
repoID: '倉庫 ID',
modelScopeEndpoint: 'ModelScope 地址',
modelScopeToken: 'ModelScope Token可選',
hfToken: 'HF Token可選',
hfEndpoint: 'HuggingFace 加速地址',
endpointLabel: '{0} 地址',
acceleratedEndpointLabel: '{0} 加速地址',
tokenOptionalLabel: '{0} Token可選',
searchSource: '搜尋 {0}',
hfEndpointHelper: '國內存取 HuggingFace 不穩定時可設定加速地址搜尋詳情和下載都會使用該地址',
searchModelScope: '搜尋 ModelScope',
searchHuggingFace: '搜尋 HuggingFace',
sortTrending: '熱門趨勢',
sortLikes: '按讚最多',
sortDownloads: '下載最多',
@@ -883,7 +846,6 @@ const message = {
progress: '進度',
localDownloaded: '已下載',
modelInfo: '模型詳情',
modelCard: '模型卡片',
downloading: '下載中',
canceled: '已取消',
downloadQueued: '已加入下載佇列',
@@ -937,7 +899,6 @@ const message = {
'根據模型帳號權重分配請求權重越高承擔的請求越多適合後端性能不同的場景',
lbPolicyFailover: '故障轉移',
lbPolicyFailoverDesc: '優先使用優先級最高的模型帳號失敗或冷卻後再切換到下一個可用帳號',
productionProtection: '生產保護',
maxConcurrency: '最大併發',
queueSize: '等待佇列大小',
queueTimeoutSeconds: '佇列等待逾時',
@@ -945,16 +906,10 @@ const message = {
streamIdleTimeoutSeconds: '串流空閒逾時',
maxBodyMb: '最大請求體MB',
runtimeRefreshSeconds: 'Runtime 刷新間隔',
logRetention: '日誌保留',
usageRetentionDays: '用量統計保留天數',
contentAuditRetentionDays: '內容合規審計日誌保留天數',
logCleanupIntervalHours: '日誌清理間隔小時',
requestBodyLog: '請求體日誌',
requestBodyLogEsEndpoint: 'Elasticsearch 地址',
requestBodyLogEsAuthMethod: 'Elasticsearch 認證方式',
requestBodyLogEsUsername: 'Elasticsearch 使用者名稱',
requestBodyLogEsPassword: 'Elasticsearch 密碼',
requestBodyLogEsApiKey: 'Elasticsearch API Key',
requestBodyLogIndexPrefix: '索引前綴',
requestBodyLogRetentionDays: '請求體日誌保留天數',
requestBodyLogMaxBodyKb: '單請求體最大保存大小KB',
@@ -979,10 +934,9 @@ const message = {
esLogCircuitOpen: '熔斷中',
esLogCircuitUntil: 'ES 熔斷結束時間',
serviceOperateConfirm: '確認{0} AI 閘道服務',
deleteBackendConfirm: '確認刪除模型帳號 {0}',
deleteTargetConfirm: '確認刪除{0} {1}',
deleteBackendTitle: '刪除模型帳號',
deleteUserConfirm: '確認刪除使用者 {0}',
userFallback: '使用者 {0}',
userFallback: '刪除使用者 (ID: {0})',
requestModel: '請求模型',
upstreamModel: '上游模型',
requestModelPlaceholder: ' qwen2.5-coder',
@@ -991,10 +945,8 @@ const message = {
overview: '概覽',
distribution: '分佈',
usageTrend: '使用趨勢',
providerDistribution: '服務商分佈',
distributionBy: '{0}分佈',
unmatched: '未匹配',
modelDistribution: '按模型分佈',
accountDistribution: '按模型帳號分佈',
modelAccount: '模型帳號',
serviceProvider: '服務商',
tokenUsage: 'Token 用量',
@@ -1003,8 +955,6 @@ const message = {
rank: '排名',
promptToken: '輸入 Token',
completionToken: '輸出 Token',
inputTokens: '輸入 Token',
outputTokens: '輸出 Token',
totalToken: ' Token',
cachedToken: '快取 Token',
cacheHitRate: '快取命中率',
@@ -1032,7 +982,6 @@ const message = {
modelGroupModels: '請求模型',
modelGroupModelsPlaceholder: '請選擇或輸入請求模型名稱',
modelGroupModelCount: '{0} 個模型',
deleteModelGroupConfirm: '確認刪除模型組 {0}',
contentCompliance: '內容合規',
contentAction: '處理動作',
actionBlock: '阻斷',
@@ -1050,9 +999,7 @@ const message = {
matchedGroups: '命中分組',
importResult: '匯入成功 {0} 重複 {1} 無效 {2} ',
auditLogs: '審計日誌',
apiKeyReset: '重設',
apiKeyCount: '數量',
deleteGroupConfirm: '確定刪除群組{name}此操作無法復原',
},
skillsHub: {
title: 'Skills Hub',
@@ -1186,7 +1133,6 @@ const message = {
},
benchmark: {
title: '基準測試',
create: '建立',
launchCommand: '啟動命令',
retest: '重新測試',
statusRunning: '執行中',
@@ -1208,8 +1154,6 @@ const message = {
totalThroughputHelper: '每秒處理的輸入與輸出 Token 總數用於衡量整體處理能力',
firstTokenLatency: ' Token 延遲',
firstTokenLatencyHelper: '從請求送出到收到第一個 Token 的時間越低表示回應越快',
inputTokens: '輸入 Token',
outputTokens: '輸出 Token',
tokenValueHelper: '請輸入正整數或 k 單位例如 5121k32k',
numPrompts: '請求數量',
concurrency: '併發數',
@@ -1220,17 +1164,7 @@ const message = {
requestRateCustom: '自訂 QPS',
requestRateCustomPlaceholder: '請輸入每秒請求數 2.5',
successfulRequests: '成功請求',
failedRequests: '失敗請求',
requestThroughput: '請求吞吐',
ttftMean: 'TTFT 平均',
ttftMedian: 'TTFT 中位數',
ttftP99: 'TTFT P99',
tpotMean: 'TPOT 平均',
tpotMedian: 'TPOT 中位數',
tpotP99: 'TPOT P99',
itlMean: 'ITL 平均',
itlMedian: 'ITL 中位數',
itlP99: 'ITL P99',
timeout: '逾時時間',
image: 'vLLM 映像',
ignoreEos: '忽略 EOS',
+15 -68
View File
@@ -648,47 +648,21 @@ const message = {
account: '模型账号',
batchOperation: '批量操作',
operationType: '操作类型',
batchInstall: '批量安装',
batchUpgrade: '批量升级',
batchSkillInstall: '批量下发 Skill',
batchStart: '批量启动',
batchStop: '批量停止',
batchRestart: '批量重启',
batchDelete: '批量删除',
batchInstallAgent: '批量安装智能体',
dispatchAgentInstallTasks: '下发智能体安装任务',
batchUpgradeAgent: '批量升级智能体',
dispatchAgentUpgradeTasks: '下发智能体升级任务',
batchInstallAgentSkill: '批量下发 Skill',
dispatchAgentSkillInstallTasks: '下发 Skill 安装任务',
batchStartAgent: '批量启动智能体',
dispatchAgentStartTasks: '下发智能体启动任务',
batchStopAgent: '批量停止智能体',
dispatchAgentStopTasks: '下发智能体停止任务',
batchRestartAgent: '批量重启智能体',
dispatchAgentRestartTasks: '下发智能体重启任务',
batchDeleteAgent: '批量删除智能体',
dispatchAgentDeleteTasks: '下发智能体删除任务',
batchAction: '批量{0}',
installSkillAction: '下发 Skill',
batchAgentTask: '批量{0}智能体',
dispatchAgentTask: '下发智能体{0}任务',
dispatchTask: '下发{0}任务',
taskSubmitted: '{0}任务已下发',
allNodes: '所有节点',
targetVersion: '目标版本',
skill: 'Skill',
skillSource: 'Skill 来源',
skillKeyword: 'Skill 关键词',
clawHubSkillPlaceholder: '请先搜索并选择 Skill',
batchInstallTaskSubmitted: '批量安装任务已下发',
batchUpgradeTaskSubmitted: '批量升级任务已下发',
batchSkillInstallTaskSubmitted: '批量下发 Skill 任务已下发',
batchStartTaskSubmitted: '批量启动任务已下发',
batchStopTaskSubmitted: '批量停止任务已下发',
batchRestartTaskSubmitted: '批量重启任务已下发',
batchDeleteTaskSubmitted: '批量删除任务已下发',
noAccountHint: '选择已有模型账号或直接创建',
accountCount: '模型账号 {0} ',
syncAgents: '同步关联智能体',
syncAgentsHelper: '更新使用该模型账号的智能体 openclaw.json',
openclawType: 'OpenClaw',
copawType: 'QwenPaw',
hermesType: 'Hermes Agent',
appVersion: '应用版本',
webuiPort: 'WebUI 端口',
allowedOrigins: '访问地址',
@@ -704,7 +678,6 @@ const message = {
fallbackModelsEmpty: '尚未配置备用模型',
modelInputTypes: '输入类型',
reasoning: '推理模型',
manualModel: '手动输入模型',
verified: '验证状态',
verifySkipped: '不验证',
skillsTab: '技能',
@@ -729,7 +702,6 @@ const message = {
skillsMarketSourceOfficial: '官方',
versionUnsupportedTitle: '当前版本暂不支持该功能',
versionUnsupportedHelper: '请升级 OpenClaw {0} 或以上版本后使用',
skillsStatusDisabled: '已禁用',
skillsGroupBuiltIn: '内置',
skillsGroupExternal: '外部',
skillsGroupWorkspace: '工作区',
@@ -752,7 +724,6 @@ const message = {
],
'BOOTSTRAP.md': ['首次运行引导流程', '只会在全新的工作区中创建'],
},
bindings: '绑定',
duplicateBinding: '频道和账号 ID 不能重复',
accountIdOptional: '账号 ID可选',
saveAllMd: '保存全部',
@@ -777,7 +748,6 @@ const message = {
hermesChatDeleteConfirm: '确认删除会话 {0}',
hermesChatDeleteSuccess: '会话已删除',
weixin: '微信',
qq: 'QQ',
wecom: '企业微信',
dingtalk: '钉钉',
feishu: '飞书',
@@ -798,16 +768,14 @@ const message = {
accountId: '账户 ID',
accountIdPlaceholder: '用于区分不同 Bot 的唯一标识保存后用于配置和路由识别',
setDefaultBot: '设为默认 Bot',
botDuplicateAccountId: '账户 ID 不能重复',
botDuplicateField: '{field} 不能重复',
botRequired: '请至少添加一个 Bot',
botId: 'Bot ID',
allowFrom: '私聊白名单',
allowFromHelper: '一行一个发送方标识仅在私聊策略为白名单时生效',
allowFromPlaceholder: '一行一个发送方标识',
allowlistPolicyHelper: '{0}仅在{1}为白名单时生效',
systemPrompt: '系统提示词',
groupAllowFrom: '群组白名单',
groupAllowFromHelper: '一行一个群组标识仅在群组策略为白名单时生效',
groupAllowFromPlaceholder: '一行一个群组标识',
separateSessionByConversation: '按会话隔离',
groupSessionScope: '群会话范围',
@@ -827,19 +795,17 @@ const message = {
pairingCodePlaceholder: '请输入配对码',
approvePairing: '批准配对',
saveSuccess: '保存成功',
saveAndRestartSuccess: '保存成功容器正在自动重启',
successAndRestart: '{0}容器正在自动重启',
pairingApproveSuccess: '配对成功',
scanConnect: '扫码对接',
scanConnectHelper: '点击后将在任务日志中显示二维码扫码确认成功后将自动重启容器',
channelAutoRestartHelper: '保存后将自动重启容器以使配置生效',
channelDeleteConfirm: '确认删除 {0} 频道配置',
deleteAndRestartSuccess: '删除成功容器正在自动重启',
customProviderHelper: '自定义模型供应商不验证账号是否可用',
},
model: {
model: '模型',
localModel: '本地模型',
create: '添加模型',
create_helper: '拉取 "{0}"',
ollama_doc: '您可以访问 Ollama 官网搜索并查找更多模型',
container_conn_helper: '容器间访问或连接使用此地址',
@@ -857,13 +823,11 @@ const message = {
manualDownload: '手动下载',
modelSource: '模型来源',
repoID: '仓库 ID',
modelScopeEndpoint: 'ModelScope 地址',
modelScopeToken: 'ModelScope Token可选',
hfToken: 'HF Token可选',
hfEndpoint: 'HuggingFace 加速地址',
endpointLabel: '{0} 地址',
acceleratedEndpointLabel: '{0} 加速地址',
tokenOptionalLabel: '{0} Token可选',
searchSource: '搜索 {0}',
hfEndpointHelper: '国内访问 HuggingFace 不稳定时可配置加速地址搜索详情和下载都会使用该地址',
searchModelScope: '搜索 ModelScope',
searchHuggingFace: '搜索 HuggingFace',
sortTrending: '热门趋势',
sortLikes: '点赞最多',
sortDownloads: '下载最多',
@@ -875,7 +839,6 @@ const message = {
progress: '进度',
localDownloaded: '已下载',
modelInfo: '模型详情',
modelCard: '模型卡片',
downloading: '下载中',
canceled: '已取消',
downloadQueued: '已加入下载队列',
@@ -906,7 +869,6 @@ const message = {
failureCount: '失败次数',
lastError: '最近错误',
modelMap: '模型映射',
apiKeyReset: '重置 API Key留空不改',
qpsLimit: 'QPS 限制',
tokenLimit: 'Token 限制',
tokenUsed: '已用 Token',
@@ -928,7 +890,6 @@ const message = {
'根据模型账号权重分配请求权重越高承担的请求越多适合后端性能不同的场景',
lbPolicyFailover: '故障转移',
lbPolicyFailoverDesc: '优先使用优先级最高的模型账号失败或冷却后再切换到下一个可用账号',
productionProtection: '生产保护',
maxConcurrency: '最大并发',
queueSize: '等待队列大小',
queueTimeoutSeconds: '队列等待超时',
@@ -936,16 +897,10 @@ const message = {
streamIdleTimeoutSeconds: '流式空闲超时',
maxBodyMb: '最大请求体MB',
runtimeRefreshSeconds: 'Runtime 刷新间隔',
logRetention: '日志保留',
usageRetentionDays: '用量统计保留天数',
contentAuditRetentionDays: '内容合规审计日志保留天数',
logCleanupIntervalHours: '日志清理间隔小时',
requestBodyLog: '请求体日志',
requestBodyLogEsEndpoint: 'Elasticsearch 地址',
requestBodyLogEsAuthMethod: 'Elasticsearch 认证方式',
requestBodyLogEsUsername: 'Elasticsearch 用户名',
requestBodyLogEsPassword: 'Elasticsearch 密码',
requestBodyLogEsApiKey: 'Elasticsearch API Key',
requestBodyLogIndexPrefix: '索引前缀',
requestBodyLogRetentionDays: '请求体日志保留天数',
requestBodyLogMaxBodyKb: '单请求体最大保存大小KB',
@@ -970,11 +925,9 @@ const message = {
esLogCircuitOpen: '熔断中',
esLogCircuitUntil: 'ES 熔断结束时间',
serviceOperateConfirm: '确认{0} AI 网关服务',
deleteBackendConfirm: '确认删除模型账号 {0}',
deleteTargetConfirm: '确认删除{0} {1}',
deleteBackendTitle: '删除模型账号',
deleteUserConfirm: '确认删除 API Key {0}',
deleteGroupConfirm: '确认删除用户组 {0}',
userFallback: '用户 {0}',
userFallback: '已删除用户 (ID: {0})',
requestModel: '请求模型',
upstreamModel: '上游模型',
requestModelPlaceholder: ' qwen2.5-coder',
@@ -983,10 +936,8 @@ const message = {
overview: '概览',
distribution: '分布',
usageTrend: '使用趋势',
providerDistribution: '服务商分布',
distributionBy: '{0}分布',
unmatched: '未匹配',
modelDistribution: '按模型分布',
accountDistribution: '按模型账号分布',
modelAccount: '模型账号',
serviceProvider: '服务商',
tokenUsage: 'Token 用量',
@@ -995,8 +946,6 @@ const message = {
rank: '排名',
promptToken: '输入 Token',
completionToken: '输出 Token',
inputTokens: '输入 Token',
outputTokens: '输出 Token',
totalToken: ' Token',
cachedToken: '缓存 Token',
cacheHitRate: '缓存命中率',
@@ -1024,7 +973,6 @@ const message = {
modelGroupModels: '请求模型',
modelGroupModelsPlaceholder: '请选择或输入请求模型名',
modelGroupModelCount: '{0} 个模型',
deleteModelGroupConfirm: '确认删除模型组 {0}',
contentCompliance: '内容合规',
contentAction: '处理动作',
actionBlock: '阻断',
@@ -1175,7 +1123,6 @@ const message = {
},
benchmark: {
title: '基准测试',
create: '创建',
launchCommand: '启动命令',
retest: '重新测试',
statusRunning: '运行中',
+44 -18
View File
@@ -1,27 +1,53 @@
import i18n from '@/lang';
const taskTextMap: Record<string, string> = {
BatchInstallAgent: 'aiTools.agents.batchInstallAgent',
DispatchAgentInstallTasks: 'aiTools.agents.dispatchAgentInstallTasks',
BatchUpgradeAgent: 'aiTools.agents.batchUpgradeAgent',
DispatchAgentUpgradeTasks: 'aiTools.agents.dispatchAgentUpgradeTasks',
BatchInstallAgentSkill: 'aiTools.agents.batchInstallAgentSkill',
DispatchAgentSkillInstallTasks: 'aiTools.agents.dispatchAgentSkillInstallTasks',
BatchStartAgent: 'aiTools.agents.batchStartAgent',
DispatchAgentStartTasks: 'aiTools.agents.dispatchAgentStartTasks',
BatchStopAgent: 'aiTools.agents.batchStopAgent',
DispatchAgentStopTasks: 'aiTools.agents.dispatchAgentStopTasks',
BatchRestartAgent: 'aiTools.agents.batchRestartAgent',
DispatchAgentRestartTasks: 'aiTools.agents.dispatchAgentRestartTasks',
BatchDeleteAgent: 'aiTools.agents.batchDeleteAgent',
DispatchAgentDeleteTasks: 'aiTools.agents.dispatchAgentDeleteTasks',
const agentActionKeyMap: Record<string, string> = {
Install: 'commons.button.install',
Upgrade: 'commons.button.upgrade',
Start: 'commons.operate.start',
Stop: 'commons.operate.stop',
Restart: 'commons.operate.restart',
Delete: 'commons.operate.delete',
};
const getActionText = (action: string) => i18n.global.t(agentActionKeyMap[action]);
const formatBatchAgentTask = (action: string) => {
return i18n.global.t('aiTools.agents.batchAgentTask', [getActionText(action)]);
};
const formatDispatchAgentTask = (action: string) => {
return i18n.global.t('aiTools.agents.dispatchAgentTask', [getActionText(action)]);
};
const formatSkillInstallTask = () => {
return `${'Skill'} ${i18n.global.t('commons.button.install')}`;
};
const taskTextMap: Record<string, () => string> = {
BatchInstallAgent: () => formatBatchAgentTask('Install'),
DispatchAgentInstallTasks: () => formatDispatchAgentTask('Install'),
BatchUpgradeAgent: () => formatBatchAgentTask('Upgrade'),
DispatchAgentUpgradeTasks: () => formatDispatchAgentTask('Upgrade'),
BatchInstallAgentSkill: () =>
i18n.global.t('aiTools.agents.batchAction', [i18n.global.t('aiTools.agents.installSkillAction')]),
DispatchAgentSkillInstallTasks: () => i18n.global.t('aiTools.agents.dispatchTask', [formatSkillInstallTask()]),
BatchStartAgent: () => formatBatchAgentTask('Start'),
DispatchAgentStartTasks: () => formatDispatchAgentTask('Start'),
BatchStopAgent: () => formatBatchAgentTask('Stop'),
DispatchAgentStopTasks: () => formatDispatchAgentTask('Stop'),
BatchRestartAgent: () => formatBatchAgentTask('Restart'),
DispatchAgentRestartTasks: () => formatDispatchAgentTask('Restart'),
BatchDeleteAgent: () => formatBatchAgentTask('Delete'),
DispatchAgentDeleteTasks: () => formatDispatchAgentTask('Delete'),
};
export const translateTaskText = (value?: string) => {
if (!value) {
return value || '';
}
return Object.entries(taskTextMap).reduce((text, [key, localeKey]) => {
return text.replaceAll(key, i18n.global.t(localeKey));
}, value);
return Object.entries(taskTextMap)
.sort(([prevKey], [nextKey]) => nextKey.length - prevKey.length)
.reduce((text, [key, resolver]) => {
return text.replaceAll(key, resolver());
}, value);
};
@@ -4,9 +4,9 @@
<el-card class="form-card">
<el-form-item :label="`${$t('aiTools.agents.agent')}${$t('commons.table.type')}`" prop="agentType">
<el-select v-model="form.agentType" @change="handleAgentTypeChange">
<el-option :label="$t('aiTools.agents.openclawType')" value="openclaw" />
<el-option :label="$t('aiTools.agents.hermesType')" value="hermes-agent" />
<el-option :label="$t('aiTools.agents.copawType')" value="copaw" />
<el-option label="OpenClaw" value="openclaw" />
<el-option label="Hermes Agent" value="hermes-agent" />
<el-option label="QwenPaw" value="copaw" />
</el-select>
</el-form-item>
<el-form-item :label="$t('commons.table.name')" prop="name">
@@ -290,7 +290,13 @@ const rules = computed<FormRules>(() => {
(bot, index) => index !== editIndex.value && bot.accountId === value,
);
if (exists) {
callback(new Error(t('aiTools.agents.botDuplicateAccountId')));
callback(
new Error(
t('aiTools.agents.botDuplicateField', {
field: t('aiTools.agents.accountId'),
}),
),
);
return;
}
callback();
@@ -122,7 +122,7 @@ const save = async () => {
},
],
});
MsgSuccess(t('aiTools.agents.saveAndRestartSuccess'));
MsgSuccess(t('aiTools.agents.successAndRestart', [t('aiTools.agents.saveSuccess')]));
configured.value = true;
} finally {
saving.value = false;
@@ -149,7 +149,7 @@ const deleteChannel = async () => {
type: 'dingtalk',
});
await load(agentId.value);
MsgSuccess(t('aiTools.agents.deleteAndRestartSuccess'));
MsgSuccess(t('aiTools.agents.successAndRestart', [t('commons.msg.deleteSuccess')]));
} finally {
deleting.value = false;
}
@@ -117,7 +117,7 @@ const save = async () => {
},
],
});
MsgSuccess(t('aiTools.agents.saveAndRestartSuccess'));
MsgSuccess(t('aiTools.agents.successAndRestart', [t('aiTools.agents.saveSuccess')]));
configured.value = true;
} finally {
saving.value = false;
@@ -140,7 +140,7 @@ const deleteChannel = async () => {
type: 'discord',
});
await load(agentId.value);
MsgSuccess(t('aiTools.agents.deleteAndRestartSuccess'));
MsgSuccess(t('aiTools.agents.successAndRestart', [t('commons.msg.deleteSuccess')]));
} finally {
deleting.value = false;
}
@@ -131,7 +131,7 @@ const save = async () => {
},
],
});
MsgSuccess(t('aiTools.agents.saveAndRestartSuccess'));
MsgSuccess(t('aiTools.agents.successAndRestart', [t('aiTools.agents.saveSuccess')]));
configured.value = true;
} finally {
saving.value = false;
@@ -158,7 +158,7 @@ const deleteChannel = async () => {
type: 'feishu',
});
await load(agentId.value);
MsgSuccess(t('aiTools.agents.deleteAndRestartSuccess'));
MsgSuccess(t('aiTools.agents.successAndRestart', [t('commons.msg.deleteSuccess')]));
} finally {
deleting.value = false;
}
@@ -131,7 +131,7 @@ const save = async () => {
},
],
});
MsgSuccess(t('aiTools.agents.saveAndRestartSuccess'));
MsgSuccess(t('aiTools.agents.successAndRestart', [t('aiTools.agents.saveSuccess')]));
configured.value = true;
} finally {
saving.value = false;
@@ -142,15 +142,11 @@ const deleteChannel = async () => {
if (!agentId.value) {
return;
}
await ElMessageBox.confirm(
t('aiTools.agents.channelDeleteConfirm', [t('aiTools.agents.qq')]),
t('commons.msg.infoTitle'),
{
confirmButtonText: t('commons.button.confirm'),
cancelButtonText: t('commons.button.cancel'),
type: 'warning',
},
);
await ElMessageBox.confirm(t('aiTools.agents.channelDeleteConfirm', ['QQ']), t('commons.msg.infoTitle'), {
confirmButtonText: t('commons.button.confirm'),
cancelButtonText: t('commons.button.cancel'),
type: 'warning',
});
deleting.value = true;
try {
await deleteAgentChannelConfig({
@@ -158,7 +154,7 @@ const deleteChannel = async () => {
type: 'qqbot',
});
await load(agentId.value);
MsgSuccess(t('aiTools.agents.deleteAndRestartSuccess'));
MsgSuccess(t('aiTools.agents.successAndRestart', [t('commons.msg.deleteSuccess')]));
} finally {
deleting.value = false;
}
@@ -122,7 +122,7 @@ const save = async () => {
},
],
});
MsgSuccess(t('aiTools.agents.saveAndRestartSuccess'));
MsgSuccess(t('aiTools.agents.successAndRestart', [t('aiTools.agents.saveSuccess')]));
configured.value = true;
} finally {
saving.value = false;
@@ -145,7 +145,7 @@ const deleteChannel = async () => {
type: 'telegram',
});
await load(agentId.value);
MsgSuccess(t('aiTools.agents.deleteAndRestartSuccess'));
MsgSuccess(t('aiTools.agents.successAndRestart', [t('commons.msg.deleteSuccess')]));
} finally {
deleting.value = false;
}
@@ -121,7 +121,7 @@ const save = async () => {
botId: form.botId,
secret: form.secret,
});
MsgSuccess(t('aiTools.agents.saveAndRestartSuccess'));
MsgSuccess(t('aiTools.agents.successAndRestart', [t('aiTools.agents.saveSuccess')]));
configured.value = true;
} finally {
saving.value = false;
@@ -148,7 +148,7 @@ const deleteChannel = async () => {
type: 'wecom',
});
await load(agentId.value);
MsgSuccess(t('aiTools.agents.deleteAndRestartSuccess'));
MsgSuccess(t('aiTools.agents.successAndRestart', [t('commons.msg.deleteSuccess')]));
} finally {
deleting.value = false;
}
@@ -70,7 +70,7 @@ const deleteChannel = async () => {
type: 'weixin',
});
await load();
MsgSuccess(t('aiTools.agents.deleteAndRestartSuccess'));
MsgSuccess(t('aiTools.agents.successAndRestart', [t('commons.msg.deleteSuccess')]));
} finally {
deleting.value = false;
}
@@ -37,7 +37,14 @@
:rows="3"
:placeholder="t('aiTools.agents.allowFromPlaceholder')"
/>
<span class="input-help">{{ t('aiTools.agents.allowFromHelper') }}</span>
<span class="input-help">
{{
t('aiTools.agents.allowlistPolicyHelper', [
t('aiTools.agents.allowFromPlaceholder'),
t('aiTools.agents.dmPolicy'),
])
}}
</span>
</el-form-item>
<el-form-item :label="t('aiTools.agents.groupPolicy')" prop="groupPolicy">
<el-select v-model="form.groupPolicy">
@@ -57,7 +64,14 @@
:rows="3"
:placeholder="t('aiTools.agents.groupAllowFromPlaceholder')"
/>
<span class="input-help">{{ t('aiTools.agents.groupAllowFromHelper') }}</span>
<span class="input-help">
{{
t('aiTools.agents.allowlistPolicyHelper', [
t('aiTools.agents.groupAllowFromPlaceholder'),
t('aiTools.agents.groupPolicy'),
])
}}
</span>
</el-form-item>
<el-form-item :label="t('aiTools.agents.separateSessionByConversation')">
<el-switch v-model="form.separateSessionByConversation" />
@@ -52,7 +52,14 @@
:rows="3"
:placeholder="t('aiTools.agents.groupAllowFromPlaceholder')"
/>
<span class="input-help">{{ t('aiTools.agents.groupAllowFromHelper') }}</span>
<span class="input-help">
{{
t('aiTools.agents.allowlistPolicyHelper', [
t('aiTools.agents.groupAllowFromPlaceholder'),
t('aiTools.agents.groupPolicy'),
])
}}
</span>
</el-form-item>
</div>
<ChannelBots
@@ -18,7 +18,14 @@
:rows="3"
:placeholder="t('aiTools.agents.allowFromPlaceholder')"
/>
<span class="input-help">{{ t('aiTools.agents.allowFromHelper') }}</span>
<span class="input-help">
{{
t('aiTools.agents.allowlistPolicyHelper', [
t('aiTools.agents.allowFromPlaceholder'),
t('aiTools.agents.dmPolicy'),
])
}}
</span>
</el-form-item>
<el-form-item :label="t('aiTools.agents.groupPolicy')" prop="groupPolicy">
<el-select v-model="form.groupPolicy">
@@ -38,7 +45,14 @@
:rows="3"
:placeholder="t('aiTools.agents.groupAllowFromPlaceholder')"
/>
<span class="input-help">{{ t('aiTools.agents.groupAllowFromHelper') }}</span>
<span class="input-help">
{{
t('aiTools.agents.allowlistPolicyHelper', [
t('aiTools.agents.groupAllowFromPlaceholder'),
t('aiTools.agents.groupPolicy'),
])
}}
</span>
</el-form-item>
<el-form-item :label="t('setting.proxy')">
<el-input v-model="form.proxy" placeholder="http://127.0.0.1:7890" />
@@ -36,7 +36,14 @@
:rows="3"
:placeholder="t('aiTools.agents.allowFromPlaceholder')"
/>
<span class="input-help">{{ t('aiTools.agents.allowFromHelper') }}</span>
<span class="input-help">
{{
t('aiTools.agents.allowlistPolicyHelper', [
t('aiTools.agents.allowFromPlaceholder'),
t('aiTools.agents.dmPolicy'),
])
}}
</span>
</el-form-item>
<el-form-item :label="t('aiTools.agents.groupPolicy')" prop="groupPolicy">
<el-select v-model="form.groupPolicy">
@@ -56,7 +63,14 @@
:rows="3"
:placeholder="t('aiTools.agents.groupAllowFromPlaceholder')"
/>
<span class="input-help">{{ t('aiTools.agents.groupAllowFromHelper') }}</span>
<span class="input-help">
{{
t('aiTools.agents.allowlistPolicyHelper', [
t('aiTools.agents.groupAllowFromPlaceholder'),
t('aiTools.agents.groupPolicy'),
])
}}
</span>
</el-form-item>
<el-form-item :label="t('aiTools.agents.botId')" prop="botId">
<el-input v-model="form.botId" />
+3 -3
View File
@@ -407,11 +407,11 @@ const search = async () => {
const getAgentTypeLabel = (agentType: AI.AgentType) => {
switch (agentType) {
case 'copaw':
return i18n.global.t('aiTools.agents.copawType');
return 'QwenPaw';
case 'hermes-agent':
return i18n.global.t('aiTools.agents.hermesType');
return 'Hermes Agent';
default:
return i18n.global.t('aiTools.agents.openclawType');
return 'OpenClaw';
}
};
@@ -13,6 +13,12 @@
{{ $t('website.forceDeleteHelper') }}
</span>
</el-form-item>
<el-form-item>
<el-checkbox v-model="deleteReq.deleteImage" :label="$t('app.deleteImage')" />
<span class="input-help">
{{ $t('app.deleteImageHelper') }}
</span>
</el-form-item>
</el-form>
</div>
<template #footer>
@@ -29,6 +35,7 @@
<script lang="ts" setup>
import { DeleteRuntime } from '@/api/modules/runtime';
import i18n from '@/lang';
import { newUUID } from '@/utils/id';
import { MsgSuccess } from '@/utils/message';
import { FormInstance } from 'element-plus';
import { ref } from 'vue';
@@ -39,8 +46,10 @@ const loading = ref(false);
const deleteReq = ref({
id: 0,
forceDelete: false,
deleteImage: false,
taskID: '',
});
const em = defineEmits(['close']);
const em = defineEmits(['close', 'task']);
const deleteForm = ref<FormInstance>();
const resourceName = ref('');
@@ -53,6 +62,8 @@ const acceptParams = async (id: number, name: string) => {
deleteReq.value = {
id: id,
forceDelete: false,
deleteImage: false,
taskID: '',
};
resourceName.value = name;
open.value = true;
@@ -60,10 +71,13 @@ const acceptParams = async (id: number, name: string) => {
const submit = () => {
loading.value = true;
const taskID = newUUID();
deleteReq.value.taskID = taskID;
DeleteRuntime(deleteReq.value)
.then(() => {
handleClose();
MsgSuccess(i18n.global.t('commons.msg.deleteSuccess'));
em('task', taskID);
})
.finally(() => {
loading.value = false;
@@ -91,12 +91,13 @@
</ComplexTable>
</template>
</LayoutContent>
<OperateDonet ref="operateRef" @close="search" />
<Delete ref="deleteRef" @close="search" />
<OperateDonet ref="operateRef" @close="search" @submit="openCreateTaskLog" />
<Delete ref="deleteRef" @close="search" @task="openCreateTaskLog" />
<ComposeLogs ref="composeLogRef" />
<PortJumpDialog ref="dialogPortJumpRef" />
<AppResources ref="checkRef" @close="search" />
<AppResources ref="checkRef" @close="search" @task="openCreateTaskLog" />
<Terminal ref="terminalRef" />
<TaskLog ref="taskLogRef" width="70%" @close="search" />
</div>
</template>
@@ -114,6 +115,7 @@ import PortJumpDialog from '@/components/port-jump/index.vue';
import AppResources from '@/views/website/runtime/php/check/index.vue';
import RuntimeStatus from '@/views/website/runtime/components/runtime-status.vue';
import PortJump from '@/views/website/runtime/components/port-jump.vue';
import TaskLog from '@/components/log/task/index.vue';
import Terminal from '@/views/website/runtime/components/terminal.vue';
import DockerStatus from '@/views/container/docker-status/index.vue';
import { disabledButton } from '@/utils/runtime';
@@ -131,6 +133,7 @@ const dialogPortJumpRef = ref();
const composeLogRef = ref();
const checkRef = ref();
const terminalRef = ref();
const taskLogRef = ref();
const isActive = ref(false);
const isExist = ref(false);
@@ -228,6 +231,10 @@ const openCreate = () => {
operateRef.value.acceptParams({ type: 'dotnet', mode: 'create' });
};
const openCreateTaskLog = (taskID: string) => {
taskLogRef.value.openWithTaskID(taskID, true);
};
const openDetail = (row: Runtime.Runtime) => {
operateRef.value.acceptParams({ type: row.type, mode: 'edit', id: row.id });
};
@@ -49,6 +49,7 @@ import { Runtime } from '@/api/interface/runtime';
import { CreateRuntime, GetRuntime, UpdateRuntime } from '@/api/modules/runtime';
import { Rules, checkNumberRange } from '@/global/form-rules';
import i18n from '@/lang';
import { newUUID } from '@/utils/id';
import { MsgError, MsgSuccess } from '@/utils/message';
import { FormInstance } from 'element-plus';
import { reactive, ref, watch } from 'vue';
@@ -97,7 +98,7 @@ const rules = ref<any>({
},
});
const scripts = ref<Runtime.NodeScripts[]>([]);
const em = defineEmits(['close']);
const em = defineEmits(['close', 'submit']);
watch(
() => runtime.name,
@@ -143,10 +144,13 @@ const submit = async (formEl: FormInstance | undefined) => {
if (mode.value == 'create') {
loading.value = true;
const taskID = newUUID();
runtime.taskID = taskID;
CreateRuntime(runtime)
.then(() => {
MsgSuccess(i18n.global.t('commons.msg.createSuccess'));
handleClose();
em('submit', taskID);
})
.finally(() => {
loading.value = false;
@@ -91,12 +91,13 @@
</ComplexTable>
</template>
</LayoutContent>
<Operate ref="operateRef" @close="search" />
<Delete ref="deleteRef" @close="search" />
<Operate ref="operateRef" @close="search" @submit="openCreateTaskLog" />
<Delete ref="deleteRef" @close="search" @task="openCreateTaskLog" />
<ComposeLogs ref="composeLogRef" />
<PortJumpDialog ref="dialogPortJumpRef" />
<AppResources ref="checkRef" @close="search" />
<AppResources ref="checkRef" @close="search" @task="openCreateTaskLog" />
<Terminal ref="terminalRef" />
<TaskLog ref="taskLogRef" width="70%" @close="search" />
</div>
</template>
@@ -114,6 +115,7 @@ import PortJumpDialog from '@/components/port-jump/index.vue';
import AppResources from '@/views/website/runtime/php/check/index.vue';
import RuntimeStatus from '@/views/website/runtime/components/runtime-status.vue';
import PortJump from '@/views/website/runtime/components/port-jump.vue';
import TaskLog from '@/components/log/task/index.vue';
import Terminal from '@/views/website/runtime/components/terminal.vue';
import DockerStatus from '@/views/container/docker-status/index.vue';
import { disabledButton } from '@/utils/runtime';
@@ -131,6 +133,7 @@ const dialogPortJumpRef = ref();
const composeLogRef = ref();
const checkRef = ref();
const terminalRef = ref();
const taskLogRef = ref();
const isActive = ref(false);
const isExist = ref(false);
@@ -228,6 +231,10 @@ const openCreate = () => {
operateRef.value.acceptParams({ type: 'go', mode: 'create' });
};
const openCreateTaskLog = (taskID: string) => {
taskLogRef.value.openWithTaskID(taskID, true);
};
const openDetail = (row: Runtime.Runtime) => {
operateRef.value.acceptParams({ type: row.type, mode: 'edit', id: row.id });
};
@@ -69,6 +69,7 @@ import { Runtime } from '@/api/interface/runtime';
import { CreateRuntime, GetRuntime, UpdateRuntime } from '@/api/modules/runtime';
import { Rules, checkNumberRange } from '@/global/form-rules';
import i18n from '@/lang';
import { newUUID } from '@/utils/id';
import { MsgError, MsgSuccess } from '@/utils/message';
import { FormInstance } from 'element-plus';
import { reactive, ref, watch } from 'vue';
@@ -118,7 +119,7 @@ const rules = ref<any>({
},
});
const scripts = ref<Runtime.NodeScripts[]>([]);
const em = defineEmits(['close']);
const em = defineEmits(['close', 'submit']);
watch(
() => runtime.name,
@@ -168,10 +169,13 @@ const submit = async (formEl: FormInstance | undefined) => {
if (mode.value == 'create') {
loading.value = true;
const taskID = newUUID();
runtime.taskID = taskID;
CreateRuntime(runtime)
.then(() => {
MsgSuccess(i18n.global.t('commons.msg.createSuccess'));
handleClose();
em('submit', taskID);
})
.finally(() => {
loading.value = false;
@@ -91,12 +91,13 @@
</ComplexTable>
</template>
</LayoutContent>
<OperateJava ref="operateRef" @close="search" />
<Delete ref="deleteRef" @close="search" />
<OperateJava ref="operateRef" @close="search" @submit="openCreateTaskLog" />
<Delete ref="deleteRef" @close="search" @task="openCreateTaskLog" />
<ComposeLogs ref="composeLogRef" />
<PortJumpDialog ref="dialogPortJumpRef" />
<AppResources ref="checkRef" @close="search" />
<AppResources ref="checkRef" @close="search" @task="openCreateTaskLog" />
<Terminal ref="terminalRef" />
<TaskLog ref="taskLogRef" width="70%" @close="search" />
</div>
</template>
@@ -114,6 +115,7 @@ import PortJumpDialog from '@/components/port-jump/index.vue';
import AppResources from '@/views/website/runtime/php/check/index.vue';
import RuntimeStatus from '@/views/website/runtime/components/runtime-status.vue';
import PortJump from '@/views/website/runtime/components/port-jump.vue';
import TaskLog from '@/components/log/task/index.vue';
import Terminal from '@/views/website/runtime/components/terminal.vue';
import DockerStatus from '@/views/container/docker-status/index.vue';
import { disabledButton } from '@/utils/runtime';
@@ -131,6 +133,7 @@ const dialogPortJumpRef = ref();
const composeLogRef = ref();
const checkRef = ref();
const terminalRef = ref();
const taskLogRef = ref();
const isActive = ref(false);
const isExist = ref(false);
@@ -228,6 +231,10 @@ const openCreate = () => {
operateRef.value.acceptParams({ type: 'java', mode: 'create' });
};
const openCreateTaskLog = (taskID: string) => {
taskLogRef.value.openWithTaskID(taskID, true);
};
const openDetail = (row: Runtime.Runtime) => {
operateRef.value.acceptParams({ type: row.type, mode: 'edit', id: row.id });
};
@@ -53,6 +53,7 @@ import { Runtime } from '@/api/interface/runtime';
import { CreateRuntime, GetRuntime, UpdateRuntime } from '@/api/modules/runtime';
import { Rules, checkNumberRange } from '@/global/form-rules';
import i18n from '@/lang';
import { newUUID } from '@/utils/id';
import { MsgError, MsgSuccess } from '@/utils/message';
import { FormInstance } from 'element-plus';
import { reactive, ref, watch } from 'vue';
@@ -100,7 +101,7 @@ const rules = ref<any>({
},
});
const scripts = ref<Runtime.NodeScripts[]>([]);
const em = defineEmits(['close']);
const em = defineEmits(['close', 'submit']);
watch(
() => runtime.params['APP_PORT'],
@@ -156,10 +157,13 @@ const submit = async (formEl: FormInstance | undefined) => {
if (mode.value == 'create') {
loading.value = true;
const taskID = newUUID();
runtime.taskID = taskID;
CreateRuntime(runtime)
.then(() => {
MsgSuccess(i18n.global.t('commons.msg.createSuccess'));
handleClose();
em('submit', taskID);
})
.finally(() => {
loading.value = false;
@@ -91,13 +91,14 @@
</ComplexTable>
</template>
</LayoutContent>
<OperateNode ref="operateRef" @close="search" />
<Delete ref="deleteRef" @close="search" />
<OperateNode ref="operateRef" @close="search" @submit="openCreateTaskLog" />
<Delete ref="deleteRef" @close="search" @task="openCreateTaskLog" />
<ComposeLogs ref="composeLogRef" />
<PortJumpDialog ref="dialogPortJumpRef" />
<Modules ref="moduleRef" />
<AppResources ref="checkRef" @close="search" />
<AppResources ref="checkRef" @close="search" @task="openCreateTaskLog" />
<Terminal ref="terminalRef" />
<TaskLog ref="taskLogRef" width="70%" @close="search" />
</div>
</template>
@@ -116,6 +117,7 @@ import PortJumpDialog from '@/components/port-jump/index.vue';
import AppResources from '@/views/website/runtime/php/check/index.vue';
import RuntimeStatus from '@/views/website/runtime/components/runtime-status.vue';
import PortJump from '@/views/website/runtime/components/port-jump.vue';
import TaskLog from '@/components/log/task/index.vue';
import Terminal from '@/views/website/runtime/components/terminal.vue';
import DockerStatus from '@/views/container/docker-status/index.vue';
import { disabledButton } from '@/utils/runtime';
@@ -134,6 +136,7 @@ const composeLogRef = ref();
const moduleRef = ref();
const checkRef = ref();
const terminalRef = ref();
const taskLogRef = ref();
const isActive = ref(false);
const isExist = ref(false);
@@ -245,6 +248,10 @@ const openCreate = () => {
operateRef.value.acceptParams({ type: 'node', mode: 'create' });
};
const openCreateTaskLog = (taskID: string) => {
taskLogRef.value.openWithTaskID(taskID, true);
};
const openDetail = (row: Runtime.Runtime) => {
operateRef.value.acceptParams({ type: row.type, mode: 'edit', id: row.id });
};
@@ -70,6 +70,7 @@ import { Runtime } from '@/api/interface/runtime';
import { CreateRuntime, GetRuntime, UpdateRuntime } from '@/api/modules/runtime';
import { Rules, checkNumberRange } from '@/global/form-rules';
import i18n from '@/lang';
import { newUUID } from '@/utils/id';
import { MsgError, MsgSuccess } from '@/utils/message';
import { FormInstance } from 'element-plus';
import { computed, reactive, ref, watch } from 'vue';
@@ -120,7 +121,7 @@ const rules = ref<any>({
CONTAINER_NAME: [Rules.requiredInput, Rules.containerName],
},
});
const em = defineEmits(['close']);
const em = defineEmits(['close', 'submit']);
const hasPnpm = computed(() => {
if (runtime.version == undefined) {
@@ -188,10 +189,13 @@ const submit = async (formEl: FormInstance | undefined) => {
if (mode.value == 'create') {
loading.value = true;
const taskID = newUUID();
runtime.taskID = taskID;
CreateRuntime(runtime)
.then(() => {
MsgSuccess(i18n.global.t('commons.msg.createSuccess'));
handleClose();
em('submit', taskID);
})
.finally(() => {
loading.value = false;
@@ -51,6 +51,7 @@
import { App } from '@/api/interface/app';
import i18n from '@/lang';
import { MsgSuccess } from '@/utils/message';
import { newUUID } from '@/utils/id';
import { ref } from 'vue';
import { DeleteRuntime } from '@/api/modules/runtime';
import { routerToName } from '@/utils/router';
@@ -69,7 +70,7 @@ const installData = ref<CheckRrops>({
const open = ref(false);
const map = new Map();
const forceDelete = ref(false);
const em = defineEmits(['close']);
const em = defineEmits(['close', 'task']);
const acceptParams = (props: CheckRrops) => {
map.clear();
@@ -106,13 +107,16 @@ const onConfirm = () => {
type: 'info',
},
).then(() => {
const taskID = newUUID();
const params = {
id: installData.value.installID.valueOf(),
forceDelete: true,
taskID: taskID,
};
DeleteRuntime(params).then(() => {
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
open.value = false;
em('task', taskID);
em('close', open.value);
});
});
@@ -210,6 +210,7 @@ import { getAppByKey, getAppDetail, getCurrentNodeCustomAppConfig, searchApp } f
import { CreateRuntime, GetRuntime, ListPHPExtensions, UpdateRuntime } from '@/api/modules/runtime';
import { Rules } from '@/global/form-rules';
import i18n from '@/lang';
import { newUUID } from '@/utils/id';
import { MsgSuccess } from '@/utils/message';
import { FormInstance } from 'element-plus';
import { reactive, ref } from 'vue';
@@ -432,18 +433,20 @@ const submit = async (formEl: FormInstance | undefined) => {
return;
}
try {
let res;
if (mode.value == 'create') {
loading.value = true;
res = await CreateRuntime(runtime);
const taskID = newUUID();
runtime.taskID = taskID;
await CreateRuntime(runtime);
MsgSuccess(i18n.global.t('commons.msg.createSuccess'));
handleClose();
em('submit', taskID);
} else {
loading.value = true;
res = await UpdateRuntime(runtime);
await UpdateRuntime(runtime);
MsgSuccess(i18n.global.t('commons.msg.updateSuccess'));
handleClose();
}
handleClose();
em('submit', res.data.id);
} catch (error) {
} finally {
loading.value = false;
@@ -121,10 +121,10 @@
</LayoutContent>
<CreateRuntime ref="createRef" @close="search" @submit="openCreateLog" />
<OpDialog ref="opRef" @search="search" />
<Delete ref="deleteRef" @close="search" @task="openCreateLog" />
<Log ref="logRef" @close="search" :heightDiff="200" />
<Extensions ref="extensionsRef" @close="search" />
<AppResources ref="checkRef" @close="search" />
<AppResources ref="checkRef" @close="search" @task="openCreateLog" />
<ExtManagement ref="extManagementRef" />
<ComposeLogs ref="composeLogRef" :highlightDiff="200" />
<Config ref="configRef" />
@@ -137,7 +137,7 @@
<script setup lang="ts">
import { onMounted, reactive, ref } from 'vue';
import { Runtime } from '@/api/interface/runtime';
import { DeleteRuntime, RuntimeDeleteCheck, SearchRuntimes } from '@/api/modules/runtime';
import { RuntimeDeleteCheck, SearchRuntimes } from '@/api/modules/runtime';
import { dateFormat } from '@/utils/date';
import { newUUID } from '@/utils/id';
import { ElMessageBox } from 'element-plus';
@@ -148,6 +148,7 @@ import ExtManagement from './extension-management/index.vue';
import Extensions from './extension-template/index.vue';
import AppResources from '@/views/website/runtime/php/check/index.vue';
import CreateRuntime from '@/views/website/runtime/php/create/index.vue';
import Delete from '@/views/website/runtime/delete/index.vue';
import RouterMenu from '../index.vue';
import Log from '@/components/log/file-drawer/index.vue';
import ComposeLogs from '@/components/log/compose/index.vue';
@@ -175,11 +176,11 @@ let req = reactive<Runtime.RuntimeReq>({
pageSize: 40,
type: 'php',
});
const opRef = ref();
const logRef = ref();
const extensionsRef = ref();
const extManagementRef = ref();
const checkRef = ref();
const deleteRef = ref();
const createRef = ref();
const loading = ref(false);
const items = ref<Runtime.RuntimeDTO[]>([]);
@@ -328,8 +329,8 @@ const openLog = (row: Runtime.RuntimeDTO) => {
}
};
const openCreateLog = (id: number) => {
logRef.value.acceptParams({ id: id, type: 'php', tail: true });
const openCreateLog = (taskID: string) => {
taskLogRef.value.openWithTaskID(taskID, true);
};
const openExtensions = () => {
@@ -346,16 +347,7 @@ const openDelete = async (row: Runtime.Runtime) => {
if (res.data && res.data.length > 0) {
checkRef.value.acceptParams({ items: items, key: 'website', installID: row.id });
} else {
opRef.value.acceptParams({
title: i18n.global.t('commons.button.delete'),
names: [row.name],
msg: i18n.global.t('commons.msg.operatorHelper', [
i18n.global.t('website.runtime'),
i18n.global.t('commons.button.delete'),
]),
api: DeleteRuntime,
params: { id: row.id, forceDelete: true },
});
deleteRef.value.acceptParams(row.id, row.name);
}
});
};
@@ -91,12 +91,13 @@
</ComplexTable>
</template>
</LayoutContent>
<Operate ref="operateRef" @close="search" />
<Delete ref="deleteRef" @close="search" />
<Operate ref="operateRef" @close="search" @submit="openCreateTaskLog" />
<Delete ref="deleteRef" @close="search" @task="openCreateTaskLog" />
<ComposeLogs ref="composeLogRef" />
<PortJumpDialog ref="dialogPortJumpRef" />
<AppResources ref="checkRef" @close="search" />
<AppResources ref="checkRef" @close="search" @task="openCreateTaskLog" />
<Terminal ref="terminalRef" />
<TaskLog ref="taskLogRef" width="70%" @close="search" />
</div>
</template>
@@ -114,6 +115,7 @@ import PortJumpDialog from '@/components/port-jump/index.vue';
import AppResources from '@/views/website/runtime/php/check/index.vue';
import RuntimeStatus from '@/views/website/runtime/components/runtime-status.vue';
import PortJump from '@/views/website/runtime/components/port-jump.vue';
import TaskLog from '@/components/log/task/index.vue';
import Terminal from '@/views/website/runtime/components/terminal.vue';
import DockerStatus from '@/views/container/docker-status/index.vue';
import { disabledButton } from '@/utils/runtime';
@@ -131,6 +133,7 @@ const dialogPortJumpRef = ref();
const composeLogRef = ref();
const checkRef = ref();
const terminalRef = ref();
const taskLogRef = ref();
const isActive = ref(false);
const isExist = ref(false);
@@ -228,6 +231,10 @@ const openCreate = () => {
operateRef.value.acceptParams({ type: 'python', mode: 'create' });
};
const openCreateTaskLog = (taskID: string) => {
taskLogRef.value.openWithTaskID(taskID, true);
};
const openDetail = (row: Runtime.Runtime) => {
operateRef.value.acceptParams({ type: row.type, mode: 'edit', id: row.id });
};
@@ -48,6 +48,7 @@ import { Runtime } from '@/api/interface/runtime';
import { CreateRuntime, GetRuntime, UpdateRuntime } from '@/api/modules/runtime';
import { Rules, checkNumberRange } from '@/global/form-rules';
import i18n from '@/lang';
import { newUUID } from '@/utils/id';
import { MsgError, MsgSuccess } from '@/utils/message';
import { FormInstance } from 'element-plus';
import { reactive, ref } from 'vue';
@@ -96,7 +97,7 @@ const rules = ref<any>({
},
});
const scripts = ref<Runtime.NodeScripts[]>([]);
const em = defineEmits(['close']);
const em = defineEmits(['close', 'submit']);
const handleClose = () => {
open.value = false;
@@ -132,10 +133,13 @@ const submit = async (formEl: FormInstance | undefined) => {
if (mode.value == 'create') {
loading.value = true;
const taskID = newUUID();
runtime.taskID = taskID;
CreateRuntime(runtime)
.then(() => {
MsgSuccess(i18n.global.t('commons.msg.createSuccess'));
handleClose();
em('submit', taskID);
})
.finally(() => {
loading.value = false;