From eeab4b64f3e8a38582851f6e62eaa5d4c6953c32 Mon Sep 17 00:00:00 2001 From: zhengkunwang223 <1paneldev@sina.com> Date: Thu, 18 Jun 2026 18:42:53 +0800 Subject: [PATCH] feat: Create and delete runtime environments, and add task logs. --- agent/app/dto/request/runtime.go | 7 +- agent/app/service/runtime.go | 313 +++++++++++++++--- agent/app/service/runtime_utils.go | 66 ++-- agent/i18n/lang/en.yaml | 2 +- agent/i18n/lang/es-ES.yaml | 2 +- agent/i18n/lang/ja.yaml | 2 +- agent/i18n/lang/ko.yaml | 2 +- agent/i18n/lang/ms.yaml | 2 +- agent/i18n/lang/pt-BR.yaml | 2 +- agent/i18n/lang/ru.yaml | 2 +- agent/i18n/lang/tr.yaml | 2 +- agent/i18n/lang/zh-Hant.yaml | 2 +- agent/i18n/lang/zh.yaml | 2 +- agent/utils/compose/compose.go | 6 +- frontend/src/api/interface/runtime.ts | 3 + frontend/src/lang/modules/en.ts | 84 +---- frontend/src/lang/modules/es-es.ts | 97 +----- frontend/src/lang/modules/ja.ts | 99 +----- frontend/src/lang/modules/ko.ts | 98 +----- frontend/src/lang/modules/ms.ts | 100 +----- frontend/src/lang/modules/pt-br.ts | 100 +----- frontend/src/lang/modules/ru.ts | 99 +----- frontend/src/lang/modules/tr.ts | 97 +----- frontend/src/lang/modules/zh-Hant.ts | 96 +----- frontend/src/lang/modules/zh.ts | 83 +---- frontend/src/utils/task.ts | 62 +++- .../src/views/ai/agents/agent/add/index.vue | 6 +- .../tabs/channels/components/channel-bots.vue | 8 +- .../config/tabs/channels/hermes/dingtalk.vue | 4 +- .../config/tabs/channels/hermes/discord.vue | 4 +- .../config/tabs/channels/hermes/feishu.vue | 4 +- .../agent/config/tabs/channels/hermes/qq.vue | 18 +- .../config/tabs/channels/hermes/telegram.vue | 4 +- .../config/tabs/channels/hermes/wecom.vue | 4 +- .../config/tabs/channels/hermes/weixin.vue | 2 +- .../tabs/channels/openclaw/dingtalk.vue | 18 +- .../config/tabs/channels/openclaw/feishu.vue | 9 +- .../tabs/channels/openclaw/telegram.vue | 18 +- .../config/tabs/channels/openclaw/wecom.vue | 18 +- frontend/src/views/ai/agents/agent/index.vue | 6 +- .../views/website/runtime/delete/index.vue | 16 +- .../views/website/runtime/dotnet/index.vue | 13 +- .../website/runtime/dotnet/operate/index.vue | 6 +- .../src/views/website/runtime/go/index.vue | 13 +- .../website/runtime/go/operate/index.vue | 6 +- .../src/views/website/runtime/java/index.vue | 13 +- .../website/runtime/java/operate/index.vue | 6 +- .../src/views/website/runtime/node/index.vue | 13 +- .../website/runtime/node/operate/index.vue | 6 +- .../views/website/runtime/php/check/index.vue | 6 +- .../website/runtime/php/create/index.vue | 13 +- .../src/views/website/runtime/php/index.vue | 24 +- .../views/website/runtime/python/index.vue | 13 +- .../website/runtime/python/operate/index.vue | 6 +- 54 files changed, 724 insertions(+), 983 deletions(-) diff --git a/agent/app/dto/request/runtime.go b/agent/app/dto/request/runtime.go index d4dd9db53ee0..bd710a250e46 100644 --- a/agent/app/dto/request/runtime.go +++ b/agent/app/dto/request/runtime.go @@ -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 { diff --git a/agent/app/service/runtime.go b/agent/app/service/runtime.go index 2c55c588b5b1..c881325d0a50 100644 --- a/agent/app/service/runtime.go +++ b/agent/app/service/runtime.go @@ -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,22 +222,90 @@ func (r *RuntimeService) Create(create request.RuntimeCreate) (*model.Runtime, e ContainerName: containerName.(string), Port: strings.Join(hostPorts, ","), Remark: create.Remark, + 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: - if err = handlePHP(create, runtime, fileOp, appVersionDir); err != nil { - return nil, err - } + err = handlePHP(create, runtime, fileOp, appVersionDir) case constant.RuntimeNode, constant.RuntimeJava, constant.RuntimeGo, constant.RuntimePython, constant.RuntimeDotNet: - if err = handleRuntime(create, runtime, fileOp, appVersionDir); err != nil { - return nil, err + 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) } - if err := runtimeRepo.Create(context.Background(), runtime); err != nil { - return nil, err + 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 } - return runtime, 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) { @@ -272,36 +386,157 @@ 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 err := stopRuntimeBeforeDelete(runtime, runtimeDelete.ForceDelete, taskItem); err != nil { + return err + } + if runtimeDelete.DeleteImage { + deleteRuntimeImages(runtime, taskItem) + } + if err := files.NewFileOp().DeleteDir(projectDir); err != nil && !runtimeDelete.ForceDelete { + return err + } + 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 != "" { - return errors.New(out) + err = errors.New(out) + } + if taskItem != nil { + taskItem.LogFailedWithErr(logStr, err) } return err } - if runtime.Type == constant.RuntimePHP { - client, err := docker.NewClient() + 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 err + return nil, err } - defer client.Close() - imageID, err := client.GetImageIDByName(runtime.Image) + 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 { - return err + global.LOG.Errorf("get runtime image [%s] error %v", imageName, err) + if taskItem != nil { + taskItem.LogFailedWithErr(logStr, err) + } + continue } - if imageID != "" { - if err := client.DeleteImage(imageID); err != nil { - global.LOG.Errorf("delete image id [%s] error %v", imageID, err) + 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) } } - if err := files.NewFileOp().DeleteDir(projectDir); err != nil && !runtimeDelete.ForceDelete { - return err - } - return runtimeRepo.DeleteBy(repo.WithByID(runtimeDelete.ID)) } func (r *RuntimeService) Get(id uint) (*response.RuntimeDTO, error) { diff --git a/agent/app/service/runtime_utils.go b/agent/app/service/runtime_utils.go index ceba002c9308..a213392e2be8 100644 --- a/agent/app/service/runtime_utils.go +++ b/agent/app/service/runtime_utils.go @@ -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) { diff --git a/agent/i18n/lang/en.yaml b/agent/i18n/lang/en.yaml index 05e1846ae8ac..29f1f74b62af 100644 --- a/agent/i18n/lang/en.yaml +++ b/agent/i18n/lang/en.yaml @@ -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 }})' diff --git a/agent/i18n/lang/es-ES.yaml b/agent/i18n/lang/es-ES.yaml index 3bd9545fb424..61a297ddf3be 100644 --- a/agent/i18n/lang/es-ES.yaml +++ b/agent/i18n/lang/es-ES.yaml @@ -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 }}' diff --git a/agent/i18n/lang/ja.yaml b/agent/i18n/lang/ja.yaml index 0db5186c4efe..a044be66d294 100644 --- a/agent/i18n/lang/ja.yaml +++ b/agent/i18n/lang/ja.yaml @@ -72,7 +72,7 @@ ErrAIProxyModelMapInvalid: 'モデルマッピングは有効な JSON オブジ ErrAIProxyModelMapEmpty: 'モデルマッピングは空にできません' ErrAIProxyModelMapEmptyExternalModel: 'モデルマッピングに空のリクエストモデルがあります' ErrAIProxyModelMapEmptyUpstreamModel: '{{ .model }} の上流モデルは空にできません' -AIProxyUserFallback: 'ユーザー {{ .id }}' +AIProxyUserFallback: '削除済みユーザー (ID: {{ .id }})' Localhost: 'ローカルマシン' ErrBackupInUsed: 'バックアップアカウントがスケジュールで使用中' ErrBackupCheck: '接続テストに失敗しました: {{ .err }}' diff --git a/agent/i18n/lang/ko.yaml b/agent/i18n/lang/ko.yaml index 9104034649c2..4c83e02d0092 100644 --- a/agent/i18n/lang/ko.yaml +++ b/agent/i18n/lang/ko.yaml @@ -72,7 +72,7 @@ ErrAIProxyModelMapInvalid: '모델 매핑은 유효한 JSON 객체여야 합니 ErrAIProxyModelMapEmpty: '모델 매핑은 비워 둘 수 없습니다' ErrAIProxyModelMapEmptyExternalModel: '모델 매핑에 빈 요청 모델이 있습니다' ErrAIProxyModelMapEmptyUpstreamModel: '{{ .model }}의 업스트림 모델은 비워 둘 수 없습니다' -AIProxyUserFallback: '사용자 {{ .id }}' +AIProxyUserFallback: '삭제된 사용자 (ID: {{ .id }})' Localhost: '로컬 머신' ErrBackupInUsed: '백업 계정이 예약에 사용 중' ErrBackupCheck: '연결 테스트 실패: {{ .err }}' diff --git a/agent/i18n/lang/ms.yaml b/agent/i18n/lang/ms.yaml index cd935d6dbc2c..e00c5c77d2cd 100644 --- a/agent/i18n/lang/ms.yaml +++ b/agent/i18n/lang/ms.yaml @@ -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 }}' diff --git a/agent/i18n/lang/pt-BR.yaml b/agent/i18n/lang/pt-BR.yaml index 7fa6ed8c42d8..1365ac8adc4e 100644 --- a/agent/i18n/lang/pt-BR.yaml +++ b/agent/i18n/lang/pt-BR.yaml @@ -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 }}' diff --git a/agent/i18n/lang/ru.yaml b/agent/i18n/lang/ru.yaml index f2eb0d5a0735..a4c0cb195cd8 100644 --- a/agent/i18n/lang/ru.yaml +++ b/agent/i18n/lang/ru.yaml @@ -72,7 +72,7 @@ ErrAIProxyModelMapInvalid: 'Сопоставление моделей должн ErrAIProxyModelMapEmpty: 'Сопоставление моделей не может быть пустым' ErrAIProxyModelMapEmptyExternalModel: 'Сопоставление моделей содержит пустую запрошенную модель' ErrAIProxyModelMapEmptyUpstreamModel: 'Upstream-модель для {{ .model }} не может быть пустой' -AIProxyUserFallback: 'Пользователь {{ .id }}' +AIProxyUserFallback: 'Удаленный пользователь (ID: {{ .id }})' Localhost: 'Локальная машина' ErrBackupInUsed: 'Аккаунт бэкапа занят задачей' ErrBackupCheck: 'Проверка подключения не удалась: {{ .err }}' diff --git a/agent/i18n/lang/tr.yaml b/agent/i18n/lang/tr.yaml index 33fd80def050..3ede8d1fba0a 100644 --- a/agent/i18n/lang/tr.yaml +++ b/agent/i18n/lang/tr.yaml @@ -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 }}' diff --git a/agent/i18n/lang/zh-Hant.yaml b/agent/i18n/lang/zh-Hant.yaml index a6787772c24e..3b58c82333d6 100644 --- a/agent/i18n/lang/zh-Hant.yaml +++ b/agent/i18n/lang/zh-Hant.yaml @@ -72,7 +72,7 @@ ErrAIProxyModelMapInvalid: '模型映射必須是合法的 JSON 物件:{{ .err ErrAIProxyModelMapEmpty: '模型映射不能為空' ErrAIProxyModelMapEmptyExternalModel: '模型映射中存在空的請求模型' ErrAIProxyModelMapEmptyUpstreamModel: '模型 {{ .model }} 的上游模型不能為空' -AIProxyUserFallback: '使用者 {{ .id }}' +AIProxyUserFallback: '已刪除使用者 (ID: {{ .id }})' Localhost: '本機' ErrBackupInUsed: '此備份帳號已在排程任務中使用,無法刪除' ErrBackupCheck: '備份帳號測試連線失敗{{ .err }}' diff --git a/agent/i18n/lang/zh.yaml b/agent/i18n/lang/zh.yaml index 3281b364a6b1..92ae4363b431 100644 --- a/agent/i18n/lang/zh.yaml +++ b/agent/i18n/lang/zh.yaml @@ -610,4 +610,4 @@ ErrAIProxyModelMapInvalid: "模型映射必须是合法的 JSON 对象:{{ .err ErrAIProxyModelMapEmpty: "模型映射不能为空" ErrAIProxyModelMapEmptyExternalModel: "模型映射中存在空的请求模型" ErrAIProxyModelMapEmptyUpstreamModel: "模型 {{ .model }} 的上游模型不能为空" -AIProxyUserFallback: "用户 {{ .id }}" +AIProxyUserFallback: "已删除用户 (ID: {{ .id }})" diff --git a/agent/utils/compose/compose.go b/agent/utils/compose/compose.go index b3f2d3bbb1da..5548eca347f1 100644 --- a/agent/utils/compose/compose.go +++ b/agent/utils/compose/compose.go @@ -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 { diff --git a/frontend/src/api/interface/runtime.ts b/frontend/src/api/interface/runtime.ts index 51b8974d5861..fe453f42f5f7 100644 --- a/frontend/src/api/interface/runtime.ts +++ b/frontend/src/api/interface/runtime.ts @@ -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 { diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index 2716c33e4df9..c2085543b125 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -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', diff --git a/frontend/src/lang/modules/es-es.ts b/frontend/src/lang/modules/es-es.ts index bfc6de67f931..aa0a5256c419 100644 --- a/frontend/src/lang/modules/es-es.ts +++ b/frontend/src/lang/modules/es-es.ts @@ -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', diff --git a/frontend/src/lang/modules/ja.ts b/frontend/src/lang/modules/ja.ts index 3938d89818bd..0b19d147d273 100644 --- a/frontend/src/lang/modules/ja.ts +++ b/frontend/src/lang/modules/ja.ts @@ -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 単位を入力してください。例: 512、1k、32k', 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 を無視', diff --git a/frontend/src/lang/modules/ko.ts b/frontend/src/lang/modules/ko.ts index 2630b4ace986..2ce8847d0e1f 100644 --- a/frontend/src/lang/modules/ko.ts +++ b/frontend/src/lang/modules/ko.ts @@ -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 무시', diff --git a/frontend/src/lang/modules/ms.ts b/frontend/src/lang/modules/ms.ts index 8e1a409c2989..385706cad88f 100644 --- a/frontend/src/lang/modules/ms.ts +++ b/frontend/src/lang/modules/ms.ts @@ -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', diff --git a/frontend/src/lang/modules/pt-br.ts b/frontend/src/lang/modules/pt-br.ts index 078304e6db89..d638b4da3d23 100644 --- a/frontend/src/lang/modules/pt-br.ts +++ b/frontend/src/lang/modules/pt-br.ts @@ -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 já existe', botDuplicateField: '{field} já 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', diff --git a/frontend/src/lang/modules/ru.ts b/frontend/src/lang/modules/ru.ts index f44f1b3cc459..5746d7e84672 100644 --- a/frontend/src/lang/modules/ru.ts +++ b/frontend/src/lang/modules/ru.ts @@ -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', diff --git a/frontend/src/lang/modules/tr.ts b/frontend/src/lang/modules/tr.ts index 8c3ec2d9087d..e88ec28aeb67 100644 --- a/frontend/src/lang/modules/tr.ts +++ b/frontend/src/lang/modules/tr.ts @@ -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 Ağ 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", diff --git a/frontend/src/lang/modules/zh-Hant.ts b/frontend/src/lang/modules/zh-Hant.ts index ec0b633da1c7..6c0b1c33dda3 100644 --- a/frontend/src/lang/modules/zh-Hant.ts +++ b/frontend/src/lang/modules/zh-Hant.ts @@ -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 單位,例如 512、1k、32k', 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', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index 268821be79a7..a377c9f6f24e 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -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: '运行中', diff --git a/frontend/src/utils/task.ts b/frontend/src/utils/task.ts index 89f971333aa7..524b96400507 100644 --- a/frontend/src/utils/task.ts +++ b/frontend/src/utils/task.ts @@ -1,27 +1,53 @@ import i18n from '@/lang'; -const taskTextMap: Record = { - 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 = { + 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> = { + 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); }; diff --git a/frontend/src/views/ai/agents/agent/add/index.vue b/frontend/src/views/ai/agents/agent/add/index.vue index 9810c04cf7f4..d2d2cc75196d 100644 --- a/frontend/src/views/ai/agents/agent/add/index.vue +++ b/frontend/src/views/ai/agents/agent/add/index.vue @@ -4,9 +4,9 @@ - - - + + + diff --git a/frontend/src/views/ai/agents/agent/config/tabs/channels/components/channel-bots.vue b/frontend/src/views/ai/agents/agent/config/tabs/channels/components/channel-bots.vue index a5e2ec0404bd..693a2dd80bbd 100644 --- a/frontend/src/views/ai/agents/agent/config/tabs/channels/components/channel-bots.vue +++ b/frontend/src/views/ai/agents/agent/config/tabs/channels/components/channel-bots.vue @@ -290,7 +290,13 @@ const rules = computed(() => { (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(); diff --git a/frontend/src/views/ai/agents/agent/config/tabs/channels/hermes/dingtalk.vue b/frontend/src/views/ai/agents/agent/config/tabs/channels/hermes/dingtalk.vue index 3fbbed2fdb52..dcd8131d5242 100644 --- a/frontend/src/views/ai/agents/agent/config/tabs/channels/hermes/dingtalk.vue +++ b/frontend/src/views/ai/agents/agent/config/tabs/channels/hermes/dingtalk.vue @@ -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; } diff --git a/frontend/src/views/ai/agents/agent/config/tabs/channels/hermes/discord.vue b/frontend/src/views/ai/agents/agent/config/tabs/channels/hermes/discord.vue index 1f3272e203f0..25e80eeb5d64 100644 --- a/frontend/src/views/ai/agents/agent/config/tabs/channels/hermes/discord.vue +++ b/frontend/src/views/ai/agents/agent/config/tabs/channels/hermes/discord.vue @@ -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; } diff --git a/frontend/src/views/ai/agents/agent/config/tabs/channels/hermes/feishu.vue b/frontend/src/views/ai/agents/agent/config/tabs/channels/hermes/feishu.vue index c5f699f12bae..15a61873d945 100644 --- a/frontend/src/views/ai/agents/agent/config/tabs/channels/hermes/feishu.vue +++ b/frontend/src/views/ai/agents/agent/config/tabs/channels/hermes/feishu.vue @@ -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; } diff --git a/frontend/src/views/ai/agents/agent/config/tabs/channels/hermes/qq.vue b/frontend/src/views/ai/agents/agent/config/tabs/channels/hermes/qq.vue index 43b745d7e873..9156b427b76f 100644 --- a/frontend/src/views/ai/agents/agent/config/tabs/channels/hermes/qq.vue +++ b/frontend/src/views/ai/agents/agent/config/tabs/channels/hermes/qq.vue @@ -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; } diff --git a/frontend/src/views/ai/agents/agent/config/tabs/channels/hermes/telegram.vue b/frontend/src/views/ai/agents/agent/config/tabs/channels/hermes/telegram.vue index 213c51e7ba27..6d0a3bd8da2a 100644 --- a/frontend/src/views/ai/agents/agent/config/tabs/channels/hermes/telegram.vue +++ b/frontend/src/views/ai/agents/agent/config/tabs/channels/hermes/telegram.vue @@ -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; } diff --git a/frontend/src/views/ai/agents/agent/config/tabs/channels/hermes/wecom.vue b/frontend/src/views/ai/agents/agent/config/tabs/channels/hermes/wecom.vue index e709e18754c1..209355a99256 100644 --- a/frontend/src/views/ai/agents/agent/config/tabs/channels/hermes/wecom.vue +++ b/frontend/src/views/ai/agents/agent/config/tabs/channels/hermes/wecom.vue @@ -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; } diff --git a/frontend/src/views/ai/agents/agent/config/tabs/channels/hermes/weixin.vue b/frontend/src/views/ai/agents/agent/config/tabs/channels/hermes/weixin.vue index d4888a6430c5..3580754d4ed2 100644 --- a/frontend/src/views/ai/agents/agent/config/tabs/channels/hermes/weixin.vue +++ b/frontend/src/views/ai/agents/agent/config/tabs/channels/hermes/weixin.vue @@ -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; } diff --git a/frontend/src/views/ai/agents/agent/config/tabs/channels/openclaw/dingtalk.vue b/frontend/src/views/ai/agents/agent/config/tabs/channels/openclaw/dingtalk.vue index a42e930b94f9..7c0c6933642b 100644 --- a/frontend/src/views/ai/agents/agent/config/tabs/channels/openclaw/dingtalk.vue +++ b/frontend/src/views/ai/agents/agent/config/tabs/channels/openclaw/dingtalk.vue @@ -37,7 +37,14 @@ :rows="3" :placeholder="t('aiTools.agents.allowFromPlaceholder')" /> - {{ t('aiTools.agents.allowFromHelper') }} + + {{ + t('aiTools.agents.allowlistPolicyHelper', [ + t('aiTools.agents.allowFromPlaceholder'), + t('aiTools.agents.dmPolicy'), + ]) + }} + @@ -57,7 +64,14 @@ :rows="3" :placeholder="t('aiTools.agents.groupAllowFromPlaceholder')" /> - {{ t('aiTools.agents.groupAllowFromHelper') }} + + {{ + t('aiTools.agents.allowlistPolicyHelper', [ + t('aiTools.agents.groupAllowFromPlaceholder'), + t('aiTools.agents.groupPolicy'), + ]) + }} + diff --git a/frontend/src/views/ai/agents/agent/config/tabs/channels/openclaw/feishu.vue b/frontend/src/views/ai/agents/agent/config/tabs/channels/openclaw/feishu.vue index 7bce8b28e4f8..0dcb63447c65 100644 --- a/frontend/src/views/ai/agents/agent/config/tabs/channels/openclaw/feishu.vue +++ b/frontend/src/views/ai/agents/agent/config/tabs/channels/openclaw/feishu.vue @@ -52,7 +52,14 @@ :rows="3" :placeholder="t('aiTools.agents.groupAllowFromPlaceholder')" /> - {{ t('aiTools.agents.groupAllowFromHelper') }} + + {{ + t('aiTools.agents.allowlistPolicyHelper', [ + t('aiTools.agents.groupAllowFromPlaceholder'), + t('aiTools.agents.groupPolicy'), + ]) + }} + - {{ t('aiTools.agents.allowFromHelper') }} + + {{ + t('aiTools.agents.allowlistPolicyHelper', [ + t('aiTools.agents.allowFromPlaceholder'), + t('aiTools.agents.dmPolicy'), + ]) + }} + @@ -38,7 +45,14 @@ :rows="3" :placeholder="t('aiTools.agents.groupAllowFromPlaceholder')" /> - {{ t('aiTools.agents.groupAllowFromHelper') }} + + {{ + t('aiTools.agents.allowlistPolicyHelper', [ + t('aiTools.agents.groupAllowFromPlaceholder'), + t('aiTools.agents.groupPolicy'), + ]) + }} + diff --git a/frontend/src/views/ai/agents/agent/config/tabs/channels/openclaw/wecom.vue b/frontend/src/views/ai/agents/agent/config/tabs/channels/openclaw/wecom.vue index d040b29138e5..cc100598d835 100644 --- a/frontend/src/views/ai/agents/agent/config/tabs/channels/openclaw/wecom.vue +++ b/frontend/src/views/ai/agents/agent/config/tabs/channels/openclaw/wecom.vue @@ -36,7 +36,14 @@ :rows="3" :placeholder="t('aiTools.agents.allowFromPlaceholder')" /> - {{ t('aiTools.agents.allowFromHelper') }} + + {{ + t('aiTools.agents.allowlistPolicyHelper', [ + t('aiTools.agents.allowFromPlaceholder'), + t('aiTools.agents.dmPolicy'), + ]) + }} + @@ -56,7 +63,14 @@ :rows="3" :placeholder="t('aiTools.agents.groupAllowFromPlaceholder')" /> - {{ t('aiTools.agents.groupAllowFromHelper') }} + + {{ + t('aiTools.agents.allowlistPolicyHelper', [ + t('aiTools.agents.groupAllowFromPlaceholder'), + t('aiTools.agents.groupPolicy'), + ]) + }} + diff --git a/frontend/src/views/ai/agents/agent/index.vue b/frontend/src/views/ai/agents/agent/index.vue index dd7fcc6ee67a..eede80b803e0 100644 --- a/frontend/src/views/ai/agents/agent/index.vue +++ b/frontend/src/views/ai/agents/agent/index.vue @@ -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'; } }; diff --git a/frontend/src/views/website/runtime/delete/index.vue b/frontend/src/views/website/runtime/delete/index.vue index c5ddee139c90..52b35f277ce7 100644 --- a/frontend/src/views/website/runtime/delete/index.vue +++ b/frontend/src/views/website/runtime/delete/index.vue @@ -13,6 +13,12 @@ {{ $t('website.forceDeleteHelper') }} + + + + {{ $t('app.deleteImageHelper') }} + +