diff --git a/agent/i18n/lang/es-ES.yaml b/agent/i18n/lang/es-ES.yaml index 8e7e2ff10..e86930d76 100644 --- a/agent/i18n/lang/es-ES.yaml +++ b/agent/i18n/lang/es-ES.yaml @@ -142,7 +142,7 @@ PullImageSuccess: 'Descarga de imagen exitosa' AppStoreSyncSuccess: 'Sincronización de la tienda de aplicaciones exitosa' SyncAppDetail: 'Sincronizar configuración de la aplicación' AppVersionNotMatch: 'La aplicación {{ .name }} requiere una versión superior de 1Panel, se omite la sincronización' -MoveSiteDir: 'La actualización actual requiere migrar el directorio del sitio web OpenResty' +MoveSiteDir: 'Se detectó un cambio en el directorio del sitio web. Es necesario migrar el directorio de OpenResty a {{ .name }}' MoveSiteDirSuccess: 'Migración del directorio del sitio exitosa' DeleteRuntimePHP: 'Eliminar entorno de ejecución PHP' CustomAppStoreFileValid: 'Los paquetes de la tienda de aplicaciones deben estar en formato.tar.gz' @@ -192,7 +192,7 @@ ErrSourcePathNotFound: 'El directorio fuente no existe' ErrFavoriteExist: 'Esta ruta ya ha sido marcada como favorita' ErrInvalidChar: 'No se permiten caracteres ilegales' ErrPathNotDelete: 'No se puede eliminar el directorio seleccionado' -ErrLogFileToLarge: 'Log file exceeds 500 MB' +ErrLogFileToLarge: 'El archivo de registro supera los 500 MB y no se puede abrir' FileDropFailed: 'Error al limpiar el archivo {{ .name }}: {{ .err }}' FileDropSuccess: 'Archivo {{ .name }} limpiado correctamente, {{ .count }} archivos eliminados, {{ .size }} de espacio liberado' FileDropSum: 'Limpieza de archivos completada, total {{ .count }} archivos eliminados, {{ .size }} de espacio liberado' @@ -242,7 +242,7 @@ ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid o EabHmacKey no pueden estar en blanco ErrOpenrestyNotFound: 'El modo HTTP requiere OpenResty' ApplySSLStart: 'Iniciando solicitud de certificado, dominio [{{ .domain }}] método de solicitud [{{ .type }}]' dnsAccount: 'DNS Automático' -dnsManual: 'DNS Manual' +dnsManual: 'DNS manual' http: 'HTTP' ApplySSLFailed: 'Solicitud de certificado para [{{ .domain }}] fallida, {{ .detail }}' ApplySSLSuccess: 'Solicitud de certificado para [{{ .domain }}] exitosa' @@ -346,7 +346,7 @@ ErrUserFindErr: 'Búsqueda del usuario {{ .name }} fallida {{ .err }}' # tarea programada CutWebsiteLogSuccess: 'Log del sitio web {{ .name }} cortado con éxito, ruta de respaldo {{ .path }}' HandleShell: 'Ejecutar script {{ .name }}' -HandleCurl: 'URL {{ .name }} にアクセス' +HandleCurl: 'Acceder a la URL {{ .name }}' HandleNtpSync: 'Sincronizar hora del sistema' HandleSystemClean: 'Limpiar caché del sistema' SystemLog: 'Log del sistema' @@ -465,7 +465,7 @@ TaskBackup: 'Respaldar' TaskRecover: 'Recuperar' TaskRollback: 'Revertir' TaskPull: 'Descargar' -TaskCommit: 'Commit' +TaskCommit: 'Crear imagen' TaskBuild: 'Construir' TaskPush: 'Enviar' TaskClean: 'Limpieza' diff --git a/agent/i18n/lang/fa.yaml b/agent/i18n/lang/fa.yaml index 7eff1108b..0ed6d6c14 100644 --- a/agent/i18n/lang/fa.yaml +++ b/agent/i18n/lang/fa.yaml @@ -436,7 +436,7 @@ allow: 'مجاز' deny: 'ممنوع' OpenrestyNotFound: 'OpenResty نصب نشده است' remoteIpIsNull: "لیست IP خالی است" -OpenrestyVersionErr: 'نسخه OpenResty بسیار پایین است؛ به ۱.۲۷.۱.۲-۲-۲-focal ارتقاء دهید' +OpenrestyVersionErr: 'نسخه OpenResty بسیار پایین است؛ به 1.27.1.2-2-2-focal ارتقاء دهید' ErrFileTooLarge: 'فایل بزرگتر از ۱ مگابایت است و قابل بارگذاری نیست' # وظیفه diff --git a/agent/i18n/lang/ko.yaml b/agent/i18n/lang/ko.yaml index ffe451774..d0b770440 100644 --- a/agent/i18n/lang/ko.yaml +++ b/agent/i18n/lang/ko.yaml @@ -113,7 +113,7 @@ ErrPortInOtherApp: '{{ .port }} 포트는 이미 {{ .apps }} 애플리케이션 ErrDbUserNotValid: '기존 데이터베이스, 사용자 이름 및 비밀번호가 일치하지 않습니다' ErrMysqlUserUsedByApps: '이 데이터베이스 사용자는 [{{ .detail }}]에서 사용 중이므로 호스트 변경, 삭제 또는 권한 해제를 할 수 없습니다' ErrUpdateBuWebsite: '응용 프로그램이 성공적으로 업데이트되었지만, 웹사이트 구성 파일 수정에 실패했습니다. 구성을 확인하세요' -Err1PanelNetworkFailed: '기본 컨테이너 네트워크 생성에 실패했습니다 {{ .세부 사항 }}' +Err1PanelNetworkFailed: '기본 컨테이너 네트워크 생성에 실패했습니다 {{ .detail }}' ErrFileParse: '응용 프로그램 docker-compose 파일 구문 분석에 실패했습니다' ErrInstallDirNotFound: '설치 디렉토리가 존재하지 않습니다. 제거를 원하실 경우 강제 제거 를 선택해주세요.' AppStoreIsUpToDate: '앱 스토어가 이미 최신 버전입니다' diff --git a/agent/i18n/lang/lo.yaml b/agent/i18n/lang/lo.yaml index ee55a1efe..71906d2fe 100644 --- a/agent/i18n/lang/lo.yaml +++ b/agent/i18n/lang/lo.yaml @@ -276,7 +276,7 @@ ErrPortRules: 'ຈຳນວນພອດບໍ່ກົງກັນ' ErrPgImagePull: 'ດຶງຮູບພາບເກີນກຳນົດເວລາ; ກະລຸນາກຳນົດຄ່າການເລັ່ງ (Acceleration) ຫຼື ດຶງ {{ .name }} ດ້ວຍຕົນເອງ' PruneHelper: "ທຳຄວາມສະອາດ {{ .name }} ຄືນພື້ນທີ່ດິສກ໌ {{ .size }}" ImageRemoveHelper: "ລຶບຮູບພາບ {{ .name }} ແລ້ວ, ຄືນພື້ນທີ່ດິສກ໌ {{ .size }}" -BuildCache: 'Build Cache' +BuildCache: 'ແຄດການສ້າງ' Volume: 'ວໍລຸມ (Volume)' Network: "ເຄືອຂ່າຍ" PruneStart: 'ກຳລັງດຳເນີນການທຳຄວາມສະອາດ' @@ -417,10 +417,10 @@ captcha: 'ການຢືນຢັນຕົວຕົນ (CAPTCHA)' fiveSeconds: 'ການຢືນຢັນ 5 ວິນາທີ' vulnCheck: 'ກົດລະບຽບເພີ່ມເຕີມ' acl: 'ກົດລະບຽບປັບແຕ່ງເອງ' -sql: 'SQL injection' +sql: 'ການໂຈມຕີແບບສອດແຊກ SQL' cc: 'ຂີດຈຳກັດຄວາມຖີ່ຂອງການເຂົ້າເຖິງ' defaultUrlBlack: 'ກົດລະບຽບ URL' -sqlInject: 'SQL injection' +sqlInject: 'ການໂຈມຕີແບບສອດແຊກ SQL' ErrDBNotExist: 'ຖານຂໍ້ມູນບໍ່ມີຢູ່' allow: 'ອະນຸຍາດ' deny: 'ປະຕິເສດ' @@ -464,7 +464,7 @@ TaskImport: "ນຳເຂົ້າ" TaskExport: "ສົ່ງອອກ" Website: 'ເວັບໄຊ' App: 'ແອັບພລິເຄຊັນ' -Runtime: 'Runtime' +Runtime: 'ສະພາບແວດລ້ອມຣັນທາມ' Database: 'ຖານຂໍ້ມູນ' ConfigFTP: 'ສ້າງຜູ້ໃຊ້ FTP {{ .name }}' ConfigOpenresty: 'ສ້າງໄຟລ໌ການຕັ້ງຄ່າ OpenResty' @@ -485,7 +485,7 @@ Compose: 'Compose' Container: 'ຄອນເທນເນີ' AppLink: 'ແອັບພລິເຄຊັນທີ່ເຊື່ອມໂຍງ' EnableSSL: 'ເປີດໃຊ້ HTTPS' -AppStore: 'App Store' +AppStore: 'ຮ້ານແອັບ' TaskSync: 'ຊິງຄ໌' LocalApp: 'ແອັບພລິເຄຊັນພາຍໃນເຄື່ອງ' SubTask: 'ວຽກຍ່ອຍ' diff --git a/agent/i18n/lang/ms.yaml b/agent/i18n/lang/ms.yaml index b9b0e8ac2..71da5e07f 100644 --- a/agent/i18n/lang/ms.yaml +++ b/agent/i18n/lang/ms.yaml @@ -164,7 +164,7 @@ ErrDatabaseNotFound: 'Pangkalan data {{ .name }} tidak wujud' # SSH ExportIP: 'IP Log Masuk' ExportArea: 'Lokasi' -ExportPort: 'Port' +ExportPort: 'Nombor port' ExportAuthMode: 'Kaedah Log Masuk' ExportUser: 'Pengguna' ExportStatus: 'Status Log Masuk' @@ -216,7 +216,7 @@ ErrWebsiteDir: 'Sila pilih direktori dalam direktori laman web.' ErrComposerFileNotFound: 'Fail composer.json tidak wujud' ErrRuntimeNoPort: 'Persekitaran runtime tidak diset dengan port, sila edit persekitaran runtime terlebih dahulu.' ErrRuntimeProjectDirContainsCodeDir: 'Direktori runtime mengandungi direktori projek yang dipilih. Sila pilih direktori projek lain dan cipta semula.' -Status: 'Status' +Status: 'Keadaan' start: 'Mulakan' stop: 'Berhenti' restart: 'Mulakan Semula' @@ -241,7 +241,7 @@ ErrSSLCertificateFormat: 'Format fail sijil tidak betul, sila gunakan format pem ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid atau EabHmacKey tidak boleh kosong' ErrOpenrestyNotFound: 'Mod HTTP memerlukan OpenResty dipasang terlebih dahulu' ApplySSLStart: 'Mula memohon sijil, nama domain [{{ .domain }}] kaedah permohonan [{{ .type }}]' -dnsAccount: 'DNS Auto' +dnsAccount: 'DNS automatik' dnsManual: 'Manual DNS' http: 'HTTP' ApplySSLFailed: 'Permohonan untuk sijil [{{ .domain }}] gagal, {{ .detail }}' @@ -400,7 +400,7 @@ urlHelper: 'URL Terlarang' dirFilter: 'Penapis direktori' xss: 'XSS' phpExec: 'Pelaksanaan skrip PHP' -oneWordTrojan: 'One Word Trojan' +oneWordTrojan: 'Trojan satu baris' appFilter: 'Gunakan penapisan direktori berbahaya' webShell: 'Webshell' args: 'Peraturan parameter' @@ -463,14 +463,14 @@ TaskRestart: 'Mulakan semula' TaskProtect: 'Lindungi' TaskBackup: 'Sandaran' TaskRecover: 'Pulihkan' -TaskRollback: 'Rollback' +TaskRollback: 'Pulangkan semula' TaskPull: 'Tarik' TaskCommit: 'Komit' TaskBuild: 'Bina' TaskPush: 'Hantar' TaskClean: 'Pembersihan' TaskHandle: 'Laksanakan' -TaskImport: 'Import' +TaskImport: 'Import data' TaskExport: 'Eksport' Website: 'Laman web' App: 'Aplikasi' @@ -495,7 +495,7 @@ Compose: 'Orkestrasi' Container: 'Bekas' AppLink: 'Aplikasi Terpaut' EnableSSL: 'Dayakan HTTPS' -AppStore: 'App Store' +AppStore: 'Kedai aplikasi' TaskSync: 'Segerakkan' LocalApp: 'Aplikasi Tempatan' SubTask: 'Subtugas' @@ -516,7 +516,7 @@ OllamaModelSize: 'Dapatkan saiz model Ollama {{ .name }}' AIBenchmarkRun: "Jalankan penanda aras AI" # tugas - syot kilat -Snapshot: 'Snapshot' +Snapshot: 'Syot kilat' SnapDBInfo: 'Tulis maklumat pangkalan data 1Panel' SnapCopy: 'Salin fail & direktori {{ .name }}' SnapNewDB: 'Mulakan sambungan {{ .name }} pangkalan data' @@ -557,7 +557,7 @@ RecoverWebsite: 'Pulihkan direktori tapak web' RecoverAppImage: 'Pulihkan sandaran imej syot kilat' RecoverCompose: 'Pulihkan kandungan komposer lain' RecoverComposeList: 'Dapatkan semua komposer untuk dipulihkan' -RecoverComposeItem: 'Recover compose {{ .name }}' +RecoverComposeItem: 'Pulihkan orkestrasi {{ .name }}' RecoverAppEmpty: 'Tiada sandaran imej aplikasi ditemui dalam fail syot kilat' RecoverBaseData: 'Pulihkan data asas dan fail' RecoverDaemonJsonEmpty: 'Kedua-dua fail syot kilat dan mesin semasa tidak mempunyai fail daemon.json konfigurasi bekas' diff --git a/agent/i18n/lang/pt-BR.yaml b/agent/i18n/lang/pt-BR.yaml index 15ef25846..5a152bd06 100644 --- a/agent/i18n/lang/pt-BR.yaml +++ b/agent/i18n/lang/pt-BR.yaml @@ -113,7 +113,7 @@ ErrPortInOtherApp: 'A porta {{ .port }} já está ocupada pelo aplicativo {{ .ap ErrDbUserNotValid: 'Banco de dados existente, nome de usuário e senha não correspondem' ErrMysqlUserUsedByApps: 'Este usuário do banco de dados está sendo usado por [{{ .detail }}]; seu host não pode ser alterado, e ele não pode ser excluído nem ter sua autorização revogada' ErrUpdateBuWebsite: 'O aplicativo foi atualizado com sucesso, mas a modificação do arquivo de configuração do site falhou., verifique a configuração' -Err1PanelNetworkFailed: 'Falha na criação da rede de contêiner padrão {{ .detalhe }}' +Err1PanelNetworkFailed: 'Falha na criação da rede de contêiner padrão {{ .detail }}' ErrFileParse: 'Falha na análise do arquivo docker-compose do aplicativo' ErrInstallDirNotFound: 'O diretório de instalação não existe. Se precisar desinstalar, selecione Forçar desinstalação' AppStoreIsUpToDate: 'A loja de aplicativos já é a versão mais recente' @@ -192,7 +192,7 @@ ErrSourcePathNotFound: 'O diretório de origem não existe' ErrFavoriteExist: 'Este caminho já foi favorito' ErrInvalidChar: 'Caracteres ilegais não são permitidos' ErrPathNotDelete: 'O diretório selecionado não pode ser excluído' -ErrLogFileToLarge: 'Fail log melebihi 500MB, tidak boleh dibuka' +ErrLogFileToLarge: 'O arquivo de log excede 500 MB e não pode ser aberto' FileDropFailed: 'Falha ao limpar arquivo {{ .name }}: {{ .err }}' FileDropSuccess: 'Arquivo {{ .name }} limpo com sucesso, {{ .count }} arquivos removidos, {{ .size }} de espaço em disco liberado' FileDropSum: 'Limpeza de arquivos concluída com sucesso, total de {{ .count }} arquivos removidos, total de {{ .size }} de espaço em disco liberado' @@ -216,7 +216,7 @@ ErrWebsiteDir: ', selecione um diretório dentro do diretório do site.' ErrComposerFileNotFound: 'O arquivo composer.json não existe' ErrRuntimeNoPort: 'O ambiente de tempo de execução não está configurado com uma porta, edite o ambiente de tempo de execução primeiro.' ErrRuntimeProjectDirContainsCodeDir: 'O diretório de execução inclui o diretório de projeto selecionado. Escolha outro diretório de projeto e crie novamente.' -Status: 'Status' +Status: 'Estado' start: 'Iniciar' stop: 'Parar' restart: 'Reiniciar' @@ -461,11 +461,11 @@ AgentPluginUpdate: 'Atualizar plugin' AgentPluginUninstall: 'Desinstalar plugin' TaskRestart: 'Reiniciar' TaskProtect: 'Proteger' -TaskBackup: 'Backup' +TaskBackup: 'Fazer cópia de segurança' TaskRecover: 'Recuperar' TaskRollback: 'Reverter' TaskPull: 'Puxar' -TaskCommit: 'Commit' +TaskCommit: 'Criar imagem' TaskBuild: 'Construir' TaskPush: 'Enviar' TaskClean: 'Limpeza' diff --git a/agent/i18n/lang/ru.yaml b/agent/i18n/lang/ru.yaml index 18acd561f..d4d560c09 100644 --- a/agent/i18n/lang/ru.yaml +++ b/agent/i18n/lang/ru.yaml @@ -402,7 +402,7 @@ xss: 'XSS' phpExec: 'Выполнение PHP-скрипта' oneWordTrojan: 'Троян из одного слова' appFilter: 'Применить фильтрацию опасных каталогов' -webShell: 'Be6-оболочка' +webShell: 'Веб-оболочка' args: 'Правила параметров' protocolFilter: 'Фильтрация протоколов' javaFilter: 'Фильтр опасных файлов Java' @@ -472,7 +472,7 @@ TaskClean: 'Очистка' TaskHandle: 'Выполнить' TaskImport: 'Импорт' TaskExport: 'Экспорт' -Website: 'Be6-сайт' +Website: 'Веб-сайт' App: 'Приложение' Runtime: 'Среда выполнения' Database: 'База данных' diff --git a/agent/i18n/lang/tr.yaml b/agent/i18n/lang/tr.yaml index 0ddbe67df..28d4885ad 100644 --- a/agent/i18n/lang/tr.yaml +++ b/agent/i18n/lang/tr.yaml @@ -164,7 +164,7 @@ ErrDatabaseNotFound: '{{ .name }} veritabanı mevcut değil' # SSH ExportIP: 'Giriş IP' ExportArea: 'Konum' -ExportPort: 'Port' +ExportPort: 'Bağlantı noktası' ExportAuthMode: 'Giriş Yöntemi' ExportUser: 'Kullanıcı' ExportStatus: 'Giriş Durumu' diff --git a/core/app/api/v2/auth.go b/core/app/api/v2/auth.go index 52b8cdcf7..9cd5e4516 100644 --- a/core/app/api/v2/auth.go +++ b/core/app/api/v2/auth.go @@ -196,11 +196,19 @@ func (b *BaseApi) PasskeyFinishLogin(c *gin.Context) { // @Security Timestamp // @Router /core/auth/logout [post] func (b *BaseApi) LogOut(c *gin.Context) { + result, prepareErr := xpack.AuthProvider.PrepareLogout(c) if err := authService.LogOut(c); err != nil { helper.InternalServer(c, err) return } - helper.Success(c) + if prepareErr != nil { + global.LOG.Warnf("prepare external logout failed: %v", prepareErr) + result = &dto.LogoutResult{} + } + if result == nil { + result = &dto.LogoutResult{} + } + helper.SuccessWithData(c, result) } // @Tags Auth diff --git a/core/app/auth/auth.go b/core/app/auth/auth.go index 9a00ead27..825c1edb4 100644 --- a/core/app/auth/auth.go +++ b/core/app/auth/auth.go @@ -90,6 +90,43 @@ func BeginMFALogin(c *gin.Context, name, entrance, mfaStatus string) *dto.UserLo return &dto.UserLoginInfo{Name: name, MfaStatus: mfaStatus, MfaSession: mfaSession} } +func BeginAuthSourceMFALogin( + c *gin.Context, + name, entrance, mfaStatus, authSource string, + authSourceID uint, + authSourceConfigVersion uint64, +) *dto.UserLoginInfo { + ip := common.GetRealClientIP(c) + mfaSession := initauth.GetMFASessionStore().SetWithAuthSource( + name, + entrance, + ip, + authSource, + authSourceID, + authSourceConfigVersion, + ) + return &dto.UserLoginInfo{Name: name, MfaStatus: mfaStatus, MfaSession: mfaSession} +} + +func BeginAuthSourceMFALoginWithSession( + c *gin.Context, + name, entrance, mfaStatus, authSource string, + authSourceID uint, + authSourceConfigVersion uint64, + externalIssuer, externalNameID, externalNameIDFormat, externalSessionIndex string, + externalSessionExpiresAt time.Time, + externalSessionRequired bool, +) *dto.UserLoginInfo { + ip := common.GetRealClientIP(c) + mfaSession := initauth.GetMFASessionStore().SetWithAuthSourceSession( + name, entrance, ip, authSource, authSourceID, authSourceConfigVersion, + externalIssuer, externalNameID, externalNameIDFormat, externalSessionIndex, + externalSessionExpiresAt, + externalSessionRequired, + ) + return &dto.UserLoginInfo{Name: name, MfaStatus: mfaStatus, MfaSession: mfaSession} +} + func VerifyMFALogin(c *gin.Context, sessionID, code, entrance string) (string, string, error) { settingRepo := repo.NewISettingRepo() mfaSessions := initauth.GetMFASessionStore() diff --git a/core/app/dto/auth.go b/core/app/dto/auth.go index 5a871849a..3042e1c87 100644 --- a/core/app/dto/auth.go +++ b/core/app/dto/auth.go @@ -13,17 +13,32 @@ type UserLoginInfo struct { MfaSession string `json:"mfaSession"` } +// AuthNavigation describes a browser handoff to an external identity provider. +// RedirectURL is used for HTTP-Redirect binding; PostURL and Fields are used +// for an auto-submitted HTTP-POST form. +type AuthNavigation struct { + Binding string `json:"binding"` + RedirectURL string `json:"redirectURL,omitempty"` + PostURL string `json:"postURL,omitempty"` + Fields map[string]string `json:"fields,omitempty"` +} + +type LogoutResult struct { + SAML2Navigation *AuthNavigation `json:"saml2Navigation,omitempty"` +} + type PasskeyBeginResponse struct { SessionID string `json:"sessionId"` PublicKey interface{} `json:"publicKey"` } type Login struct { - Name string `json:"name" validate:"required"` - Password string `json:"password" validate:"required"` - Captcha string `json:"captcha"` - CaptchaID string `json:"captchaID"` - Language string `json:"language" validate:"required,oneof=zh en 'zh-Hant' ko ja ru ms 'pt-BR' tr 'es-ES' fa lo"` + Name string `json:"name" validate:"required"` + Password string `json:"password" validate:"required"` + Captcha string `json:"captcha"` + CaptchaID string `json:"captchaID"` + Language string `json:"language" validate:"required,oneof=zh en 'zh-Hant' ko ja ru ms 'pt-BR' tr 'es-ES' fa lo"` + AuthSource string `json:"authSource,omitempty"` } type SystemSetting struct { diff --git a/core/app/repo/agent.go b/core/app/repo/agent.go index 6a2b8849d..34af7e45c 100644 --- a/core/app/repo/agent.go +++ b/core/app/repo/agent.go @@ -10,6 +10,13 @@ type AgentRepo struct{} type IAgentRepo interface { GetWebsiteSSL(opts ...global.DBOption) (model.WebsiteSSL, error) GetCA(opts ...global.DBOption) (model.WebsiteCA, error) + GetSettingValue(key string) (string, error) +} + +func (a *AgentRepo) GetSettingValue(key string) (string, error) { + var setting model.Setting + err := global.AgentDB.Model(&model.Setting{}).Where("key = ?", key).First(&setting).Error + return setting.Value, err } func NewIAgentRepo() IAgentRepo { diff --git a/core/go.mod b/core/go.mod index 0a29b7632..196d5c189 100644 --- a/core/go.mod +++ b/core/go.mod @@ -4,13 +4,17 @@ go 1.26.1 require ( github.com/1panel-dev/base64Captcha v1.3.8 + github.com/beevik/etree v1.5.0 + github.com/coreos/go-oidc/v3 v3.20.0 github.com/creack/pty v1.1.24 + github.com/crewjam/saml v0.5.1 github.com/fsnotify/fsnotify v1.10.1 github.com/gin-contrib/gzip v1.2.6 github.com/gin-gonic/gin v1.12.0 github.com/glebarez/sqlite v1.11.0 github.com/go-gormigrate/gormigrate/v2 v2.1.6 github.com/go-ldap/ldap/v3 v3.4.14 + github.com/go-jose/go-jose/v4 v4.1.4 github.com/go-playground/validator/v10 v10.30.3 github.com/go-resty/resty/v2 v2.17.2 github.com/go-webauthn/webauthn v0.17.4 @@ -18,12 +22,14 @@ require ( github.com/gorilla/websocket v1.5.3 github.com/jinzhu/copier v0.4.0 github.com/johnfercher/maroto/v2 v2.4.0 + github.com/mattermost/xml-roundtrip-validator v0.1.0 github.com/nicksnyder/go-i18n/v2 v2.6.1 github.com/oschwald/maxminddb-golang v1.13.1 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/pkg/errors v0.9.1 github.com/pkg/sftp v1.13.11 github.com/robfig/cron/v3 v3.0.1 + github.com/russellhaering/goxmldsig v1.4.0 github.com/shirou/gopsutil/v4 v4.26.6 github.com/sirupsen/logrus v1.9.4 github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e @@ -35,6 +41,7 @@ require ( github.com/xlzd/gotp v0.1.0 golang.org/x/crypto v0.54.0 golang.org/x/net v0.57.0 + golang.org/x/oauth2 v0.36.0 golang.org/x/sys v0.47.0 golang.org/x/term v0.45.0 golang.org/x/text v0.40.0 @@ -77,6 +84,7 @@ require ( github.com/go-webauthn/x v0.2.6 // indirect github.com/goccy/go-json v0.10.6 // indirect github.com/goccy/go-yaml v1.19.2 // indirect + github.com/golang-jwt/jwt/v4 v4.5.2 // indirect github.com/golang-jwt/jwt/v5 v5.3.1 // indirect github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/google/go-tpm v0.9.8 // indirect @@ -87,6 +95,7 @@ require ( github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect github.com/johnfercher/go-tree v1.1.0 // indirect + github.com/jonboulle/clockwork v0.2.2 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/cpuid/v2 v2.3.0 // indirect github.com/kr/fs v0.1.0 // indirect diff --git a/core/go.sum b/core/go.sum index 4ad72525d..764ac1636 100644 --- a/core/go.sum +++ b/core/go.sum @@ -8,6 +8,9 @@ github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= github.com/alexbrainman/sspi v0.0.0-20250919150558-7d374ff0d59e h1:4dAU9FXIyQktpoUAgOJK3OTFc/xug0PCXYCqU0FgDKI= github.com/alexbrainman/sspi v0.0.0-20250919150558-7d374ff0d59e/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4= +github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A= +github.com/beevik/etree v1.5.0 h1:iaQZFSDS+3kYZiGoc9uKeOkUY3nYMXOKLl6KIJxiJWs= +github.com/beevik/etree v1.5.0/go.mod h1:gPNJNaBGVZ9AwsidazFZyygnd+0pAU38N4D+WemwKNs= github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/boombuler/barcode v1.1.0 h1:ChaYjBR63fr4LFyGn8E8nt7dBSt3MiU3zMOZqFvVkHo= github.com/boombuler/barcode v1.1.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= @@ -21,9 +24,14 @@ github.com/clipperhouse/uax29/v2 v2.7.0 h1:+gs4oBZ2gPfVrKPthwbMzWZDaAFPGYK72F0NJ github.com/clipperhouse/uax29/v2 v2.7.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM= github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M= github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU= +github.com/coreos/go-oidc/v3 v3.20.0 h1:EtE0WIBHk03N+DqGkY4+UONzzZHk7amKt6IyNd7OsZE= +github.com/coreos/go-oidc/v3 v3.20.0/go.mod h1:DYCf24+ncYi+XkIH97GY1+dqoRlbaSI26KVTCI9SrY4= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= +github.com/crewjam/saml v0.5.1 h1:g+mfp0CrLuLRZCK793PgJcZeg5dS/0CDwoeAX2zcwNI= +github.com/crewjam/saml v0.5.1/go.mod h1:r0fDkmFe5URDgPrmtH0IYokva6fac3AUdstiPhyEolQ= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -57,6 +65,8 @@ github.com/go-gormigrate/gormigrate/v2 v2.1.6 h1:VtX+l1Stj2v5RGubVQk0LS/8EPGXR+l github.com/go-gormigrate/gormigrate/v2 v2.1.6/go.mod h1:PZpedQc4tWaxn6kvXicwhinh3L0seLpMc5ReKRX5id4= github.com/go-ldap/ldap/v3 v3.4.14 h1:D6PYdEgsaVzsXyr6w/yDC06Ria4uUhWm+Rb+er8lfAs= github.com/go-ldap/ldap/v3 v3.4.14/go.mod h1:S4eJUMUNjDkE0ZJtIZdybwyb03sGGLW6gxXT1Hs8VKA= +github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= +github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-openapi/jsonpointer v0.23.0 h1:c25HFTJ6uWGmoe5BQI6p72p4o7KnlWYsy1MeFlAumsw= @@ -106,6 +116,8 @@ github.com/goccy/go-json v0.10.6 h1:p8HrPJzOakx/mn/bQtjgNjdTcN+/S6FcG2CTtQOrHVU= github.com/goccy/go-json v0.10.6/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= +github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI= +github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY= github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= @@ -158,6 +170,8 @@ github.com/johnfercher/go-tree v1.1.0 h1:L0Fs5jLR1uA2e/CwfHjNdO/Lt4IGQ46QgxarAC1 github.com/johnfercher/go-tree v1.1.0/go.mod h1:DUO6QkXIFh1K7jeGBIkLCZaeUgnkdQAsB64FDSoHswg= github.com/johnfercher/maroto/v2 v2.4.0 h1:Nc/jA2RCZvNZESrQj41HJOgtkwmerSHd5FUbP4dRrIE= github.com/johnfercher/maroto/v2 v2.4.0/go.mod h1:Nnxa3g4f+vzdx/u/dUgx/52HnrCOCt5QBPSdeSlkFZQ= +github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= +github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= @@ -165,14 +179,21 @@ github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzh github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/mattermost/xml-roundtrip-validator v0.1.0 h1:RXbVD2UAl7A7nOTR4u7E3ILa4IbtvKBHw64LDsmu9hU= +github.com/mattermost/xml-roundtrip-validator v0.1.0/go.mod h1:qccnGMcpgwcNaBnxqpJpWWUiPNr5H3O8eDgGV9gT5To= github.com/mattn/go-isatty v0.0.21 h1:xYae+lCNBP7QuW4PUnNG61ffM4hVIfm+zUzDuSzYLGs= github.com/mattn/go-isatty v0.0.21/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4= github.com/mattn/go-runewidth v0.0.21 h1:jJKAZiQH+2mIinzCJIaIG9Be1+0NR+5sz/lYEEjdM8w= @@ -201,6 +222,7 @@ github.com/philhofer/fwd v1.2.0/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJ github.com/phpdave11/gofpdf v1.4.3 h1:M/zHvS8FO3zh9tUd2RCOPEjyuVcs281FCyF22Qlz/IA= github.com/phpdave11/gofpdf v1.4.3/go.mod h1:MAwzoUIgD3J55u0rxIG2eu37c+XWhBtXSpPAhnQXf/o= github.com/phpdave11/gofpdi v1.0.15/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -218,8 +240,12 @@ github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94 github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/russellhaering/goxmldsig v1.4.0 h1:8UcDh/xGyQiyrW+Fq5t8f+l2DLB1+zlhYzkPUJ7Qhys= +github.com/russellhaering/goxmldsig v1.4.0/go.mod h1:gM4MDENBQf7M+V824SGfyIUVFWydB7n0KkEubVJl+Tw= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= github.com/sagikazarmark/locafero v0.12.0 h1:/NQhBAkUb4+fH1jivKHWusDYFjMOOKU88eegjfxfHb4= @@ -251,6 +277,7 @@ github.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4= github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= @@ -300,6 +327,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.57.0 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE= golang.org/x/net v0.57.0/go.mod h1:KpXc8iv+r3XplLAG/f7Jsf9RPszJzdR0f58q9vGOuEU= +golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= +golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek= golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -324,11 +353,14 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gorm.io/driver/sqlite v1.6.0 h1:WHRRrIiulaPiPFmDcod6prc4l2VGVWHz80KspNsxSfQ= diff --git a/core/i18n/lang/en.yaml b/core/i18n/lang/en.yaml index 3c2a8e55f..1307bf35a 100644 --- a/core/i18n/lang/en.yaml +++ b/core/i18n/lang/en.yaml @@ -42,6 +42,29 @@ ErrPasskeyLimit: "Passkey limit reached (max 5)" ErrPasskeySession: "Passkey session expired or invalid" ErrPasskeyDuplicate: "Passkey already exists" ErrPasskeyVerify: "Passkey verification failed" +ErrOIDCNotEnabled: "OIDC authentication is not enabled" +ErrOIDCConfigInvalid: "OIDC configuration is invalid" +ErrOIDCConfigChanged: "OIDC configuration changed; start authentication again" +ErrOIDCDiscoveryFailed: "Failed to discover the OIDC provider configuration" +ErrOIDCIssuerMismatch: "The OIDC issuer does not match the configured issuer" +ErrOIDCUnsupportedPKCE: "The OIDC provider does not support the required PKCE method" +ErrOIDCUnsupportedSigningAlgorithm: "The OIDC signing algorithm is not supported" +ErrOIDCInvalidState: "The OIDC login state is invalid or has already been used" +ErrOIDCLoginExpired: "The OIDC login request has expired; try again" +ErrOIDCTokenExchange: "Failed to exchange the OIDC authorization code" +ErrOIDCTokenValidation: "Failed to validate the OIDC token" +ErrOIDCUserInfoValidation: "Failed to validate OIDC user information" +ErrOIDCNameClaimMissing: "The configured OIDC user name claim is missing or invalid" +ErrOIDCNameConflictLocal: "The OIDC user name conflicts with a local user" +ErrOIDCNameConflictLDAP: "The OIDC user name conflicts with an LDAP user" +ErrOIDCNameConflictOIDC: "The OIDC user name conflicts with another OIDC identity" +ErrOIDCDefaultRoleInvalid: "The default role configured for OIDC is unavailable" +ErrOIDCPrivateAddressDenied: "The OIDC endpoint address is not allowed by the network security policy" +ErrOIDCTLSValidation: "OIDC TLS certificate validation failed" +ErrOIDCTestExpired: "The OIDC browser test has expired; run the test again" +ErrOIDCLocalCredentialsReadonly: "OIDC user names and passwords are managed by the identity provider and cannot be changed locally." +ErrOIDCPasswordExpirationUnsupported: "OIDC users do not use the local password expiration policy." +ErrOIDCInternal: "OIDC authentication encountered an internal error. Please try again later." # user and permission ErrNoSuchUser: "User information not found, check and try again!" @@ -121,11 +144,11 @@ ErrVMStorageInUse: "Storage pool is in use and cannot be deleted" ErrVMStorageNameCannotChange: "Storage pool name cannot be changed" ErrVMStoragePathCannotChange: "Storage pool path cannot be changed" ErrVMRunning: "Virtual machine is running" -ErrVMLibvirtConnect: "Failed to connect to libvirt" +ErrVMLibvirtConnect: "Failed to connect to libvirt: {{ .detail }}" ErrVMPermission: "No permission to operate virtual machine: {{ .detail }}" -ErrVMNetworkNotFound: "Virtual machine network does not exist" -ErrVMInvalidPath: "Invalid virtual machine path" -ErrVMInvalidInput: "Invalid virtual machine parameter" +ErrVMNetworkNotFound: "Virtual machine network does not exist: {{ .detail }}" +ErrVMInvalidPath: "Invalid virtual machine path: {{ .detail }}" +ErrVMInvalidInput: "Invalid virtual machine parameter: {{ .detail }}" ErrVMCommandFailed: "Virtual machine command failed: {{ .err }}" VMCreateTask: "Create virtual machine [{{ .name }}]" VMCreateFromTemplateTask: "Create virtual machine [{{ .name }}] from template" @@ -255,7 +278,7 @@ PushAppInstallTaskToNode: "Push app installation task to node [{{ .name }}]" AppInstallTask: "App installation task" PushAppFailed: "Failed to push app installation task" SkillHubInstallTask: "Install skill [{{ .name }}]" -SkillHubInstallToTarget: "Install skill to target [{{ .name }}]" +SkillHubInstallToTarget: "Install skill [{{ .name }}] to target [{{ .target }}]" # script library ScriptLibrary: "Script Library" @@ -472,3 +495,33 @@ ErrLDAPSyncRunning: "An LDAP synchronization task is already running." ErrLDAPSyncDirectoryIncomplete: "LDAP returned an incomplete full query result. No user status was changed." ErrLDAPSyncFailed: "LDAP user synchronization failed." LDAPSyncSuccess: "LDAP user synchronization completed successfully." +ErrSAML2NotEnabled: "SAML2 authentication is not enabled." +ErrSAML2ConfigInvalid: "The SAML2 configuration is invalid." +ErrSAML2ConfigChanged: "The SAML2 configuration has changed. Start authentication again." +ErrSAML2PanelOriginMissing: "Enter a valid 1Panel public URL containing only scheme, host, and optional port." +ErrSAML2MetadataInvalid: "The IdP Metadata is missing or invalid." +ErrSAML2MetadataURLInvalid: "The IdP Metadata URL or an endpoint in the Metadata is not allowed." +ErrSAML2MetadataFetch: "Failed to load the IdP Metadata." +ErrSAML2MetadataCertificate: "The IdP Metadata does not contain a usable signing certificate." +ErrSAML2KeyPairInvalid: "The SP private key and certificate are invalid or do not match." +ErrSAML2NameAttributeMissing: "The configured SAML2 username attribute is missing or invalid." +ErrSAML2DefaultRoleInvalid: "The default role configured for SAML2 is unavailable." +ErrSAML2SLOUnavailable: "The IdP does not provide a supported Single Logout service." +ErrSAML2TestExpired: "The SAML2 test has expired. Run it again." +ErrSAML2LoginExpired: "The SAML2 login request has expired. Try again." +ErrSAML2InvalidState: "The SAML2 login state is invalid or has already been used." +ErrSAML2RequestBuild: "Failed to build the SAML2 request." +ErrSAML2ResponseInvalid: "The SAML2 response is invalid." +ErrSAML2SignatureInvalid: "The SAML2 signature is invalid." +ErrSAML2Replay: "The SAML2 message has already been used." +ErrSAML2NameIDMissing: "The SAML2 NameID is missing or invalid." +ErrSAML2SessionIndexMissing: "The SAML2 SessionIndex is missing or invalid." +ErrSAML2NameConflictLocal: "The SAML2 username conflicts with a local user." +ErrSAML2NameConflictLDAP: "The SAML2 username conflicts with an LDAP user." +ErrSAML2NameConflictOIDC: "The SAML2 username conflicts with an OIDC user." +ErrSAML2NameConflictSAML2: "The SAML2 username conflicts with another SAML2 identity." +ErrSAML2Internal: "An internal error occurred during SAML2 authentication. Try again later." +ErrSAML2LogoutExpired: "The SAML2 logout request has expired." +ErrSAML2LogoutInvalid: "The SAML2 logout message is invalid." +ErrSAML2LocalCredentialsReadonly: "SAML2 usernames and passwords are managed by the identity provider and cannot be changed locally." +ErrSAML2PasswordExpirationUnsupported: "SAML2 users do not use the local password expiration policy." diff --git a/core/i18n/lang/es-ES.yaml b/core/i18n/lang/es-ES.yaml index d9d3c9b53..1349edbd9 100644 --- a/core/i18n/lang/es-ES.yaml +++ b/core/i18n/lang/es-ES.yaml @@ -6,7 +6,7 @@ ErrInternalServer: 'Error interno: {{ .detail }}' ErrInternalServerKey: "Error interno del servidor:" ErrRecordExist: 'Registro ya existe' ErrRecordNotFound: 'Registro no encontrado' -ErrStructTransform: 'Error de conversión: {{ .err }}' +ErrStructTransform: 'Error de conversión: {{ .detail }}' ErrNotSupportType: 'Tipo no soportado: {{ .name }}' ErrDemoEnvironment: 'No disponible en demo' ErrCmdTimeout: 'Comando agotó tiempo' @@ -42,6 +42,29 @@ ErrPasskeyLimit: "Límite de Passkey alcanzado (máximo 5)" ErrPasskeySession: "La sesión de Passkey ha expirado o no es válida" ErrPasskeyDuplicate: "Passkey ya existe" ErrPasskeyVerify: "Error al verificar Passkey" +ErrOIDCNotEnabled: "La autenticación OIDC no está habilitada" +ErrOIDCConfigInvalid: "La configuración de OIDC no es válida" +ErrOIDCConfigChanged: "La configuración de OIDC ha cambiado; inicie la autenticación de nuevo" +ErrOIDCDiscoveryFailed: "No se pudo descubrir la configuración del Provider OIDC" +ErrOIDCIssuerMismatch: "El Issuer de OIDC no coincide con el Issuer configurado" +ErrOIDCUnsupportedPKCE: "El Provider OIDC no admite el método PKCE requerido" +ErrOIDCUnsupportedSigningAlgorithm: "El algoritmo de firma OIDC no es compatible" +ErrOIDCInvalidState: "El estado de inicio de sesión OIDC no es válido o ya se ha utilizado" +ErrOIDCLoginExpired: "La solicitud de inicio de sesión OIDC ha caducado; inténtelo de nuevo" +ErrOIDCTokenExchange: "No se pudo intercambiar el código de autorización OIDC" +ErrOIDCTokenValidation: "No se pudo validar el Token OIDC" +ErrOIDCUserInfoValidation: "No se pudo validar la información del usuario OIDC" +ErrOIDCNameClaimMissing: "El Claim de nombre de usuario OIDC configurado no existe o no es válido" +ErrOIDCNameConflictLocal: "El nombre de usuario OIDC entra en conflicto con un usuario local" +ErrOIDCNameConflictLDAP: "El nombre de usuario OIDC entra en conflicto con un usuario LDAP" +ErrOIDCNameConflictOIDC: "El nombre de usuario OIDC entra en conflicto con otra identidad OIDC" +ErrOIDCDefaultRoleInvalid: "El rol predeterminado configurado para OIDC no está disponible" +ErrOIDCPrivateAddressDenied: "La dirección del Endpoint OIDC no está permitida por la política de seguridad de red" +ErrOIDCTLSValidation: "Error al validar el certificado TLS de OIDC" +ErrOIDCTestExpired: "La prueba de OIDC en el navegador ha caducado; vuelva a ejecutarla" +ErrOIDCLocalCredentialsReadonly: "Los nombres de usuario y las contraseñas OIDC los administra el Provider de identidad y no se pueden cambiar localmente." +ErrOIDCPasswordExpirationUnsupported: "Los usuarios OIDC no utilizan la política local de caducidad de contraseñas." +ErrOIDCInternal: "Se produjo un error interno durante la autenticación OIDC. Inténtelo de nuevo más tarde." # usuario y permisos ErrNoSuchUser: "No se encontró la información del usuario. Verifique e intente de nuevo." @@ -114,12 +137,12 @@ ErrVMNotFound: "La máquina virtual no existe" ErrVMAlreadyExists: "La máquina virtual ya existe" ErrVMImageAlreadyExists: "La imagen de la máquina virtual ya existe: {{ .detail }}" ErrVMStoragePathInUse: "La ruta del pool de almacenamiento ya está usada por [{{ .name }}]" -ErrVMHelperNotFound: "1panel-kvm not found" -ErrVMBridgeManaged: "Bridge name is already managed by libvirt or Docker" -ErrVMNetworkInUse: "Network is in use and cannot be deleted" -ErrVMStorageInUse: "Storage pool is in use and cannot be deleted" -ErrVMStorageNameCannotChange: "Storage pool name cannot be changed" -ErrVMStoragePathCannotChange: "Storage pool path cannot be changed" +ErrVMHelperNotFound: "No se encontró 1panel-kvm" +ErrVMBridgeManaged: "El nombre del bridge ya está administrado por libvirt o Docker" +ErrVMNetworkInUse: "La red está en uso y no se puede eliminar" +ErrVMStorageInUse: "El pool de almacenamiento está en uso y no se puede eliminar" +ErrVMStorageNameCannotChange: "El nombre del pool de almacenamiento no se puede cambiar" +ErrVMStoragePathCannotChange: "La ruta del pool de almacenamiento no se puede cambiar" ErrVMRunning: "La máquina virtual está en ejecución" ErrVMLibvirtConnect: "Error al conectar con libvirt: {{ .detail }}" ErrVMPermission: "Sin permiso para operar la máquina virtual: {{ .detail }}" @@ -190,7 +213,7 @@ TaskSync: 'Sincronizar' TaskSyncForNode: "Sincronizar Datos del Nodo" TaskBackup: "Respaldar" TaskPush: "Enviar" -TaskRsync: "Sync" +TaskRsync: "Sincronizar" SuccessStatus: "{{ .name }} correcta" FailedStatus: "{{ .name }} fallida {{ .err }}" Start: "Iniciar" @@ -255,7 +278,7 @@ PushAppInstallTaskToNode: "Enviar tarea de instalación de aplicación al nodo [ AppInstallTask: "Tarea de instalación de aplicación" PushAppFailed: "Error al enviar tarea de instalación de aplicación" SkillHubInstallTask: "Instalar skill [{{ .name }}]" -SkillHubInstallToTarget: "Instalar skill en destino [{{ .name }}]" +SkillHubInstallToTarget: "Instalar skill [{{ .name }}] en el destino [{{ .target }}]" # biblioteca de scripts ScriptLibrary: "Biblioteca de scripts" @@ -266,9 +289,9 @@ DownloadPackage: "Descargando paquete de la biblioteca de scripts" AnalyticCompletion: "Análisis completado, sincronizando con la base de datos..." # sincronización de nodos -SyncNode: "Sincronizar datos del nodo" +SyncNode: "Sincronizar datos con el nodo {{ .name }}" LocalName: "El nombre 'local' solo se utiliza para la identificación local del sistema" -SyncPackageData: "Sincronizar datos del paquete [{{ .detail }}]" +SyncPackageData: "Empaquetar los datos de sincronización" SyncPackageEncrypt: "Encriptación del paquete de datos" SyncRequest: "Solicitar API de sincronización de nodos" SyncFailedRetry: "Tiempo de espera en la sincronización de datos del nodo (intento {{ .index }}), reintentando..." @@ -312,25 +335,25 @@ StartService: "Iniciar servicio" NoBackupNode: "Actualmente no hay nodo de respaldo. Seleccione uno para guardar e intente de nuevo." # sincronización de archivos e imágenes de nodo -LocalNodeIpFailed: "Failed to get master node IP. Edit the master node and add IP address and SSH authentication information." -HandlePrivateKey: "Handle node private key" -HandlePublicKey: "Handle node public key" -ExchangeFile: "Start syncing {{ .sourcePath }} from node {{ .source }} to node {{ .dest }}:{{ .destPath }}" -NodeFile: "Node file" -ImageSyncTaskName: "Image sync {{ .count }} images" -SSLSyncTaskName: "Certificate sync {{ .count }} certificates" -AppSyncTaskName: "App sync {{ .name }}" -SSLSyncToNode: "Push certificate [{{ .cert }}] to node [{{ .node }}]" -ImageSyncSave: "Save image {{ .image }}" -ImageSyncSaveTags: "Save image tags {{ .tags }}" -ImageSyncToNode: "Sync image {{ .image }} to node {{ .node }}" -ImageSyncLoad: "Load image {{ .image }} on node {{ .node }}" -ImageSyncClean: "Clean temporary files for image {{ .image }}" -ImageSyncNoTag: "Image {{ .image }} has no tag and will be saved by image ID" -ImageSyncFrontendTagsIgnored: "No tags were found for image {{ .image }} on the source node. Frontend tags were ignored." -ImageSyncHandlePrivateKey: "Handle image sync node private key" -ImageSyncHandlePublicKey: "Handle image sync node public key" -ImageSyncTransfer: "Start transferring image temporary file: {{ .source }}:{{ .sourcePath }} -> {{ .dest }}:{{ .destPath }}" +LocalNodeIpFailed: "No se pudo obtener la IP del nodo principal. Edite el nodo principal y añada la dirección IP y la información de autenticación SSH." +HandlePrivateKey: "Procesar la clave privada del nodo" +HandlePublicKey: "Procesar la clave pública del nodo" +ExchangeFile: "Iniciar la sincronización de {{ .sourcePath }} desde el nodo {{ .source }} al nodo {{ .dest }}:{{ .destPath }}" +NodeFile: "Archivo del nodo" +ImageSyncTaskName: "Sincronizar {{ .count }} imágenes" +SSLSyncTaskName: "Sincronizar {{ .count }} certificados" +AppSyncTaskName: "Sincronizar la aplicación {{ .name }}" +SSLSyncToNode: "Enviar el certificado [{{ .cert }}] al nodo [{{ .node }}]" +ImageSyncSave: "Guardar la imagen {{ .image }}" +ImageSyncSaveTags: "Guardar las etiquetas de la imagen {{ .tags }}" +ImageSyncToNode: "Sincronizar la imagen {{ .image }} con el nodo {{ .node }}" +ImageSyncLoad: "Cargar la imagen {{ .image }} en el nodo {{ .node }}" +ImageSyncClean: "Limpiar los archivos temporales de la imagen {{ .image }}" +ImageSyncNoTag: "La imagen {{ .image }} no tiene etiqueta y se guardará mediante su ID" +ImageSyncFrontendTagsIgnored: "No se encontraron etiquetas para la imagen {{ .image }} en el nodo de origen. Se ignoraron las etiquetas del frontend." +ImageSyncHandlePrivateKey: "Procesar la clave privada del nodo de sincronización de imágenes" +ImageSyncHandlePublicKey: "Procesar la clave pública del nodo de sincronización de imágenes" +ImageSyncTransfer: "Iniciar la transferencia del archivo temporal de la imagen: {{ .source }}:{{ .sourcePath }} -> {{ .dest }}:{{ .destPath }}" # línea de comandos SudoHelper: "Por favor use {{ .cmd }} o cambie al usuario root" @@ -472,3 +495,33 @@ ErrLDAPSyncRunning: "Ya hay una tarea de sincronización LDAP en ejecución." ErrLDAPSyncDirectoryIncomplete: "LDAP devolvió un resultado incompleto de la consulta completa. No se modificó el estado de ningún usuario." ErrLDAPSyncFailed: "La sincronización de usuarios LDAP falló." LDAPSyncSuccess: "La sincronización de usuarios LDAP se completó correctamente." +ErrSAML2NotEnabled: "La autenticación SAML2 no está activada." +ErrSAML2ConfigInvalid: "La configuración de SAML2 no es válida." +ErrSAML2ConfigChanged: "La configuración de SAML2 ha cambiado. Inicie de nuevo la autenticación." +ErrSAML2PanelOriginMissing: "Introduzca una URL pública de 1Panel válida que solo contenga el esquema, el host y un puerto opcional." +ErrSAML2MetadataInvalid: "Faltan los metadatos del IdP o no son válidos." +ErrSAML2MetadataURLInvalid: "La URL de metadatos del IdP o uno de sus puntos de conexión no está permitido." +ErrSAML2MetadataFetch: "No se pudieron cargar los metadatos del IdP." +ErrSAML2MetadataCertificate: "Los metadatos del IdP no contienen un certificado de firma utilizable." +ErrSAML2KeyPairInvalid: "La clave privada y el certificado del SP no son válidos o no coinciden." +ErrSAML2NameAttributeMissing: "Falta el atributo de nombre de usuario SAML2 configurado o no es válido." +ErrSAML2DefaultRoleInvalid: "El rol predeterminado configurado para SAML2 no está disponible." +ErrSAML2SLOUnavailable: "El IdP no proporciona un servicio de cierre de sesión único compatible." +ErrSAML2TestExpired: "La prueba de SAML2 ha caducado. Ejecútela de nuevo." +ErrSAML2LoginExpired: "La solicitud de inicio de sesión SAML2 ha caducado. Inténtelo de nuevo." +ErrSAML2InvalidState: "El estado de inicio de sesión SAML2 no es válido o ya se utilizó." +ErrSAML2RequestBuild: "No se pudo crear la solicitud SAML2." +ErrSAML2ResponseInvalid: "La respuesta SAML2 no es válida." +ErrSAML2SignatureInvalid: "La firma SAML2 no es válida." +ErrSAML2Replay: "El mensaje SAML2 ya se utilizó." +ErrSAML2NameIDMissing: "Falta el NameID de SAML2 o no es válido." +ErrSAML2SessionIndexMissing: "Falta el SessionIndex de SAML2 o no es válido." +ErrSAML2NameConflictLocal: "El nombre de usuario SAML2 entra en conflicto con un usuario local." +ErrSAML2NameConflictLDAP: "El nombre de usuario SAML2 entra en conflicto con un usuario LDAP." +ErrSAML2NameConflictOIDC: "El nombre de usuario SAML2 entra en conflicto con un usuario OIDC." +ErrSAML2NameConflictSAML2: "El nombre de usuario SAML2 entra en conflicto con otra identidad SAML2." +ErrSAML2Internal: "Se produjo un error interno durante la autenticación SAML2. Inténtelo más tarde." +ErrSAML2LogoutExpired: "La solicitud de cierre de sesión SAML2 ha caducado." +ErrSAML2LogoutInvalid: "El mensaje de cierre de sesión SAML2 no es válido." +ErrSAML2LocalCredentialsReadonly: "Los nombres de usuario y las contraseñas SAML2 los gestiona el proveedor de identidad y no pueden modificarse localmente." +ErrSAML2PasswordExpirationUnsupported: "Los usuarios SAML2 no utilizan la política local de caducidad de contraseñas." diff --git a/core/i18n/lang/fa.yaml b/core/i18n/lang/fa.yaml index ca31004ce..988d63a87 100644 --- a/core/i18n/lang/fa.yaml +++ b/core/i18n/lang/fa.yaml @@ -42,6 +42,29 @@ ErrPasskeyLimit: "محدودیت کلید عبور رسیده است (حداکث ErrPasskeySession: "جلسه کلید عبور منقضی یا نامعتبر است" ErrPasskeyDuplicate: "کلید عبور از قبل وجود دارد" ErrPasskeyVerify: "تأیید کلید عبور ناموفق بود" +ErrOIDCNotEnabled: "احراز هویت OIDC فعال نیست" +ErrOIDCConfigInvalid: "پیکربندی OIDC نامعتبر است" +ErrOIDCConfigChanged: "پیکربندی OIDC تغییر کرده است؛ احراز هویت را دوباره آغاز کنید" +ErrOIDCDiscoveryFailed: "کشف پیکربندی Provider OIDC ناموفق بود" +ErrOIDCIssuerMismatch: "Issuer OIDC با Issuer پیکربندی‌شده مطابقت ندارد" +ErrOIDCUnsupportedPKCE: "Provider OIDC از روش PKCE موردنیاز پشتیبانی نمی‌کند" +ErrOIDCUnsupportedSigningAlgorithm: "الگوریتم امضای OIDC پشتیبانی نمی‌شود" +ErrOIDCInvalidState: "وضعیت ورود OIDC نامعتبر است یا قبلاً استفاده شده است" +ErrOIDCLoginExpired: "درخواست ورود OIDC منقضی شده است؛ دوباره تلاش کنید" +ErrOIDCTokenExchange: "تبادل کد مجوز OIDC ناموفق بود" +ErrOIDCTokenValidation: "اعتبارسنجی Token OIDC ناموفق بود" +ErrOIDCUserInfoValidation: "اعتبارسنجی اطلاعات کاربر OIDC ناموفق بود" +ErrOIDCNameClaimMissing: "Claim نام کاربری OIDC پیکربندی‌شده وجود ندارد یا نامعتبر است" +ErrOIDCNameConflictLocal: "نام کاربری OIDC با یک کاربر محلی تداخل دارد" +ErrOIDCNameConflictLDAP: "نام کاربری OIDC با یک کاربر LDAP تداخل دارد" +ErrOIDCNameConflictOIDC: "نام کاربری OIDC با هویت OIDC دیگری تداخل دارد" +ErrOIDCDefaultRoleInvalid: "نقش پیش‌فرض پیکربندی‌شده برای OIDC در دسترس نیست" +ErrOIDCPrivateAddressDenied: "نشانی Endpoint OIDC طبق سیاست امنیت شبکه مجاز نیست" +ErrOIDCTLSValidation: "اعتبارسنجی گواهی TLS OIDC ناموفق بود" +ErrOIDCTestExpired: "آزمایش مرورگری OIDC منقضی شده است؛ آن را دوباره اجرا کنید" +ErrOIDCLocalCredentialsReadonly: "نام کاربری و رمز عبور OIDC توسط Provider هویت مدیریت می‌شوند و به‌صورت محلی قابل تغییر نیستند." +ErrOIDCPasswordExpirationUnsupported: "کاربران OIDC از سیاست انقضای رمز عبور محلی استفاده نمی‌کنند." +ErrOIDCInternal: "در احراز هویت OIDC خطای داخلی رخ داد. بعداً دوباره تلاش کنید." # کاربر و مجوزها ErrNoSuchUser: "اطلاعات کاربر یافت نشد، بررسی و دوباره تلاش کنید!" @@ -114,12 +137,12 @@ ErrVMNotFound: "ماشین مجازی وجود ندارد" ErrVMAlreadyExists: "ماشین مجازی از قبل وجود دارد" ErrVMImageAlreadyExists: "فایل ایمیج ماشین مجازی از قبل وجود دارد: {{ .detail }}" ErrVMStoragePathInUse: "مسیر استخر ذخیره‌سازی قبلاً توسط [{{ .name }}] استفاده شده است" -ErrVMHelperNotFound: "1panel-kvm not found" -ErrVMBridgeManaged: "Bridge name is already managed by libvirt or Docker" -ErrVMNetworkInUse: "Network is in use and cannot be deleted" -ErrVMStorageInUse: "Storage pool is in use and cannot be deleted" -ErrVMStorageNameCannotChange: "Storage pool name cannot be changed" -ErrVMStoragePathCannotChange: "Storage pool path cannot be changed" +ErrVMHelperNotFound: "1panel-kvm یافت نشد" +ErrVMBridgeManaged: "نام bridge از قبل توسط libvirt یا Docker مدیریت می‌شود" +ErrVMNetworkInUse: "شبکه در حال استفاده است و قابل حذف نیست" +ErrVMStorageInUse: "مخزن ذخیره‌سازی در حال استفاده است و قابل حذف نیست" +ErrVMStorageNameCannotChange: "نام مخزن ذخیره‌سازی قابل تغییر نیست" +ErrVMStoragePathCannotChange: "مسیر مخزن ذخیره‌سازی قابل تغییر نیست" ErrVMRunning: "ماشین مجازی در حال اجرا است" ErrVMLibvirtConnect: "اتصال به libvirt ناموفق بود: {{ .detail }}" ErrVMPermission: "مجوز عملیات ماشین مجازی وجود ندارد: {{ .detail }}" @@ -255,7 +278,7 @@ PushAppInstallTaskToNode: "ارسال وظیفه نصب برنامه به گره AppInstallTask: "وظیفه نصب برنامه" PushAppFailed: "ارسال وظیفه نصب برنامه ناموفق بود" SkillHubInstallTask: "نصب مهارت [{{ .name }}]" -SkillHubInstallToTarget: "نصب مهارت به هدف [{{ .name }}]" +SkillHubInstallToTarget: "نصب مهارت [{{ .name }}] روی هدف [{{ .target }}]" # کتابخانه اسکریپت ScriptLibrary: "کتابخانه اسکریپت" @@ -317,10 +340,10 @@ HandlePrivateKey: "مدیریت کلید خصوصی گره" HandlePublicKey: "مدیریت کلید عمومی گره" ExchangeFile: "شروع همگام‌سازی {{ .sourcePath }} از گره {{ .source }} به گره {{ .dest }}:{{ .destPath }}" NodeFile: "فایل گره" -ImageSyncTaskName: "Image sync {{ .count }} images" -SSLSyncTaskName: "Certificate sync {{ .count }} certificates" -AppSyncTaskName: "App sync {{ .name }}" -SSLSyncToNode: "Push certificate [{{ .cert }}] to node [{{ .node }}]" +ImageSyncTaskName: "همگام‌سازی {{ .count }} تصویر" +SSLSyncTaskName: "همگام‌سازی {{ .count }} گواهی" +AppSyncTaskName: "همگام‌سازی برنامه {{ .name }}" +SSLSyncToNode: "ارسال گواهی [{{ .cert }}] به گره [{{ .node }}]" ImageSyncSave: "ذخیره تصویر {{ .image }}" ImageSyncSaveTags: "ذخیره برچسب‌های تصویر {{ .tags }}" ImageSyncToNode: "همگام‌سازی تصویر {{ .image }} به گره {{ .node }}" @@ -472,3 +495,33 @@ ErrLDAPSyncRunning: "یک وظیفه همگام‌سازی LDAP در حال اج ErrLDAPSyncDirectoryIncomplete: "LDAP نتیجه ناقصی از پرس‌وجوی کامل برگرداند. وضعیت هیچ کاربری تغییر نکرد." ErrLDAPSyncFailed: "همگام‌سازی کاربران LDAP ناموفق بود." LDAPSyncSuccess: "همگام‌سازی کاربران LDAP با موفقیت انجام شد." +ErrSAML2NotEnabled: "احراز هویت SAML2 فعال نیست." +ErrSAML2ConfigInvalid: "پیکربندی SAML2 نامعتبر است." +ErrSAML2ConfigChanged: "پیکربندی SAML2 تغییر کرده است. احراز هویت را دوباره آغاز کنید." +ErrSAML2PanelOriginMissing: "یک URL عمومی معتبر برای 1Panel وارد کنید که فقط شامل طرح، میزبان و در صورت نیاز درگاه باشد." +ErrSAML2MetadataInvalid: "فراداده IdP وجود ندارد یا نامعتبر است." +ErrSAML2MetadataURLInvalid: "URL فراداده IdP یا یکی از نقاط پایانی موجود در فراداده مجاز نیست." +ErrSAML2MetadataFetch: "بارگیری فراداده IdP ناموفق بود." +ErrSAML2MetadataCertificate: "فراداده IdP شامل گواهی امضای قابل استفاده نیست." +ErrSAML2KeyPairInvalid: "کلید خصوصی و گواهی SP نامعتبر هستند یا با هم مطابقت ندارند." +ErrSAML2NameAttributeMissing: "ویژگی نام کاربری SAML2 پیکربندی‌شده وجود ندارد یا نامعتبر است." +ErrSAML2DefaultRoleInvalid: "نقش پیش‌فرض پیکربندی‌شده برای SAML2 در دسترس نیست." +ErrSAML2SLOUnavailable: "IdP سرویس خروج یکپارچه پشتیبانی‌شده‌ای ارائه نمی‌کند." +ErrSAML2TestExpired: "آزمایش SAML2 منقضی شده است. دوباره آن را اجرا کنید." +ErrSAML2LoginExpired: "درخواست ورود SAML2 منقضی شده است. دوباره تلاش کنید." +ErrSAML2InvalidState: "وضعیت ورود SAML2 نامعتبر است یا قبلاً استفاده شده است." +ErrSAML2RequestBuild: "ساخت درخواست SAML2 ناموفق بود." +ErrSAML2ResponseInvalid: "پاسخ SAML2 نامعتبر است." +ErrSAML2SignatureInvalid: "امضای SAML2 نامعتبر است." +ErrSAML2Replay: "پیام SAML2 قبلاً استفاده شده است." +ErrSAML2NameIDMissing: "NameID مربوط به SAML2 وجود ندارد یا نامعتبر است." +ErrSAML2SessionIndexMissing: "SessionIndex مربوط به SAML2 وجود ندارد یا نامعتبر است." +ErrSAML2NameConflictLocal: "نام کاربری SAML2 با یک کاربر محلی تداخل دارد." +ErrSAML2NameConflictLDAP: "نام کاربری SAML2 با یک کاربر LDAP تداخل دارد." +ErrSAML2NameConflictOIDC: "نام کاربری SAML2 با یک کاربر OIDC تداخل دارد." +ErrSAML2NameConflictSAML2: "نام کاربری SAML2 با هویت SAML2 دیگری تداخل دارد." +ErrSAML2Internal: "هنگام احراز هویت SAML2 خطای داخلی رخ داد. بعداً دوباره تلاش کنید." +ErrSAML2LogoutExpired: "درخواست خروج SAML2 منقضی شده است." +ErrSAML2LogoutInvalid: "پیام خروج SAML2 نامعتبر است." +ErrSAML2LocalCredentialsReadonly: "نام‌های کاربری و گذرواژه‌های SAML2 توسط ارائه‌دهنده هویت مدیریت می‌شوند و در محل قابل تغییر نیستند." +ErrSAML2PasswordExpirationUnsupported: "کاربران SAML2 از سیاست محلی انقضای گذرواژه استفاده نمی‌کنند." diff --git a/core/i18n/lang/ja.yaml b/core/i18n/lang/ja.yaml index 408b2a646..6f43228b8 100644 --- a/core/i18n/lang/ja.yaml +++ b/core/i18n/lang/ja.yaml @@ -6,7 +6,7 @@ ErrInternalServer: '内部エラー: {{ .detail }}' ErrInternalServerKey: "サーバー内部エラー: " ErrRecordExist: 'レコードが既に存在します' ErrRecordNotFound: 'レコードが見つかりません' -ErrStructTransform: '型変換エラー: {{ .err }}' +ErrStructTransform: '型変換エラー: {{ .detail }}' ErrNotSupportType: '未対応のタイプ: {{ .name }}' ErrDemoEnvironment: 'デモ環境では利用できません' ErrCmdTimeout: 'コマンドがタイムアウトしました' @@ -42,6 +42,29 @@ ErrPasskeyLimit: "Passkeyの上限に達しました(最大5個)" ErrPasskeySession: "Passkeyセッションの有効期限が切れているか無効です" ErrPasskeyDuplicate: "Passkeyは既に存在します" ErrPasskeyVerify: "Passkeyの検証に失敗しました" +ErrOIDCNotEnabled: "OIDC 認証が有効になっていません" +ErrOIDCConfigInvalid: "OIDC 設定が無効です" +ErrOIDCConfigChanged: "OIDC 設定が変更されました。認証をやり直してください" +ErrOIDCDiscoveryFailed: "OIDC Provider 設定の検出に失敗しました" +ErrOIDCIssuerMismatch: "OIDC の Issuer が設定済みの Issuer と一致しません" +ErrOIDCUnsupportedPKCE: "OIDC Provider は必要な PKCE 方式をサポートしていません" +ErrOIDCUnsupportedSigningAlgorithm: "OIDC の署名アルゴリズムはサポートされていません" +ErrOIDCInvalidState: "OIDC のログイン状態が無効であるか、すでに使用されています" +ErrOIDCLoginExpired: "OIDC ログイン要求の有効期限が切れました。もう一度お試しください" +ErrOIDCTokenExchange: "OIDC 認可コードの交換に失敗しました" +ErrOIDCTokenValidation: "OIDC Token の検証に失敗しました" +ErrOIDCUserInfoValidation: "OIDC ユーザー情報の検証に失敗しました" +ErrOIDCNameClaimMissing: "設定された OIDC ユーザー名 Claim が存在しないか無効です" +ErrOIDCNameConflictLocal: "OIDC ユーザー名がローカルユーザーと競合しています" +ErrOIDCNameConflictLDAP: "OIDC ユーザー名が LDAP ユーザーと競合しています" +ErrOIDCNameConflictOIDC: "OIDC ユーザー名が別の OIDC アイデンティティと競合しています" +ErrOIDCDefaultRoleInvalid: "OIDC に設定されたデフォルトロールは利用できません" +ErrOIDCPrivateAddressDenied: "OIDC Endpoint のアドレスはネットワークセキュリティポリシーで許可されていません" +ErrOIDCTLSValidation: "OIDC の TLS 証明書検証に失敗しました" +ErrOIDCTestExpired: "OIDC のブラウザーテストは期限切れです。もう一度実行してください" +ErrOIDCLocalCredentialsReadonly: "OIDC のユーザー名とパスワードは ID Provider によって管理されるため、ローカルでは変更できません。" +ErrOIDCPasswordExpirationUnsupported: "OIDC ユーザーにはローカルのパスワード有効期限ポリシーは適用されません。" +ErrOIDCInternal: "OIDC 認証で内部エラーが発生しました。しばらくしてからもう一度お試しください。" # ユーザーと権限 ErrNoSuchUser: "ユーザー情報が見つかりません。確認して再試行してください!" @@ -114,12 +137,12 @@ ErrVMNotFound: "仮想マシンが存在しません" ErrVMAlreadyExists: "仮想マシンは既に存在します" ErrVMImageAlreadyExists: "仮想マシンのイメージファイルは既に存在します: {{ .detail }}" ErrVMStoragePathInUse: "ストレージプールのパスは既に [{{ .name }}] で使用されています" -ErrVMHelperNotFound: "1panel-kvm not found" -ErrVMBridgeManaged: "Bridge name is already managed by libvirt or Docker" -ErrVMNetworkInUse: "Network is in use and cannot be deleted" -ErrVMStorageInUse: "Storage pool is in use and cannot be deleted" -ErrVMStorageNameCannotChange: "Storage pool name cannot be changed" -ErrVMStoragePathCannotChange: "Storage pool path cannot be changed" +ErrVMHelperNotFound: "1panel-kvm が見つかりません" +ErrVMBridgeManaged: "ブリッジ名はすでに libvirt または Docker によって管理されています" +ErrVMNetworkInUse: "ネットワークは使用中のため削除できません" +ErrVMStorageInUse: "ストレージプールは使用中のため削除できません" +ErrVMStorageNameCannotChange: "ストレージプール名は変更できません" +ErrVMStoragePathCannotChange: "ストレージプールのパスは変更できません" ErrVMRunning: "仮想マシンは実行中です" ErrVMLibvirtConnect: "libvirt への接続に失敗しました: {{ .detail }}" ErrVMPermission: "仮想マシンを操作する権限がありません: {{ .detail }}" @@ -190,7 +213,7 @@ TaskSync: '同期' TaskSyncForNode: "ノードデータを同期" TaskBackup: "バックアップ" TaskPush: "送信" -TaskRsync: "Sync" +TaskRsync: "同期" SuccessStatus: "{{ .name }} 成功" FailedStatus: "{{ .name }} 失敗 {{ .err }}" Start: "開始" @@ -255,7 +278,7 @@ PushAppInstallTaskToNode: "ノード [{{ .name }}] にアプリインストー AppInstallTask: "アプリインストールタスク" PushAppFailed: "アプリインストールタスクの送信に失敗しました" SkillHubInstallTask: "スキルをインストール [{{ .name }}]" -SkillHubInstallToTarget: "ターゲットにスキルをインストール [{{ .name }}]" +SkillHubInstallToTarget: "スキル [{{ .name }}] をターゲット [{{ .target }}] にインストール" # スクリプトライブラリ ScriptLibrary: "スクリプトライブラリ" @@ -312,25 +335,25 @@ StartService: "サービスを開始" NoBackupNode: "現在バックアップノードが空です。保存するバックアップノードを選択して再試行してください!" # ノードファイルとイメージ同期 -LocalNodeIpFailed: "Failed to get master node IP. Edit the master node and add IP address and SSH authentication information." -HandlePrivateKey: "Handle node private key" -HandlePublicKey: "Handle node public key" -ExchangeFile: "Start syncing {{ .sourcePath }} from node {{ .source }} to node {{ .dest }}:{{ .destPath }}" -NodeFile: "Node file" -ImageSyncTaskName: "Image sync {{ .count }} images" -SSLSyncTaskName: "Certificate sync {{ .count }} certificates" -AppSyncTaskName: "App sync {{ .name }}" -SSLSyncToNode: "Push certificate [{{ .cert }}] to node [{{ .node }}]" -ImageSyncSave: "Save image {{ .image }}" -ImageSyncSaveTags: "Save image tags {{ .tags }}" -ImageSyncToNode: "Sync image {{ .image }} to node {{ .node }}" -ImageSyncLoad: "Load image {{ .image }} on node {{ .node }}" -ImageSyncClean: "Clean temporary files for image {{ .image }}" -ImageSyncNoTag: "Image {{ .image }} has no tag and will be saved by image ID" -ImageSyncFrontendTagsIgnored: "No tags were found for image {{ .image }} on the source node. Frontend tags were ignored." -ImageSyncHandlePrivateKey: "Handle image sync node private key" -ImageSyncHandlePublicKey: "Handle image sync node public key" -ImageSyncTransfer: "Start transferring image temporary file: {{ .source }}:{{ .sourcePath }} -> {{ .dest }}:{{ .destPath }}" +LocalNodeIpFailed: "マスターノードの IP を取得できませんでした。マスターノードを編集し、IP アドレスと SSH 認証情報を追加してください。" +HandlePrivateKey: "ノードの秘密鍵を処理" +HandlePublicKey: "ノードの公開鍵を処理" +ExchangeFile: "ノード {{ .source }} の {{ .sourcePath }} からノード {{ .dest }}:{{ .destPath }} への同期を開始" +NodeFile: "ノードファイル" +ImageSyncTaskName: "{{ .count }} 個のイメージを同期" +SSLSyncTaskName: "{{ .count }} 件の証明書を同期" +AppSyncTaskName: "アプリケーション {{ .name }} を同期" +SSLSyncToNode: "証明書 [{{ .cert }}] をノード [{{ .node }}] に送信" +ImageSyncSave: "イメージ {{ .image }} を保存" +ImageSyncSaveTags: "イメージタグ {{ .tags }} を保存" +ImageSyncToNode: "イメージ {{ .image }} をノード {{ .node }} に同期" +ImageSyncLoad: "ノード {{ .node }} にイメージ {{ .image }} を読み込み" +ImageSyncClean: "イメージ {{ .image }} の一時ファイルを削除" +ImageSyncNoTag: "イメージ {{ .image }} にはタグがないため、イメージ ID で保存します" +ImageSyncFrontendTagsIgnored: "ソースノードのイメージ {{ .image }} にタグが見つからなかったため、フロントエンドからのタグを無視しました。" +ImageSyncHandlePrivateKey: "イメージ同期ノードの秘密鍵を処理" +ImageSyncHandlePublicKey: "イメージ同期ノードの公開鍵を処理" +ImageSyncTransfer: "イメージ一時ファイルの転送を開始: {{ .source }}:{{ .sourcePath }} -> {{ .dest }}:{{ .destPath }}" # コマンドライン SudoHelper: "{{.cmd}}を使用するか、ルートユーザーに切り替えてください" @@ -350,21 +373,21 @@ AppMissKey: "アプリキーがありません、-kを使用して指定しま AppMissVersion: "アプリバージョンがありません、-vを使用して指定します" AppVersionExist: "バージョンはすでに存在します!" AppCreateSuccessful: "創造は成功しました!" -AppWriteErr: "file {{ .name }} write failed {{ .err }}" +AppWriteErr: "ファイル {{ .name }} の書き込みに失敗しました {{ .err }}" # コマンドライン - 監視IP ListenIPCommands: "リスニングIPを切り替えます" ListenIPv4: "IPv4で聞いてください" ListenIPv6: "IPv6で聞く" -ListenChangeSuccessful: "切り替え成功!{{.Value}}で聞いています" +ListenChangeSuccessful: "切り替えに成功しました。現在 {{ .value }} で待ち受けています" # コマンドライン - リセット ResetCommands: "システム情報をリセットします" -ResetMFA: "1パネルの2要素認証をキャンセルします" +ResetMFA: "1Panel の二要素認証を解除" ResetHttps: "1Panel HTTPSログインをキャンセルします" -ResetEntrance: "1パネルの安全な入り口をキャンセルします" -ResetIPs: "1パネル認定IP制限をキャンセルします" -ResetDomain: "1パネルドメインバインディングをキャンセルします" +ResetEntrance: "1Panel のセキュリティエントランスを解除" +ResetIPs: "1Panel の許可 IP 制限を解除" +ResetDomain: "1Panel のドメインバインドを解除" ResetPasskey: "1Panel のパスキーをクリアします" # コマンドライン - ユーザー @@ -472,3 +495,33 @@ ErrLDAPSyncRunning: "LDAP 同期タスクはすでに実行中です。" ErrLDAPSyncDirectoryIncomplete: "LDAP の全件クエリ結果が不完全です。ユーザーの状態は変更されませんでした。" ErrLDAPSyncFailed: "LDAP ユーザーの同期に失敗しました。" LDAPSyncSuccess: "LDAP ユーザーの同期が正常に完了しました。" +ErrSAML2NotEnabled: "SAML2 認証が有効になっていません。" +ErrSAML2ConfigInvalid: "SAML2 設定が無効です。" +ErrSAML2ConfigChanged: "SAML2 設定が変更されました。認証をやり直してください。" +ErrSAML2PanelOriginMissing: "スキーム、ホスト、任意のポートのみを含む有効な 1Panel 公開 URL を入力してください。" +ErrSAML2MetadataInvalid: "IdP メタデータがないか、無効です。" +ErrSAML2MetadataURLInvalid: "IdP メタデータ URL またはメタデータ内のエンドポイントは許可されていません。" +ErrSAML2MetadataFetch: "IdP メタデータの読み込みに失敗しました。" +ErrSAML2MetadataCertificate: "IdP メタデータに使用可能な署名証明書がありません。" +ErrSAML2KeyPairInvalid: "SP 秘密鍵と証明書が無効か、一致していません。" +ErrSAML2NameAttributeMissing: "設定された SAML2 ユーザー名属性がないか、無効です。" +ErrSAML2DefaultRoleInvalid: "SAML2 に設定されたデフォルトロールを利用できません。" +ErrSAML2SLOUnavailable: "IdP はサポート対象のシングルログアウトサービスを提供していません。" +ErrSAML2TestExpired: "SAML2 テストの有効期限が切れました。もう一度実行してください。" +ErrSAML2LoginExpired: "SAML2 ログイン要求の有効期限が切れました。もう一度お試しください。" +ErrSAML2InvalidState: "SAML2 ログイン状態が無効か、すでに使用されています。" +ErrSAML2RequestBuild: "SAML2 要求の作成に失敗しました。" +ErrSAML2ResponseInvalid: "SAML2 応答が無効です。" +ErrSAML2SignatureInvalid: "SAML2 署名が無効です。" +ErrSAML2Replay: "SAML2 メッセージはすでに使用されています。" +ErrSAML2NameIDMissing: "SAML2 NameID がないか、無効です。" +ErrSAML2SessionIndexMissing: "SAML2 SessionIndex がないか、無効です。" +ErrSAML2NameConflictLocal: "SAML2 ユーザー名がローカルユーザーと競合しています。" +ErrSAML2NameConflictLDAP: "SAML2 ユーザー名が LDAP ユーザーと競合しています。" +ErrSAML2NameConflictOIDC: "SAML2 ユーザー名が OIDC ユーザーと競合しています。" +ErrSAML2NameConflictSAML2: "SAML2 ユーザー名が別の SAML2 ID と競合しています。" +ErrSAML2Internal: "SAML2 認証中に内部エラーが発生しました。後でもう一度お試しください。" +ErrSAML2LogoutExpired: "SAML2 ログアウト要求の有効期限が切れました。" +ErrSAML2LogoutInvalid: "SAML2 ログアウトメッセージが無効です。" +ErrSAML2LocalCredentialsReadonly: "SAML2 のユーザー名とパスワードは IdP によって管理されるため、ローカルでは変更できません。" +ErrSAML2PasswordExpirationUnsupported: "SAML2 ユーザーにはローカルのパスワード有効期限ポリシーが適用されません。" diff --git a/core/i18n/lang/ko.yaml b/core/i18n/lang/ko.yaml index 273cbe4e0..7f53564a7 100644 --- a/core/i18n/lang/ko.yaml +++ b/core/i18n/lang/ko.yaml @@ -6,7 +6,7 @@ ErrInternalServer: '서버 오류: {{ .detail }}' ErrInternalServerKey: "서버 내부 오류:" ErrRecordExist: '레코드가 이미 있습니다' ErrRecordNotFound: '레코드를 찾을 수 없습니다' -ErrStructTransform: '형 변환 실패: {{ .err }}' +ErrStructTransform: '형 변환 실패: {{ .detail }}' ErrNotSupportType: '지원하지 않는 타입: {{ .name }}' ErrDemoEnvironment: '데모 환경에서는 불가' ErrCmdTimeout: '명령이 시간 초과했습니다' @@ -42,6 +42,29 @@ ErrPasskeyLimit: "Passkey 개수가 한도에 도달했습니다(최대 5개)" ErrPasskeySession: "Passkey 세션이 만료되었거나 유효하지 않습니다" ErrPasskeyDuplicate: "Passkey가 이미 존재합니다" ErrPasskeyVerify: "Passkey 검증에 실패했습니다" +ErrOIDCNotEnabled: "OIDC 인증이 활성화되지 않았습니다" +ErrOIDCConfigInvalid: "OIDC 설정이 올바르지 않습니다" +ErrOIDCConfigChanged: "OIDC 설정이 변경되었습니다. 인증을 다시 시작하세요" +ErrOIDCDiscoveryFailed: "OIDC Provider 설정을 검색하지 못했습니다" +ErrOIDCIssuerMismatch: "OIDC Issuer가 설정된 Issuer와 일치하지 않습니다" +ErrOIDCUnsupportedPKCE: "OIDC Provider가 필요한 PKCE 방식을 지원하지 않습니다" +ErrOIDCUnsupportedSigningAlgorithm: "OIDC 서명 알고리즘이 지원되지 않습니다" +ErrOIDCInvalidState: "OIDC 로그인 상태가 올바르지 않거나 이미 사용되었습니다" +ErrOIDCLoginExpired: "OIDC 로그인 요청이 만료되었습니다. 다시 시도하세요" +ErrOIDCTokenExchange: "OIDC 인증 코드 교환에 실패했습니다" +ErrOIDCTokenValidation: "OIDC Token 검증에 실패했습니다" +ErrOIDCUserInfoValidation: "OIDC 사용자 정보 검증에 실패했습니다" +ErrOIDCNameClaimMissing: "설정된 OIDC 사용자 이름 Claim이 없거나 올바르지 않습니다" +ErrOIDCNameConflictLocal: "OIDC 사용자 이름이 로컬 사용자와 충돌합니다" +ErrOIDCNameConflictLDAP: "OIDC 사용자 이름이 LDAP 사용자와 충돌합니다" +ErrOIDCNameConflictOIDC: "OIDC 사용자 이름이 다른 OIDC ID와 충돌합니다" +ErrOIDCDefaultRoleInvalid: "OIDC에 설정된 기본 역할을 사용할 수 없습니다" +ErrOIDCPrivateAddressDenied: "OIDC Endpoint 주소가 네트워크 보안 정책에서 허용되지 않습니다" +ErrOIDCTLSValidation: "OIDC TLS 인증서 검증에 실패했습니다" +ErrOIDCTestExpired: "OIDC 브라우저 테스트가 만료되었습니다. 다시 실행하세요" +ErrOIDCLocalCredentialsReadonly: "OIDC 사용자 이름과 비밀번호는 ID Provider에서 관리하므로 로컬에서 변경할 수 없습니다." +ErrOIDCPasswordExpirationUnsupported: "OIDC 사용자는 로컬 비밀번호 만료 정책을 사용하지 않습니다." +ErrOIDCInternal: "OIDC 인증 중 내부 오류가 발생했습니다. 잠시 후 다시 시도하세요." # 사용자 및 권한 ErrNoSuchUser: "사용자 정보를 찾을 수 없습니다. 확인 후 다시 시도하세요" @@ -114,12 +137,12 @@ ErrVMNotFound: "가상 머신이 존재하지 않습니다" ErrVMAlreadyExists: "가상 머신이 이미 존재합니다" ErrVMImageAlreadyExists: "가상 머신 이미지 파일이 이미 존재합니다: {{ .detail }}" ErrVMStoragePathInUse: "스토리지 풀 경로가 이미 [{{ .name }}]에서 사용 중입니다" -ErrVMHelperNotFound: "1panel-kvm not found" -ErrVMBridgeManaged: "Bridge name is already managed by libvirt or Docker" -ErrVMNetworkInUse: "Network is in use and cannot be deleted" -ErrVMStorageInUse: "Storage pool is in use and cannot be deleted" -ErrVMStorageNameCannotChange: "Storage pool name cannot be changed" -ErrVMStoragePathCannotChange: "Storage pool path cannot be changed" +ErrVMHelperNotFound: "1panel-kvm을 찾을 수 없습니다" +ErrVMBridgeManaged: "브리지 이름이 이미 libvirt 또는 Docker에서 관리되고 있습니다" +ErrVMNetworkInUse: "네트워크가 사용 중이므로 삭제할 수 없습니다" +ErrVMStorageInUse: "스토리지 풀이 사용 중이므로 삭제할 수 없습니다" +ErrVMStorageNameCannotChange: "스토리지 풀 이름은 변경할 수 없습니다" +ErrVMStoragePathCannotChange: "스토리지 풀 경로는 변경할 수 없습니다" ErrVMRunning: "가상 머신이 실행 중입니다" ErrVMLibvirtConnect: "libvirt 연결 실패: {{ .detail }}" ErrVMPermission: "가상 머신 작업 권한이 없습니다: {{ .detail }}" @@ -190,7 +213,7 @@ TaskSync: '동기화' TaskSyncForNode: "노드 데이터 동기화" TaskBackup: "백업" TaskPush: "전송" -TaskRsync: "Sync" +TaskRsync: "동기화" SuccessStatus: "{{ .name }} 성공" FailedStatus: "{{ .name }} 실패 {{ .err }}" Start: "시작" @@ -255,7 +278,7 @@ PushAppInstallTaskToNode: "노드 [{{ .name }}]로 앱 설치 작업 전송" AppInstallTask: "앱 설치 작업" PushAppFailed: "앱 설치 작업 전송 실패" SkillHubInstallTask: "스킬 설치 [{{ .name }}]" -SkillHubInstallToTarget: "대상에 스킬 설치 [{{ .name }}]" +SkillHubInstallToTarget: "스킬 [{{ .name }}]을 대상 [{{ .target }}]에 설치" # 스크립트 라이브러리 ScriptLibrary: "스크립트 라이브러리" @@ -312,25 +335,25 @@ StartService: "서비스 시작" NoBackupNode: "현재 백업 노드가 비어 있습니다. 저장할 백업 노드를 선택한 후 다시 시도하십시오" # 노드 파일 및 이미지 동기화 -LocalNodeIpFailed: "Failed to get master node IP. Edit the master node and add IP address and SSH authentication information." -HandlePrivateKey: "Handle node private key" -HandlePublicKey: "Handle node public key" -ExchangeFile: "Start syncing {{ .sourcePath }} from node {{ .source }} to node {{ .dest }}:{{ .destPath }}" -NodeFile: "Node file" -ImageSyncTaskName: "Image sync {{ .count }} images" -SSLSyncTaskName: "Certificate sync {{ .count }} certificates" -AppSyncTaskName: "App sync {{ .name }}" -SSLSyncToNode: "Push certificate [{{ .cert }}] to node [{{ .node }}]" -ImageSyncSave: "Save image {{ .image }}" -ImageSyncSaveTags: "Save image tags {{ .tags }}" -ImageSyncToNode: "Sync image {{ .image }} to node {{ .node }}" -ImageSyncLoad: "Load image {{ .image }} on node {{ .node }}" -ImageSyncClean: "Clean temporary files for image {{ .image }}" -ImageSyncNoTag: "Image {{ .image }} has no tag and will be saved by image ID" -ImageSyncFrontendTagsIgnored: "No tags were found for image {{ .image }} on the source node. Frontend tags were ignored." -ImageSyncHandlePrivateKey: "Handle image sync node private key" -ImageSyncHandlePublicKey: "Handle image sync node public key" -ImageSyncTransfer: "Start transferring image temporary file: {{ .source }}:{{ .sourcePath }} -> {{ .dest }}:{{ .destPath }}" +LocalNodeIpFailed: "마스터 노드 IP를 가져오지 못했습니다. 마스터 노드를 편집하여 IP 주소와 SSH 인증 정보를 추가하세요." +HandlePrivateKey: "노드 개인 키 처리" +HandlePublicKey: "노드 공개 키 처리" +ExchangeFile: "노드 {{ .source }}의 {{ .sourcePath }}에서 노드 {{ .dest }}:{{ .destPath }}(으)로 동기화 시작" +NodeFile: "노드 파일" +ImageSyncTaskName: "이미지 {{ .count }}개 동기화" +SSLSyncTaskName: "인증서 {{ .count }}개 동기화" +AppSyncTaskName: "애플리케이션 {{ .name }} 동기화" +SSLSyncToNode: "인증서 [{{ .cert }}]을(를) 노드 [{{ .node }}]에 전송" +ImageSyncSave: "이미지 {{ .image }} 저장" +ImageSyncSaveTags: "이미지 태그 {{ .tags }} 저장" +ImageSyncToNode: "이미지 {{ .image }}을(를) 노드 {{ .node }}에 동기화" +ImageSyncLoad: "이미지 {{ .image }}을(를) 노드 {{ .node }}에 로드" +ImageSyncClean: "이미지 {{ .image }}의 임시 파일 정리" +ImageSyncNoTag: "이미지 {{ .image }}에 태그가 없어 이미지 ID로 저장합니다" +ImageSyncFrontendTagsIgnored: "소스 노드의 이미지 {{ .image }}에서 태그를 찾지 못해 프론트엔드 태그를 무시했습니다." +ImageSyncHandlePrivateKey: "이미지 동기화 노드 개인 키 처리" +ImageSyncHandlePublicKey: "이미지 동기화 노드 공개 키 처리" +ImageSyncTransfer: "이미지 임시 파일 전송 시작: {{ .source }}:{{ .sourcePath }} -> {{ .dest }}:{{ .destPath }}" # 명령줄 SudoHelper: "{{ .cmd }} 명령을 사용하거나 root 사용자로 전환하세요." @@ -472,3 +495,33 @@ ErrLDAPSyncRunning: "LDAP 동기화 작업이 이미 실행 중입니다." ErrLDAPSyncDirectoryIncomplete: "LDAP 전체 조회 결과가 불완전하여 사용자 상태를 변경하지 않았습니다." ErrLDAPSyncFailed: "LDAP 사용자 동기화에 실패했습니다." LDAPSyncSuccess: "LDAP 사용자 동기화가 완료되었습니다." +ErrSAML2NotEnabled: "SAML2 인증이 활성화되지 않았습니다." +ErrSAML2ConfigInvalid: "SAML2 구성이 올바르지 않습니다." +ErrSAML2ConfigChanged: "SAML2 구성이 변경되었습니다. 인증을 다시 시작하세요." +ErrSAML2PanelOriginMissing: "스킴, 호스트 및 선택적 포트만 포함하는 유효한 1Panel 공개 URL을 입력하세요." +ErrSAML2MetadataInvalid: "IdP 메타데이터가 없거나 올바르지 않습니다." +ErrSAML2MetadataURLInvalid: "IdP 메타데이터 URL 또는 메타데이터의 엔드포인트가 허용되지 않습니다." +ErrSAML2MetadataFetch: "IdP 메타데이터를 불러오지 못했습니다." +ErrSAML2MetadataCertificate: "IdP 메타데이터에 사용할 수 있는 서명 인증서가 없습니다." +ErrSAML2KeyPairInvalid: "SP 개인 키와 인증서가 올바르지 않거나 서로 일치하지 않습니다." +ErrSAML2NameAttributeMissing: "구성된 SAML2 사용자 이름 속성이 없거나 올바르지 않습니다." +ErrSAML2DefaultRoleInvalid: "SAML2에 구성된 기본 역할을 사용할 수 없습니다." +ErrSAML2SLOUnavailable: "IdP가 지원되는 Single Logout 서비스를 제공하지 않습니다." +ErrSAML2TestExpired: "SAML2 테스트가 만료되었습니다. 다시 실행하세요." +ErrSAML2LoginExpired: "SAML2 로그인 요청이 만료되었습니다. 다시 시도하세요." +ErrSAML2InvalidState: "SAML2 로그인 상태가 올바르지 않거나 이미 사용되었습니다." +ErrSAML2RequestBuild: "SAML2 요청을 생성하지 못했습니다." +ErrSAML2ResponseInvalid: "SAML2 응답이 올바르지 않습니다." +ErrSAML2SignatureInvalid: "SAML2 서명이 올바르지 않습니다." +ErrSAML2Replay: "SAML2 메시지가 이미 사용되었습니다." +ErrSAML2NameIDMissing: "SAML2 NameID가 없거나 올바르지 않습니다." +ErrSAML2SessionIndexMissing: "SAML2 SessionIndex가 없거나 올바르지 않습니다." +ErrSAML2NameConflictLocal: "SAML2 사용자 이름이 로컬 사용자와 충돌합니다." +ErrSAML2NameConflictLDAP: "SAML2 사용자 이름이 LDAP 사용자와 충돌합니다." +ErrSAML2NameConflictOIDC: "SAML2 사용자 이름이 OIDC 사용자와 충돌합니다." +ErrSAML2NameConflictSAML2: "SAML2 사용자 이름이 다른 SAML2 ID와 충돌합니다." +ErrSAML2Internal: "SAML2 인증 중 내부 오류가 발생했습니다. 나중에 다시 시도하세요." +ErrSAML2LogoutExpired: "SAML2 로그아웃 요청이 만료되었습니다." +ErrSAML2LogoutInvalid: "SAML2 로그아웃 메시지가 올바르지 않습니다." +ErrSAML2LocalCredentialsReadonly: "SAML2 사용자 이름과 비밀번호는 ID 공급자가 관리하므로 로컬에서 변경할 수 없습니다." +ErrSAML2PasswordExpirationUnsupported: "SAML2 사용자는 로컬 비밀번호 만료 정책을 사용하지 않습니다." diff --git a/core/i18n/lang/lo.yaml b/core/i18n/lang/lo.yaml index 7541817e7..4530e69c3 100644 --- a/core/i18n/lang/lo.yaml +++ b/core/i18n/lang/lo.yaml @@ -42,6 +42,29 @@ ErrPasskeyLimit: "ຈຳນວນ Passkey ຮອດຂີດຈຳກັດແ ErrPasskeySession: "ເຊດຊັນ Passkey ໝົດອາຍຸ ຫຼື ບໍ່ຖືກຕ້ອງ" ErrPasskeyDuplicate: "ມີ Passkey ນີ້ຢູ່ແລ້ວ" ErrPasskeyVerify: "ການຢືນຢັນ Passkey ລົ້ມເຫຼວ" +ErrOIDCNotEnabled: "ຍັງບໍ່ໄດ້ເປີດໃຊ້ການຢືນຢັນຕົວຕົນ OIDC" +ErrOIDCConfigInvalid: "ການຕັ້ງຄ່າ OIDC ບໍ່ຖືກຕ້ອງ" +ErrOIDCConfigChanged: "ການຕັ້ງຄ່າ OIDC ຖືກປ່ຽນແປງ; ກະລຸນາເລີ່ມການຢືນຢັນຕົວຕົນໃໝ່" +ErrOIDCDiscoveryFailed: "ຄົ້ນຫາການຕັ້ງຄ່າ Provider OIDC ບໍ່ສຳເລັດ" +ErrOIDCIssuerMismatch: "Issuer OIDC ບໍ່ກົງກັບ Issuer ທີ່ຕັ້ງຄ່າໄວ້" +ErrOIDCUnsupportedPKCE: "Provider OIDC ບໍ່ຮອງຮັບວິທີ PKCE ທີ່ຈຳເປັນ" +ErrOIDCUnsupportedSigningAlgorithm: "ບໍ່ຮອງຮັບອັນກໍຣິທຶມລາຍເຊັນ OIDC" +ErrOIDCInvalidState: "ສະຖານະການເຂົ້າລະບົບ OIDC ບໍ່ຖືກຕ້ອງຫຼືຖືກໃຊ້ແລ້ວ" +ErrOIDCLoginExpired: "ຄຳຂໍເຂົ້າລະບົບ OIDC ໝົດອາຍຸແລ້ວ; ກະລຸນາລອງໃໝ່" +ErrOIDCTokenExchange: "ແລກປ່ຽນລະຫັດອະນຸຍາດ OIDC ບໍ່ສຳເລັດ" +ErrOIDCTokenValidation: "ກວດສອບ Token OIDC ບໍ່ສຳເລັດ" +ErrOIDCUserInfoValidation: "ກວດສອບຂໍ້ມູນຜູ້ໃຊ້ OIDC ບໍ່ສຳເລັດ" +ErrOIDCNameClaimMissing: "Claim ຊື່ຜູ້ໃຊ້ OIDC ທີ່ຕັ້ງຄ່າໄວ້ບໍ່ມີຫຼືບໍ່ຖືກຕ້ອງ" +ErrOIDCNameConflictLocal: "ຊື່ຜູ້ໃຊ້ OIDC ຂັດແຍ່ງກັບຜູ້ໃຊ້ທ້ອງຖິ່ນ" +ErrOIDCNameConflictLDAP: "ຊື່ຜູ້ໃຊ້ OIDC ຂັດແຍ່ງກັບຜູ້ໃຊ້ LDAP" +ErrOIDCNameConflictOIDC: "ຊື່ຜູ້ໃຊ້ OIDC ຂັດແຍ່ງກັບຕົວຕົນ OIDC ອື່ນ" +ErrOIDCDefaultRoleInvalid: "ບົດບາດເລີ່ມຕົ້ນທີ່ຕັ້ງຄ່າສຳລັບ OIDC ບໍ່ສາມາດໃຊ້ງານໄດ້" +ErrOIDCPrivateAddressDenied: "ທີ່ຢູ່ Endpoint OIDC ບໍ່ໄດ້ຮັບອະນຸຍາດຈາກນະໂຍບາຍຄວາມປອດໄພເຄືອຂ່າຍ" +ErrOIDCTLSValidation: "ການກວດສອບໃບຢັ້ງຢືນ TLS ຂອງ OIDC ບໍ່ສຳເລັດ" +ErrOIDCTestExpired: "ການທົດສອບ OIDC ຜ່ານເບຣົາເຊີໝົດອາຍຸແລ້ວ; ກະລຸນາທົດສອບໃໝ່" +ErrOIDCLocalCredentialsReadonly: "ຊື່ຜູ້ໃຊ້ແລະລະຫັດຜ່ານ OIDC ຖືກຈັດການໂດຍ Provider ຕົວຕົນ ແລະບໍ່ສາມາດປ່ຽນໃນເຄື່ອງໄດ້." +ErrOIDCPasswordExpirationUnsupported: "ຜູ້ໃຊ້ OIDC ບໍ່ໃຊ້ນະໂຍບາຍອາຍຸລະຫັດຜ່ານທ້ອງຖິ່ນ." +ErrOIDCInternal: "ການຢືນຢັນຕົວຕົນ OIDC ເກີດຂໍ້ຜິດພາດພາຍໃນ; ກະລຸນາລອງໃໝ່ພາຍຫຼັງ." # user and permission ErrNoSuchUser: "ບໍ່ພົບຂໍ້ມູນຜູ້ໃຊ້, ກະລຸນາກວດສອບແລ້ວລອງໃໝ່!" @@ -121,11 +144,11 @@ ErrVMStorageInUse: "ພູນຈັດເກັບກຳລັງຖືກໃຊ ErrVMStorageNameCannotChange: "ບໍ່ສາມາດປ່ຽນຊື່ພູນຈັດເກັບໄດ້" ErrVMStoragePathCannotChange: "ບໍ່ສາມາດປ່ຽນເສັ້ນທາງພູນຈັດເກັບໄດ້" ErrVMRunning: "ເຄື່ອງສະເໝືອນກຳລັງເຮັດວຽກ" -ErrVMLibvirtConnect: "ເຊື່ອມຕໍ່ກັບ libvirt ບໍ່ສຳເລັດ" +ErrVMLibvirtConnect: "ເຊື່ອມຕໍ່ກັບ libvirt ບໍ່ສຳເລັດ: {{ .detail }}" ErrVMPermission: "ບໍ່ມີສິດດຳເນີນການກັບເຄື່ອງສະເໝືອນ: {{ .detail }}" -ErrVMNetworkNotFound: "ບໍ່ມີເຄືອຂ່າຍເຄື່ອງສະເໝືອນ" -ErrVMInvalidPath: "ເສັ້ນທາງເຄື່ອງສະເໝືອນບໍ່ຖືກຕ້ອງ" -ErrVMInvalidInput: "ພາລາມິເຕີເຄື່ອງສະເໝືອນບໍ່ຖືກຕ້ອງ" +ErrVMNetworkNotFound: "ບໍ່ມີເຄືອຂ່າຍເຄື່ອງສະເໝືອນ: {{ .detail }}" +ErrVMInvalidPath: "ເສັ້ນທາງເຄື່ອງສະເໝືອນບໍ່ຖືກຕ້ອງ: {{ .detail }}" +ErrVMInvalidInput: "ພາລາມິເຕີເຄື່ອງສະເໝືອນບໍ່ຖືກຕ້ອງ: {{ .detail }}" ErrVMCommandFailed: "ຄຳສັ່ງເຄື່ອງສະເໝືອນລົ້ມເຫຼວ: {{ .err }}" VMCreateTask: "ສ້າງເຄື່ອງສະເໝືອນ [{{ .name }}]" VMCreateFromTemplateTask: "ສ້າງເຄື່ອງສະເໝືອນ [{{ .name }}] ຈາກແມ່ແບບ" @@ -255,7 +278,7 @@ PushAppInstallTaskToNode: "ສົ່ງວຽກຕິດຕັ້ງແອັ AppInstallTask: "ວຽກຕິດຕັ້ງແອັບ" PushAppFailed: "ສົ່ງວຽກຕິດຕັ້ງແອັບບໍ່ສຳເລັດ" SkillHubInstallTask: "ຕິດຕັ້ງ Skill [{{ .name }}]" -SkillHubInstallToTarget: "ຕິດຕັ້ງ Skill ໄປຍັງເປົ້າໝາຍ [{{ .name }}]" +SkillHubInstallToTarget: "ຕິດຕັ້ງ Skill [{{ .name }}] ໄປຍັງເປົ້າໝາຍ [{{ .target }}]" # script library ScriptLibrary: "ຄັງສະຄຣິບ" @@ -472,3 +495,33 @@ ErrLDAPSyncRunning: "ມີວຽກຊິງຂໍ້ມູນ LDAP ກຳລ ErrLDAPSyncDirectoryIncomplete: "LDAP ສົ່ງຄືນຜົນການຄົ້ນຫາທັງໝົດທີ່ບໍ່ຄົບຖ້ວນ. ບໍ່ມີການປ່ຽນແປງສະຖານະຜູ້ໃຊ້." ErrLDAPSyncFailed: "ການຊິງຂໍ້ມູນຜູ້ໃຊ້ LDAP ບໍ່ສຳເລັດ." LDAPSyncSuccess: "ການຊິງຂໍ້ມູນຜູ້ໃຊ້ LDAP ສຳເລັດແລ້ວ." +ErrSAML2NotEnabled: "ການຢືນຢັນ SAML2 ຍັງບໍ່ໄດ້ເປີດໃຊ້." +ErrSAML2ConfigInvalid: "ການຕັ້ງຄ່າ SAML2 ບໍ່ຖືກຕ້ອງ." +ErrSAML2ConfigChanged: "ການຕັ້ງຄ່າ SAML2 ມີການປ່ຽນແປງ. ເລີ່ມການຢືນຢັນໃໝ່." +ErrSAML2PanelOriginMissing: "ໃສ່ URL ສາທາລະນະຂອງ 1Panel ທີ່ຖືກຕ້ອງ ໂດຍມີສະເພາະ scheme, host ແລະ port ທາງເລືອກ." +ErrSAML2MetadataInvalid: "ຂໍ້ມູນເມຕາຂອງ IdP ຂາດຫາຍ ຫຼືບໍ່ຖືກຕ້ອງ." +ErrSAML2MetadataURLInvalid: "Metadata URL ຂອງ IdP ຫຼື endpoint ໃນ Metadata ບໍ່ໄດ້ຮັບອະນຸຍາດ." +ErrSAML2MetadataFetch: "ບໍ່ສາມາດໂຫຼດຂໍ້ມູນເມຕາຂອງ IdP ໄດ້." +ErrSAML2MetadataCertificate: "ຂໍ້ມູນເມຕາຂອງ IdP ບໍ່ມີໃບຢັ້ງຢືນລາຍເຊັນທີ່ໃຊ້ໄດ້." +ErrSAML2KeyPairInvalid: "ກະແຈສ່ວນຕົວ ແລະໃບຢັ້ງຢືນຂອງ SP ບໍ່ຖືກຕ້ອງ ຫຼືບໍ່ກົງກັນ." +ErrSAML2NameAttributeMissing: "Attribute ຊື່ຜູ້ໃຊ້ SAML2 ທີ່ຕັ້ງຄ່າໄວ້ຂາດຫາຍ ຫຼືບໍ່ຖືກຕ້ອງ." +ErrSAML2DefaultRoleInvalid: "ບົດບາດເລີ່ມຕົ້ນທີ່ຕັ້ງຄ່າສຳລັບ SAML2 ບໍ່ສາມາດໃຊ້ໄດ້." +ErrSAML2SLOUnavailable: "IdP ບໍ່ມີບໍລິການ Single Logout ທີ່ຮອງຮັບ." +ErrSAML2TestExpired: "ການທົດສອບ SAML2 ໝົດອາຍຸແລ້ວ. ດຳເນີນການໃໝ່." +ErrSAML2LoginExpired: "ຄຳຮ້ອງຂໍເຂົ້າລະບົບ SAML2 ໝົດອາຍຸແລ້ວ. ລອງໃໝ່." +ErrSAML2InvalidState: "ສະຖານະເຂົ້າລະບົບ SAML2 ບໍ່ຖືກຕ້ອງ ຫຼືຖືກໃຊ້ແລ້ວ." +ErrSAML2RequestBuild: "ບໍ່ສາມາດສ້າງຄຳຮ້ອງຂໍ SAML2 ໄດ້." +ErrSAML2ResponseInvalid: "ການຕອບກັບ SAML2 ບໍ່ຖືກຕ້ອງ." +ErrSAML2SignatureInvalid: "ລາຍເຊັນ SAML2 ບໍ່ຖືກຕ້ອງ." +ErrSAML2Replay: "ຂໍ້ຄວາມ SAML2 ນີ້ຖືກໃຊ້ແລ້ວ." +ErrSAML2NameIDMissing: "NameID ຂອງ SAML2 ຂາດຫາຍ ຫຼືບໍ່ຖືກຕ້ອງ." +ErrSAML2SessionIndexMissing: "SessionIndex ຂອງ SAML2 ຂາດຫາຍ ຫຼືບໍ່ຖືກຕ້ອງ." +ErrSAML2NameConflictLocal: "ຊື່ຜູ້ໃຊ້ SAML2 ຂັດກັບຜູ້ໃຊ້ທ້ອງຖິ່ນ." +ErrSAML2NameConflictLDAP: "ຊື່ຜູ້ໃຊ້ SAML2 ຂັດກັບຜູ້ໃຊ້ LDAP." +ErrSAML2NameConflictOIDC: "ຊື່ຜູ້ໃຊ້ SAML2 ຂັດກັບຜູ້ໃຊ້ OIDC." +ErrSAML2NameConflictSAML2: "ຊື່ຜູ້ໃຊ້ SAML2 ຂັດກັບຕົວຕົນ SAML2 ອື່ນ." +ErrSAML2Internal: "ເກີດຂໍ້ຜິດພາດພາຍໃນລະຫວ່າງການຢືນຢັນ SAML2. ລອງໃໝ່ພາຍຫຼັງ." +ErrSAML2LogoutExpired: "ຄຳຮ້ອງຂໍອອກລະບົບ SAML2 ໝົດອາຍຸແລ້ວ." +ErrSAML2LogoutInvalid: "ຂໍ້ຄວາມອອກລະບົບ SAML2 ບໍ່ຖືກຕ້ອງ." +ErrSAML2LocalCredentialsReadonly: "ຊື່ຜູ້ໃຊ້ ແລະລະຫັດຜ່ານ SAML2 ຖືກຈັດການໂດຍຜູ້ໃຫ້ບໍລິການຕົວຕົນ ແລະບໍ່ສາມາດປ່ຽນໃນເຄື່ອງໄດ້." +ErrSAML2PasswordExpirationUnsupported: "ຜູ້ໃຊ້ SAML2 ບໍ່ໄດ້ໃຊ້ນະໂຍບາຍການໝົດອາຍຸລະຫັດຜ່ານທ້ອງຖິ່ນ." diff --git a/core/i18n/lang/ms.yaml b/core/i18n/lang/ms.yaml index 63f87f14a..76cd51934 100644 --- a/core/i18n/lang/ms.yaml +++ b/core/i18n/lang/ms.yaml @@ -6,7 +6,7 @@ ErrInternalServer: 'Ralat pelayan: {{ .detail }}' ErrInternalServerKey: "Ralat dalaman pelayan:" ErrRecordExist: 'Rekod sudah wujud' ErrRecordNotFound: 'Rekod tidak ditemui' -ErrStructTransform: 'Ralat penukaran: {{ .err }}' +ErrStructTransform: 'Ralat penukaran: {{ .detail }}' ErrNotSupportType: 'Jenis tidak disokong: {{ .name }}' ErrDemoEnvironment: 'Tidak tersedia dalam demo' ErrCmdTimeout: 'Arahan tamat masa' @@ -42,6 +42,29 @@ ErrPasskeyLimit: "Had Passkey telah dicapai (maksimum 5)" ErrPasskeySession: "Sesi Passkey telah tamat tempoh atau tidak sah" ErrPasskeyDuplicate: "Passkey sudah wujud" ErrPasskeyVerify: "Pengesahan Passkey gagal" +ErrOIDCNotEnabled: "Pengesahan OIDC belum diaktifkan" +ErrOIDCConfigInvalid: "Konfigurasi OIDC tidak sah" +ErrOIDCConfigChanged: "Konfigurasi OIDC telah berubah; mulakan semula pengesahan" +ErrOIDCDiscoveryFailed: "Gagal menemui konfigurasi Provider OIDC" +ErrOIDCIssuerMismatch: "Issuer OIDC tidak sepadan dengan Issuer yang dikonfigurasi" +ErrOIDCUnsupportedPKCE: "Provider OIDC tidak menyokong kaedah PKCE yang diperlukan" +ErrOIDCUnsupportedSigningAlgorithm: "Algoritma tandatangan OIDC tidak disokong" +ErrOIDCInvalidState: "Status log masuk OIDC tidak sah atau telah digunakan" +ErrOIDCLoginExpired: "Permintaan log masuk OIDC telah tamat tempoh; cuba lagi" +ErrOIDCTokenExchange: "Gagal menukar kod kebenaran OIDC" +ErrOIDCTokenValidation: "Gagal mengesahkan Token OIDC" +ErrOIDCUserInfoValidation: "Gagal mengesahkan maklumat pengguna OIDC" +ErrOIDCNameClaimMissing: "Claim nama pengguna OIDC yang dikonfigurasi tiada atau tidak sah" +ErrOIDCNameConflictLocal: "Nama pengguna OIDC bercanggah dengan pengguna tempatan" +ErrOIDCNameConflictLDAP: "Nama pengguna OIDC bercanggah dengan pengguna LDAP" +ErrOIDCNameConflictOIDC: "Nama pengguna OIDC bercanggah dengan identiti OIDC lain" +ErrOIDCDefaultRoleInvalid: "Peranan lalai yang dikonfigurasi untuk OIDC tidak tersedia" +ErrOIDCPrivateAddressDenied: "Alamat Endpoint OIDC tidak dibenarkan oleh dasar keselamatan rangkaian" +ErrOIDCTLSValidation: "Pengesahan sijil TLS OIDC gagal" +ErrOIDCTestExpired: "Ujian pelayar OIDC telah tamat tempoh; jalankan semula ujian" +ErrOIDCLocalCredentialsReadonly: "Nama pengguna dan kata laluan OIDC diurus oleh Provider identiti dan tidak boleh diubah secara tempatan." +ErrOIDCPasswordExpirationUnsupported: "Pengguna OIDC tidak menggunakan dasar tamat tempoh kata laluan tempatan." +ErrOIDCInternal: "Pengesahan OIDC mengalami ralat dalaman. Cuba lagi kemudian." # pengguna dan kebenaran ErrNoSuchUser: "Maklumat pengguna tidak ditemui, sila semak dan cuba lagi" @@ -114,12 +137,12 @@ ErrVMNotFound: "Mesin maya tidak wujud" ErrVMAlreadyExists: "Mesin maya sudah wujud" ErrVMImageAlreadyExists: "Fail imej mesin maya sudah wujud: {{ .detail }}" ErrVMStoragePathInUse: "Laluan kolam storan sudah digunakan oleh [{{ .name }}]" -ErrVMHelperNotFound: "1panel-kvm not found" -ErrVMBridgeManaged: "Bridge name is already managed by libvirt or Docker" -ErrVMNetworkInUse: "Network is in use and cannot be deleted" -ErrVMStorageInUse: "Storage pool is in use and cannot be deleted" -ErrVMStorageNameCannotChange: "Storage pool name cannot be changed" -ErrVMStoragePathCannotChange: "Storage pool path cannot be changed" +ErrVMHelperNotFound: "1panel-kvm tidak ditemui" +ErrVMBridgeManaged: "Nama bridge telah diurus oleh libvirt atau Docker" +ErrVMNetworkInUse: "Rangkaian sedang digunakan dan tidak boleh dipadamkan" +ErrVMStorageInUse: "Kumpulan storan sedang digunakan dan tidak boleh dipadamkan" +ErrVMStorageNameCannotChange: "Nama kumpulan storan tidak boleh diubah" +ErrVMStoragePathCannotChange: "Laluan kumpulan storan tidak boleh diubah" ErrVMRunning: "Mesin maya sedang berjalan" ErrVMLibvirtConnect: "Gagal menyambung ke libvirt: {{ .detail }}" ErrVMPermission: "Tiada kebenaran untuk mengendalikan mesin maya: {{ .detail }}" @@ -190,7 +213,7 @@ TaskSync: 'Selaraskan' TaskSyncForNode: "Segerakan Data Nod" TaskBackup: "Sandaran" TaskPush: "Hantar" -TaskRsync: "Sync" +TaskRsync: "Selaraskan" SuccessStatus: "{{ .name }} berjaya" FailedStatus: "{{ .name }} gagal {{ .err }}" Start: "Mula" @@ -255,7 +278,7 @@ PushAppInstallTaskToNode: "Hantar tugas pemasangan aplikasi ke nod [{{ .name }}] AppInstallTask: "Tugas pemasangan aplikasi" PushAppFailed: "Gagal menghantar tugas pemasangan aplikasi" SkillHubInstallTask: "Pasang kemahiran [{{ .name }}]" -SkillHubInstallToTarget: "Pasang kemahiran ke sasaran [{{ .name }}]" +SkillHubInstallToTarget: "Pasang kemahiran [{{ .name }}] ke sasaran [{{ .target }}]" # pustaka skrip ScriptLibrary: "Pustaka Skrip" @@ -312,25 +335,25 @@ StartService: "Mulakan perkhidmatan" NoBackupNode: "Nod sandaran kosong. Sila pilih nod sandaran untuk disimpan dan cuba lagi" # penyegerakan fail dan imej nod -LocalNodeIpFailed: "Failed to get master node IP. Edit the master node and add IP address and SSH authentication information." -HandlePrivateKey: "Handle node private key" -HandlePublicKey: "Handle node public key" -ExchangeFile: "Start syncing {{ .sourcePath }} from node {{ .source }} to node {{ .dest }}:{{ .destPath }}" -NodeFile: "Node file" -ImageSyncTaskName: "Image sync {{ .count }} images" -SSLSyncTaskName: "Certificate sync {{ .count }} certificates" -AppSyncTaskName: "App sync {{ .name }}" -SSLSyncToNode: "Push certificate [{{ .cert }}] to node [{{ .node }}]" -ImageSyncSave: "Save image {{ .image }}" -ImageSyncSaveTags: "Save image tags {{ .tags }}" -ImageSyncToNode: "Sync image {{ .image }} to node {{ .node }}" -ImageSyncLoad: "Load image {{ .image }} on node {{ .node }}" -ImageSyncClean: "Clean temporary files for image {{ .image }}" -ImageSyncNoTag: "Image {{ .image }} has no tag and will be saved by image ID" -ImageSyncFrontendTagsIgnored: "No tags were found for image {{ .image }} on the source node. Frontend tags were ignored." -ImageSyncHandlePrivateKey: "Handle image sync node private key" -ImageSyncHandlePublicKey: "Handle image sync node public key" -ImageSyncTransfer: "Start transferring image temporary file: {{ .source }}:{{ .sourcePath }} -> {{ .dest }}:{{ .destPath }}" +LocalNodeIpFailed: "Gagal mendapatkan IP nod induk. Edit nod induk dan tambahkan alamat IP serta maklumat pengesahan SSH." +HandlePrivateKey: "Kendalikan kunci peribadi nod" +HandlePublicKey: "Kendalikan kunci awam nod" +ExchangeFile: "Mulakan penyegerakan {{ .sourcePath }} dari nod {{ .source }} ke nod {{ .dest }}:{{ .destPath }}" +NodeFile: "Fail nod" +ImageSyncTaskName: "Segerakkan {{ .count }} imej" +SSLSyncTaskName: "Segerakkan {{ .count }} sijil" +AppSyncTaskName: "Segerakkan aplikasi {{ .name }}" +SSLSyncToNode: "Hantar sijil [{{ .cert }}] ke nod [{{ .node }}]" +ImageSyncSave: "Simpan imej {{ .image }}" +ImageSyncSaveTags: "Simpan tag imej {{ .tags }}" +ImageSyncToNode: "Segerakkan imej {{ .image }} ke nod {{ .node }}" +ImageSyncLoad: "Muatkan imej {{ .image }} pada nod {{ .node }}" +ImageSyncClean: "Bersihkan fail sementara imej {{ .image }}" +ImageSyncNoTag: "Imej {{ .image }} tidak mempunyai tag dan akan disimpan menggunakan ID imej" +ImageSyncFrontendTagsIgnored: "Tiada tag ditemui untuk imej {{ .image }} pada nod sumber. Tag frontend telah diabaikan." +ImageSyncHandlePrivateKey: "Kendalikan kunci peribadi nod penyegerakan imej" +ImageSyncHandlePublicKey: "Kendalikan kunci awam nod penyegerakan imej" +ImageSyncTransfer: "Mulakan pemindahan fail sementara imej: {{ .source }}:{{ .sourcePath }} -> {{ .dest }}:{{ .destPath }}" # baris perintah SudoHelper: "Sila gunakan {{ .cmd }} atau tukar ke pengguna root" @@ -472,3 +495,33 @@ ErrLDAPSyncRunning: "Tugas penyegerakan LDAP sedang berjalan." ErrLDAPSyncDirectoryIncomplete: "LDAP mengembalikan hasil pertanyaan penuh yang tidak lengkap. Tiada status pengguna diubah." ErrLDAPSyncFailed: "Penyegerakan pengguna LDAP gagal." LDAPSyncSuccess: "Penyegerakan pengguna LDAP berjaya diselesaikan." +ErrSAML2NotEnabled: "Pengesahan SAML2 tidak didayakan." +ErrSAML2ConfigInvalid: "Konfigurasi SAML2 tidak sah." +ErrSAML2ConfigChanged: "Konfigurasi SAML2 telah berubah. Mulakan pengesahan sekali lagi." +ErrSAML2PanelOriginMissing: "Masukkan URL awam 1Panel yang sah dan hanya mengandungi skema, hos serta port pilihan." +ErrSAML2MetadataInvalid: "Metadata IdP tiada atau tidak sah." +ErrSAML2MetadataURLInvalid: "URL metadata IdP atau titik akhir dalam metadata tidak dibenarkan." +ErrSAML2MetadataFetch: "Gagal memuatkan metadata IdP." +ErrSAML2MetadataCertificate: "Metadata IdP tidak mengandungi sijil tandatangan yang boleh digunakan." +ErrSAML2KeyPairInvalid: "Kunci peribadi dan sijil SP tidak sah atau tidak sepadan." +ErrSAML2NameAttributeMissing: "Atribut nama pengguna SAML2 yang dikonfigurasikan tiada atau tidak sah." +ErrSAML2DefaultRoleInvalid: "Peranan lalai yang dikonfigurasikan untuk SAML2 tidak tersedia." +ErrSAML2SLOUnavailable: "IdP tidak menyediakan perkhidmatan Single Logout yang disokong." +ErrSAML2TestExpired: "Ujian SAML2 telah tamat tempoh. Jalankan sekali lagi." +ErrSAML2LoginExpired: "Permintaan log masuk SAML2 telah tamat tempoh. Cuba lagi." +ErrSAML2InvalidState: "Keadaan log masuk SAML2 tidak sah atau telah digunakan." +ErrSAML2RequestBuild: "Gagal membina permintaan SAML2." +ErrSAML2ResponseInvalid: "Respons SAML2 tidak sah." +ErrSAML2SignatureInvalid: "Tandatangan SAML2 tidak sah." +ErrSAML2Replay: "Mesej SAML2 telah digunakan." +ErrSAML2NameIDMissing: "NameID SAML2 tiada atau tidak sah." +ErrSAML2SessionIndexMissing: "SessionIndex SAML2 tiada atau tidak sah." +ErrSAML2NameConflictLocal: "Nama pengguna SAML2 bercanggah dengan pengguna setempat." +ErrSAML2NameConflictLDAP: "Nama pengguna SAML2 bercanggah dengan pengguna LDAP." +ErrSAML2NameConflictOIDC: "Nama pengguna SAML2 bercanggah dengan pengguna OIDC." +ErrSAML2NameConflictSAML2: "Nama pengguna SAML2 bercanggah dengan identiti SAML2 lain." +ErrSAML2Internal: "Ralat dalaman berlaku semasa pengesahan SAML2. Cuba lagi kemudian." +ErrSAML2LogoutExpired: "Permintaan log keluar SAML2 telah tamat tempoh." +ErrSAML2LogoutInvalid: "Mesej log keluar SAML2 tidak sah." +ErrSAML2LocalCredentialsReadonly: "Nama pengguna dan kata laluan SAML2 diurus oleh penyedia identiti dan tidak boleh diubah secara setempat." +ErrSAML2PasswordExpirationUnsupported: "Pengguna SAML2 tidak menggunakan dasar tamat tempoh kata laluan setempat." diff --git a/core/i18n/lang/pt-BR.yaml b/core/i18n/lang/pt-BR.yaml index b563a7828..60fea5fc8 100644 --- a/core/i18n/lang/pt-BR.yaml +++ b/core/i18n/lang/pt-BR.yaml @@ -6,7 +6,7 @@ ErrInternalServer: 'Erro interno: {{ .detail }}' ErrInternalServerKey: "Erro interno do servidor:" ErrRecordExist: 'Registro já existe' ErrRecordNotFound: 'Registro não encontrado' -ErrStructTransform: 'Erro de conversão: {{ .err }}' +ErrStructTransform: 'Erro de conversão: {{ .detail }}' ErrNotSupportType: 'Tipo não suportado: {{ .name }}' ErrDemoEnvironment: 'Indisponível em demo' ErrCmdTimeout: 'Comando expirou' @@ -42,6 +42,29 @@ ErrPasskeyLimit: "Limite de Passkeys atingido (máximo 5)" ErrPasskeySession: "Sessão do Passkey expirada ou inválida" ErrPasskeyDuplicate: "Passkey já existe" ErrPasskeyVerify: "Falha na verificação do Passkey" +ErrOIDCNotEnabled: "A autenticação OIDC não está habilitada" +ErrOIDCConfigInvalid: "A configuração OIDC é inválida" +ErrOIDCConfigChanged: "A configuração OIDC foi alterada; inicie a autenticação novamente" +ErrOIDCDiscoveryFailed: "Falha ao descobrir a configuração do Provider OIDC" +ErrOIDCIssuerMismatch: "O Issuer OIDC não corresponde ao Issuer configurado" +ErrOIDCUnsupportedPKCE: "O Provider OIDC não oferece suporte ao método PKCE necessário" +ErrOIDCUnsupportedSigningAlgorithm: "O algoritmo de assinatura OIDC não é suportado" +ErrOIDCInvalidState: "O estado de login OIDC é inválido ou já foi utilizado" +ErrOIDCLoginExpired: "A solicitação de login OIDC expirou; tente novamente" +ErrOIDCTokenExchange: "Falha ao trocar o código de autorização OIDC" +ErrOIDCTokenValidation: "Falha ao validar o Token OIDC" +ErrOIDCUserInfoValidation: "Falha ao validar as informações do usuário OIDC" +ErrOIDCNameClaimMissing: "O Claim de nome de usuário OIDC configurado está ausente ou é inválido" +ErrOIDCNameConflictLocal: "O nome de usuário OIDC entra em conflito com um usuário local" +ErrOIDCNameConflictLDAP: "O nome de usuário OIDC entra em conflito com um usuário LDAP" +ErrOIDCNameConflictOIDC: "O nome de usuário OIDC entra em conflito com outra identidade OIDC" +ErrOIDCDefaultRoleInvalid: "A função padrão configurada para OIDC não está disponível" +ErrOIDCPrivateAddressDenied: "O endereço do Endpoint OIDC não é permitido pela política de segurança de rede" +ErrOIDCTLSValidation: "Falha na validação do certificado TLS OIDC" +ErrOIDCTestExpired: "O teste OIDC no navegador expirou; execute-o novamente" +ErrOIDCLocalCredentialsReadonly: "Os nomes de usuário e as senhas OIDC são gerenciados pelo Provider de identidade e não podem ser alterados localmente." +ErrOIDCPasswordExpirationUnsupported: "Os usuários OIDC não utilizam a política local de expiração de senha." +ErrOIDCInternal: "Ocorreu um erro interno na autenticação OIDC. Tente novamente mais tarde." # usuário e permissão ErrNoSuchUser: "Informações do usuário não encontradas. Verifique e tente novamente." @@ -114,12 +137,12 @@ ErrVMNotFound: "Máquina virtual não existe" ErrVMAlreadyExists: "Máquina virtual já existe" ErrVMImageAlreadyExists: "A imagem da máquina virtual já existe: {{ .detail }}" ErrVMStoragePathInUse: "O caminho do pool de armazenamento já é usado por [{{ .name }}]" -ErrVMHelperNotFound: "1panel-kvm not found" -ErrVMBridgeManaged: "Bridge name is already managed by libvirt or Docker" -ErrVMNetworkInUse: "Network is in use and cannot be deleted" -ErrVMStorageInUse: "Storage pool is in use and cannot be deleted" -ErrVMStorageNameCannotChange: "Storage pool name cannot be changed" -ErrVMStoragePathCannotChange: "Storage pool path cannot be changed" +ErrVMHelperNotFound: "1panel-kvm não encontrado" +ErrVMBridgeManaged: "O nome da bridge já é gerenciado pelo libvirt ou Docker" +ErrVMNetworkInUse: "A rede está em uso e não pode ser excluída" +ErrVMStorageInUse: "O pool de armazenamento está em uso e não pode ser excluído" +ErrVMStorageNameCannotChange: "O nome do pool de armazenamento não pode ser alterado" +ErrVMStoragePathCannotChange: "O caminho do pool de armazenamento não pode ser alterado" ErrVMRunning: "Máquina virtual está em execução" ErrVMLibvirtConnect: "Falha ao conectar ao libvirt: {{ .detail }}" ErrVMPermission: "Sem permissão para operar a máquina virtual: {{ .detail }}" @@ -188,9 +211,9 @@ TaskInstall: "Instalar" TaskUpgrade: "Atualizar" TaskSync: 'Sincronizar' TaskSyncForNode: "Sincronizar Dados do Nó" -TaskBackup: "Backup" +TaskBackup: "Fazer cópia de segurança" TaskPush: "Enviar" -TaskRsync: "Sync" +TaskRsync: "Sincronizar" SuccessStatus: "{{ .name }} bem-sucedido" FailedStatus: "{{ .name }} falhou {{ .err }}" Start: "Iniciar" @@ -255,7 +278,7 @@ PushAppInstallTaskToNode: "Enviar tarefa de instalação de aplicativo para o n AppInstallTask: "Tarefa de instalação de aplicativo" PushAppFailed: "Falha ao enviar tarefa de instalação de aplicativo" SkillHubInstallTask: "Instalar skill [{{ .name }}]" -SkillHubInstallToTarget: "Instalar skill no destino [{{ .name }}]" +SkillHubInstallToTarget: "Instalar skill [{{ .name }}] no destino [{{ .target }}]" # biblioteca de scripts ScriptLibrary: "Biblioteca de Scripts" @@ -312,25 +335,25 @@ StartService: "Iniciando serviço" NoBackupNode: "O nó de backup está vazio atualmente. Selecione um nó de backup para salvar e tente novamente" # sincronização de arquivos e imagens do nó -LocalNodeIpFailed: "Failed to get master node IP. Edit the master node and add IP address and SSH authentication information." -HandlePrivateKey: "Handle node private key" -HandlePublicKey: "Handle node public key" -ExchangeFile: "Start syncing {{ .sourcePath }} from node {{ .source }} to node {{ .dest }}:{{ .destPath }}" -NodeFile: "Node file" -ImageSyncTaskName: "Image sync {{ .count }} images" -SSLSyncTaskName: "Certificate sync {{ .count }} certificates" -AppSyncTaskName: "App sync {{ .name }}" -SSLSyncToNode: "Push certificate [{{ .cert }}] to node [{{ .node }}]" -ImageSyncSave: "Save image {{ .image }}" -ImageSyncSaveTags: "Save image tags {{ .tags }}" -ImageSyncToNode: "Sync image {{ .image }} to node {{ .node }}" -ImageSyncLoad: "Load image {{ .image }} on node {{ .node }}" -ImageSyncClean: "Clean temporary files for image {{ .image }}" -ImageSyncNoTag: "Image {{ .image }} has no tag and will be saved by image ID" -ImageSyncFrontendTagsIgnored: "No tags were found for image {{ .image }} on the source node. Frontend tags were ignored." -ImageSyncHandlePrivateKey: "Handle image sync node private key" -ImageSyncHandlePublicKey: "Handle image sync node public key" -ImageSyncTransfer: "Start transferring image temporary file: {{ .source }}:{{ .sourcePath }} -> {{ .dest }}:{{ .destPath }}" +LocalNodeIpFailed: "Falha ao obter o IP do nó mestre. Edite o nó mestre e adicione o endereço IP e as informações de autenticação SSH." +HandlePrivateKey: "Processar a chave privada do nó" +HandlePublicKey: "Processar a chave pública do nó" +ExchangeFile: "Iniciar a sincronização de {{ .sourcePath }} do nó {{ .source }} para o nó {{ .dest }}:{{ .destPath }}" +NodeFile: "Arquivo do nó" +ImageSyncTaskName: "Sincronizar {{ .count }} imagens" +SSLSyncTaskName: "Sincronizar {{ .count }} certificados" +AppSyncTaskName: "Sincronizar o aplicativo {{ .name }}" +SSLSyncToNode: "Enviar o certificado [{{ .cert }}] para o nó [{{ .node }}]" +ImageSyncSave: "Salvar a imagem {{ .image }}" +ImageSyncSaveTags: "Salvar as tags da imagem {{ .tags }}" +ImageSyncToNode: "Sincronizar a imagem {{ .image }} com o nó {{ .node }}" +ImageSyncLoad: "Carregar a imagem {{ .image }} no nó {{ .node }}" +ImageSyncClean: "Limpar os arquivos temporários da imagem {{ .image }}" +ImageSyncNoTag: "A imagem {{ .image }} não tem tag e será salva pelo ID da imagem" +ImageSyncFrontendTagsIgnored: "Nenhuma tag foi encontrada para a imagem {{ .image }} no nó de origem. As tags do frontend foram ignoradas." +ImageSyncHandlePrivateKey: "Processar a chave privada do nó de sincronização de imagens" +ImageSyncHandlePublicKey: "Processar a chave pública do nó de sincronização de imagens" +ImageSyncTransfer: "Iniciar a transferência do arquivo temporário da imagem: {{ .source }}:{{ .sourcePath }} -> {{ .dest }}:{{ .destPath }}" # linha de comando SudoHelper: "Por favor, use {{ .cmd }} ou altere para o usuário root" @@ -472,3 +495,33 @@ ErrLDAPSyncRunning: "Uma tarefa de sincronização LDAP já está em execução. ErrLDAPSyncDirectoryIncomplete: "O LDAP retornou um resultado incompleto da consulta completa. Nenhum status de usuário foi alterado." ErrLDAPSyncFailed: "Falha na sincronização de usuários LDAP." LDAPSyncSuccess: "A sincronização de usuários LDAP foi concluída com sucesso." +ErrSAML2NotEnabled: "A autenticação SAML2 não está ativada." +ErrSAML2ConfigInvalid: "A configuração do SAML2 é inválida." +ErrSAML2ConfigChanged: "A configuração do SAML2 foi alterada. Inicie a autenticação novamente." +ErrSAML2PanelOriginMissing: "Insira uma URL pública válida do 1Panel contendo apenas o esquema, o host e uma porta opcional." +ErrSAML2MetadataInvalid: "Os metadados do IdP estão ausentes ou são inválidos." +ErrSAML2MetadataURLInvalid: "A URL de metadados do IdP ou um endpoint contido neles não é permitido." +ErrSAML2MetadataFetch: "Falha ao carregar os metadados do IdP." +ErrSAML2MetadataCertificate: "Os metadados do IdP não contêm um certificado de assinatura utilizável." +ErrSAML2KeyPairInvalid: "A chave privada e o certificado do SP são inválidos ou não correspondem." +ErrSAML2NameAttributeMissing: "O atributo de nome de usuário SAML2 configurado está ausente ou é inválido." +ErrSAML2DefaultRoleInvalid: "A função padrão configurada para o SAML2 não está disponível." +ErrSAML2SLOUnavailable: "O IdP não fornece um serviço de logout único compatível." +ErrSAML2TestExpired: "O teste do SAML2 expirou. Execute-o novamente." +ErrSAML2LoginExpired: "A solicitação de login do SAML2 expirou. Tente novamente." +ErrSAML2InvalidState: "O estado de login do SAML2 é inválido ou já foi utilizado." +ErrSAML2RequestBuild: "Falha ao criar a solicitação SAML2." +ErrSAML2ResponseInvalid: "A resposta SAML2 é inválida." +ErrSAML2SignatureInvalid: "A assinatura SAML2 é inválida." +ErrSAML2Replay: "A mensagem SAML2 já foi utilizada." +ErrSAML2NameIDMissing: "O NameID do SAML2 está ausente ou é inválido." +ErrSAML2SessionIndexMissing: "O SessionIndex do SAML2 está ausente ou é inválido." +ErrSAML2NameConflictLocal: "O nome de usuário SAML2 entra em conflito com um usuário local." +ErrSAML2NameConflictLDAP: "O nome de usuário SAML2 entra em conflito com um usuário LDAP." +ErrSAML2NameConflictOIDC: "O nome de usuário SAML2 entra em conflito com um usuário OIDC." +ErrSAML2NameConflictSAML2: "O nome de usuário SAML2 entra em conflito com outra identidade SAML2." +ErrSAML2Internal: "Ocorreu um erro interno durante a autenticação SAML2. Tente novamente mais tarde." +ErrSAML2LogoutExpired: "A solicitação de logout do SAML2 expirou." +ErrSAML2LogoutInvalid: "A mensagem de logout do SAML2 é inválida." +ErrSAML2LocalCredentialsReadonly: "Os nomes de usuário e as senhas SAML2 são gerenciados pelo provedor de identidade e não podem ser alterados localmente." +ErrSAML2PasswordExpirationUnsupported: "Os usuários SAML2 não usam a política local de expiração de senha." diff --git a/core/i18n/lang/ru.yaml b/core/i18n/lang/ru.yaml index fdd48a7df..8a8bb49ce 100644 --- a/core/i18n/lang/ru.yaml +++ b/core/i18n/lang/ru.yaml @@ -6,7 +6,7 @@ ErrInternalServer: 'Внутренняя ошибка: {{ .detail }}' ErrInternalServerKey: "Внутренняя ошибка сервера:" ErrRecordExist: 'Запись уже существует' ErrRecordNotFound: 'Запись не найдена' -ErrStructTransform: 'Ошибка преобразования: {{ .err }}' +ErrStructTransform: 'Ошибка преобразования: {{ .detail }}' ErrNotSupportType: 'Тип не поддерживается: {{ .name }}' ErrDemoEnvironment: 'Недоступно в демо' ErrCmdTimeout: 'Команда завершилась по тайм-ауту' @@ -42,6 +42,29 @@ ErrPasskeyLimit: "Достигнут лимит Passkey (максимум 5)" ErrPasskeySession: "Сеанс Passkey истек или недействителен" ErrPasskeyDuplicate: "Passkey уже существует" ErrPasskeyVerify: "Не удалось проверить Passkey" +ErrOIDCNotEnabled: "Аутентификация OIDC не включена" +ErrOIDCConfigInvalid: "Конфигурация OIDC недействительна" +ErrOIDCConfigChanged: "Конфигурация OIDC изменилась; запустите аутентификацию заново" +ErrOIDCDiscoveryFailed: "Не удалось обнаружить конфигурацию Provider OIDC" +ErrOIDCIssuerMismatch: "Issuer OIDC не совпадает с настроенным Issuer" +ErrOIDCUnsupportedPKCE: "Provider OIDC не поддерживает требуемый метод PKCE" +ErrOIDCUnsupportedSigningAlgorithm: "Алгоритм подписи OIDC не поддерживается" +ErrOIDCInvalidState: "Состояние входа OIDC недействительно или уже использовано" +ErrOIDCLoginExpired: "Срок действия запроса на вход OIDC истёк; повторите попытку" +ErrOIDCTokenExchange: "Не удалось обменять код авторизации OIDC" +ErrOIDCTokenValidation: "Не удалось проверить Token OIDC" +ErrOIDCUserInfoValidation: "Не удалось проверить сведения о пользователе OIDC" +ErrOIDCNameClaimMissing: "Настроенный Claim имени пользователя OIDC отсутствует или недействителен" +ErrOIDCNameConflictLocal: "Имя пользователя OIDC конфликтует с локальным пользователем" +ErrOIDCNameConflictLDAP: "Имя пользователя OIDC конфликтует с пользователем LDAP" +ErrOIDCNameConflictOIDC: "Имя пользователя OIDC конфликтует с другой идентичностью OIDC" +ErrOIDCDefaultRoleInvalid: "Роль по умолчанию, настроенная для OIDC, недоступна" +ErrOIDCPrivateAddressDenied: "Адрес Endpoint OIDC запрещён политикой сетевой безопасности" +ErrOIDCTLSValidation: "Не удалось проверить сертификат TLS OIDC" +ErrOIDCTestExpired: "Срок действия браузерного теста OIDC истёк; запустите тест снова" +ErrOIDCLocalCredentialsReadonly: "Имена пользователей и пароли OIDC управляются Provider идентификации и не могут быть изменены локально." +ErrOIDCPasswordExpirationUnsupported: "Для пользователей OIDC не применяется локальная политика истечения срока действия пароля." +ErrOIDCInternal: "Во время аутентификации OIDC произошла внутренняя ошибка. Повторите попытку позже." # пользователь и права ErrNoSuchUser: "Информация о пользователе не найдена. Проверьте и повторите попытку." @@ -114,12 +137,12 @@ ErrVMNotFound: "Виртуальная машина не существует" ErrVMAlreadyExists: "Виртуальная машина уже существует" ErrVMImageAlreadyExists: "Файл образа виртуальной машины уже существует: {{ .detail }}" ErrVMStoragePathInUse: "Путь пула хранения уже используется [{{ .name }}]" -ErrVMHelperNotFound: "1panel-kvm not found" -ErrVMBridgeManaged: "Bridge name is already managed by libvirt or Docker" -ErrVMNetworkInUse: "Network is in use and cannot be deleted" -ErrVMStorageInUse: "Storage pool is in use and cannot be deleted" -ErrVMStorageNameCannotChange: "Storage pool name cannot be changed" -ErrVMStoragePathCannotChange: "Storage pool path cannot be changed" +ErrVMHelperNotFound: "1panel-kvm не найден" +ErrVMBridgeManaged: "Имя моста уже управляется libvirt или Docker" +ErrVMNetworkInUse: "Сеть используется и не может быть удалена" +ErrVMStorageInUse: "Пул хранилища используется и не может быть удалён" +ErrVMStorageNameCannotChange: "Имя пула хранилища нельзя изменить" +ErrVMStoragePathCannotChange: "Путь к пулу хранилища нельзя изменить" ErrVMRunning: "Виртуальная машина запущена" ErrVMLibvirtConnect: "Не удалось подключиться к libvirt: {{ .detail }}" ErrVMPermission: "Нет разрешения на операцию с виртуальной машиной: {{ .detail }}" @@ -190,7 +213,7 @@ TaskSync: 'Синхронизация' TaskSyncForNode: "Синхронизировать Данные Узла" TaskBackup: "Резервная копия" TaskPush: "Отправить" -TaskRsync: "Sync" +TaskRsync: "Синхронизация" SuccessStatus: "{{ .name }} успешно" FailedStatus: "{{ .name }} не удалось {{ .err }}" Start: "Начать" @@ -255,7 +278,7 @@ PushAppInstallTaskToNode: "Отправить задачу установки п AppInstallTask: "Задача установки приложения" PushAppFailed: "Не удалось отправить задачу установки приложения" SkillHubInstallTask: "Установить навык [{{ .name }}]" -SkillHubInstallToTarget: "Установить навык в цель [{{ .name }}]" +SkillHubInstallToTarget: "Установить навык [{{ .name }}] в цель [{{ .target }}]" # библиотека скриптов ScriptLibrary: "Библиотека скриптов" @@ -312,25 +335,25 @@ StartService: "Запустить сервис" NoBackupNode: "Резервный узел в настоящее время пуст. Выберите резервный узел для сохранения и повторите попытку" # синхронизация файлов и образов узла -LocalNodeIpFailed: "Failed to get master node IP. Edit the master node and add IP address and SSH authentication information." -HandlePrivateKey: "Handle node private key" -HandlePublicKey: "Handle node public key" -ExchangeFile: "Start syncing {{ .sourcePath }} from node {{ .source }} to node {{ .dest }}:{{ .destPath }}" -NodeFile: "Node file" -ImageSyncTaskName: "Image sync {{ .count }} images" -SSLSyncTaskName: "Certificate sync {{ .count }} certificates" -AppSyncTaskName: "App sync {{ .name }}" -SSLSyncToNode: "Push certificate [{{ .cert }}] to node [{{ .node }}]" -ImageSyncSave: "Save image {{ .image }}" -ImageSyncSaveTags: "Save image tags {{ .tags }}" -ImageSyncToNode: "Sync image {{ .image }} to node {{ .node }}" -ImageSyncLoad: "Load image {{ .image }} on node {{ .node }}" -ImageSyncClean: "Clean temporary files for image {{ .image }}" -ImageSyncNoTag: "Image {{ .image }} has no tag and will be saved by image ID" -ImageSyncFrontendTagsIgnored: "No tags were found for image {{ .image }} on the source node. Frontend tags were ignored." -ImageSyncHandlePrivateKey: "Handle image sync node private key" -ImageSyncHandlePublicKey: "Handle image sync node public key" -ImageSyncTransfer: "Start transferring image temporary file: {{ .source }}:{{ .sourcePath }} -> {{ .dest }}:{{ .destPath }}" +LocalNodeIpFailed: "Не удалось получить IP главного узла. Измените главный узел и добавьте IP-адрес и данные аутентификации SSH." +HandlePrivateKey: "Обработать закрытый ключ узла" +HandlePublicKey: "Обработать открытый ключ узла" +ExchangeFile: "Начать синхронизацию {{ .sourcePath }} с узла {{ .source }} на узел {{ .dest }}:{{ .destPath }}" +NodeFile: "Файл узла" +ImageSyncTaskName: "Синхронизировать образы: {{ .count }}" +SSLSyncTaskName: "Синхронизировать сертификаты: {{ .count }}" +AppSyncTaskName: "Синхронизировать приложение {{ .name }}" +SSLSyncToNode: "Отправить сертификат [{{ .cert }}] на узел [{{ .node }}]" +ImageSyncSave: "Сохранить образ {{ .image }}" +ImageSyncSaveTags: "Сохранить теги образа {{ .tags }}" +ImageSyncToNode: "Синхронизировать образ {{ .image }} с узлом {{ .node }}" +ImageSyncLoad: "Загрузить образ {{ .image }} на узел {{ .node }}" +ImageSyncClean: "Очистить временные файлы образа {{ .image }}" +ImageSyncNoTag: "У образа {{ .image }} нет тега, поэтому он будет сохранён по ID образа" +ImageSyncFrontendTagsIgnored: "На исходном узле не найдены теги образа {{ .image }}. Теги из frontend проигнорированы." +ImageSyncHandlePrivateKey: "Обработать закрытый ключ узла синхронизации образов" +ImageSyncHandlePublicKey: "Обработать открытый ключ узла синхронизации образов" +ImageSyncTransfer: "Начать передачу временного файла образа: {{ .source }}:{{ .sourcePath }} -> {{ .dest }}:{{ .destPath }}" # командная строка SudoHelper: "Пожалуйста, используйте {{ .cmd }} или переключитесь на пользователя root" @@ -472,3 +495,33 @@ ErrLDAPSyncRunning: "Задача синхронизации LDAP уже вып ErrLDAPSyncDirectoryIncomplete: "LDAP вернул неполный результат полного запроса. Статусы пользователей не были изменены." ErrLDAPSyncFailed: "Не удалось синхронизировать пользователей LDAP." LDAPSyncSuccess: "Синхронизация пользователей LDAP успешно завершена." +ErrSAML2NotEnabled: "Аутентификация SAML2 не включена." +ErrSAML2ConfigInvalid: "Конфигурация SAML2 недействительна." +ErrSAML2ConfigChanged: "Конфигурация SAML2 изменилась. Запустите аутентификацию заново." +ErrSAML2PanelOriginMissing: "Введите корректный публичный URL 1Panel, содержащий только схему, хост и необязательный порт." +ErrSAML2MetadataInvalid: "Метаданные IdP отсутствуют или недействительны." +ErrSAML2MetadataURLInvalid: "URL метаданных IdP или одна из конечных точек в метаданных не разрешены." +ErrSAML2MetadataFetch: "Не удалось загрузить метаданные IdP." +ErrSAML2MetadataCertificate: "Метаданные IdP не содержат подходящего сертификата подписи." +ErrSAML2KeyPairInvalid: "Закрытый ключ и сертификат SP недействительны или не соответствуют друг другу." +ErrSAML2NameAttributeMissing: "Настроенный атрибут имени пользователя SAML2 отсутствует или недействителен." +ErrSAML2DefaultRoleInvalid: "Роль по умолчанию, настроенная для SAML2, недоступна." +ErrSAML2SLOUnavailable: "IdP не предоставляет поддерживаемую службу единого выхода." +ErrSAML2TestExpired: "Срок действия теста SAML2 истек. Запустите его снова." +ErrSAML2LoginExpired: "Срок действия запроса на вход SAML2 истек. Повторите попытку." +ErrSAML2InvalidState: "Состояние входа SAML2 недействительно или уже использовано." +ErrSAML2RequestBuild: "Не удалось сформировать запрос SAML2." +ErrSAML2ResponseInvalid: "Ответ SAML2 недействителен." +ErrSAML2SignatureInvalid: "Подпись SAML2 недействительна." +ErrSAML2Replay: "Сообщение SAML2 уже было использовано." +ErrSAML2NameIDMissing: "NameID SAML2 отсутствует или недействителен." +ErrSAML2SessionIndexMissing: "SessionIndex SAML2 отсутствует или недействителен." +ErrSAML2NameConflictLocal: "Имя пользователя SAML2 конфликтует с локальным пользователем." +ErrSAML2NameConflictLDAP: "Имя пользователя SAML2 конфликтует с пользователем LDAP." +ErrSAML2NameConflictOIDC: "Имя пользователя SAML2 конфликтует с пользователем OIDC." +ErrSAML2NameConflictSAML2: "Имя пользователя SAML2 конфликтует с другой учетной записью SAML2." +ErrSAML2Internal: "Во время аутентификации SAML2 произошла внутренняя ошибка. Повторите попытку позже." +ErrSAML2LogoutExpired: "Срок действия запроса на выход SAML2 истек." +ErrSAML2LogoutInvalid: "Сообщение выхода SAML2 недействительно." +ErrSAML2LocalCredentialsReadonly: "Имена пользователей и пароли SAML2 управляются поставщиком удостоверений и не могут быть изменены локально." +ErrSAML2PasswordExpirationUnsupported: "Для пользователей SAML2 не применяется локальная политика срока действия паролей." diff --git a/core/i18n/lang/tr.yaml b/core/i18n/lang/tr.yaml index 6e62c825b..49c763fbc 100644 --- a/core/i18n/lang/tr.yaml +++ b/core/i18n/lang/tr.yaml @@ -6,7 +6,7 @@ ErrInternalServer: 'Sunucu hatası: {{ .detail }}' ErrInternalServerKey: "İç sunucu hatası:" ErrRecordExist: 'Kayıt zaten var' ErrRecordNotFound: 'Kayıt bulunamadı' -ErrStructTransform: 'Dönüşüm hatası: {{ .err }}' +ErrStructTransform: 'Dönüşüm hatası: {{ .detail }}' ErrNotSupportType: 'Bu tür desteklenmiyor: {{ .name }}' ErrDemoEnvironment: 'Demo modunda yok' ErrCmdTimeout: 'Komut zaman aşımına uğradı' @@ -42,6 +42,29 @@ ErrPasskeyLimit: "Passkey sınırına ulaşıldı (en fazla 5)" ErrPasskeySession: "Passkey oturumu süresi dolmuş veya geçersiz" ErrPasskeyDuplicate: "Passkey zaten mevcut" ErrPasskeyVerify: "Passkey doğrulaması başarısız" +ErrOIDCNotEnabled: "OIDC kimlik doğrulaması etkin değil" +ErrOIDCConfigInvalid: "OIDC yapılandırması geçersiz" +ErrOIDCConfigChanged: "OIDC yapılandırması değişti; kimlik doğrulamayı yeniden başlatın" +ErrOIDCDiscoveryFailed: "OIDC Provider yapılandırması keşfedilemedi" +ErrOIDCIssuerMismatch: "OIDC Issuer, yapılandırılan Issuer ile eşleşmiyor" +ErrOIDCUnsupportedPKCE: "OIDC Provider gerekli PKCE yöntemini desteklemiyor" +ErrOIDCUnsupportedSigningAlgorithm: "OIDC imza algoritması desteklenmiyor" +ErrOIDCInvalidState: "OIDC oturum açma durumu geçersiz veya daha önce kullanılmış" +ErrOIDCLoginExpired: "OIDC oturum açma isteğinin süresi doldu; tekrar deneyin" +ErrOIDCTokenExchange: "OIDC yetkilendirme kodu değişimi başarısız oldu" +ErrOIDCTokenValidation: "OIDC Token doğrulaması başarısız oldu" +ErrOIDCUserInfoValidation: "OIDC kullanıcı bilgileri doğrulanamadı" +ErrOIDCNameClaimMissing: "Yapılandırılan OIDC kullanıcı adı Claim alanı eksik veya geçersiz" +ErrOIDCNameConflictLocal: "OIDC kullanıcı adı yerel bir kullanıcıyla çakışıyor" +ErrOIDCNameConflictLDAP: "OIDC kullanıcı adı bir LDAP kullanıcısıyla çakışıyor" +ErrOIDCNameConflictOIDC: "OIDC kullanıcı adı başka bir OIDC kimliğiyle çakışıyor" +ErrOIDCDefaultRoleInvalid: "OIDC için yapılandırılan varsayılan rol kullanılamıyor" +ErrOIDCPrivateAddressDenied: "OIDC Endpoint adresine ağ güvenliği ilkesi tarafından izin verilmiyor" +ErrOIDCTLSValidation: "OIDC TLS sertifikası doğrulanamadı" +ErrOIDCTestExpired: "OIDC tarayıcı testinin süresi doldu; testi yeniden çalıştırın" +ErrOIDCLocalCredentialsReadonly: "OIDC kullanıcı adları ve parolaları kimlik Provider tarafından yönetilir ve yerel olarak değiştirilemez." +ErrOIDCPasswordExpirationUnsupported: "OIDC kullanıcıları yerel parola sona erme ilkesini kullanmaz." +ErrOIDCInternal: "OIDC kimlik doğrulamasında dahili bir hata oluştu. Lütfen daha sonra tekrar deneyin." # kullanıcı ve izin ErrNoSuchUser: "Kullanıcı bilgisi bulunamadı, lütfen kontrol edip tekrar deneyin" @@ -114,12 +137,12 @@ ErrVMNotFound: "Sanal makine mevcut değil" ErrVMAlreadyExists: "Sanal makine zaten mevcut" ErrVMImageAlreadyExists: "Sanal makine imaj dosyası zaten mevcut: {{ .detail }}" ErrVMStoragePathInUse: "Depolama havuzu yolu zaten [{{ .name }}] tarafından kullanılıyor" -ErrVMHelperNotFound: "1panel-kvm not found" -ErrVMBridgeManaged: "Bridge name is already managed by libvirt or Docker" -ErrVMNetworkInUse: "Network is in use and cannot be deleted" -ErrVMStorageInUse: "Storage pool is in use and cannot be deleted" -ErrVMStorageNameCannotChange: "Storage pool name cannot be changed" -ErrVMStoragePathCannotChange: "Storage pool path cannot be changed" +ErrVMHelperNotFound: "1panel-kvm bulunamadı" +ErrVMBridgeManaged: "Bridge adı zaten libvirt veya Docker tarafından yönetiliyor" +ErrVMNetworkInUse: "Ağ kullanımda ve silinemez" +ErrVMStorageInUse: "Depolama havuzu kullanımda ve silinemez" +ErrVMStorageNameCannotChange: "Depolama havuzunun adı değiştirilemez" +ErrVMStoragePathCannotChange: "Depolama havuzunun yolu değiştirilemez" ErrVMRunning: "Sanal makine çalışıyor" ErrVMLibvirtConnect: "libvirt bağlantısı başarısız: {{ .detail }}" ErrVMPermission: "Sanal makine işlemi için izin yok: {{ .detail }}" @@ -190,7 +213,7 @@ TaskSync: 'Senkronize' TaskSyncForNode: "Düğüm Verilerini Senkronize Et" TaskBackup: "Yedekleme" TaskPush: "Gönder" -TaskRsync: "Sync" +TaskRsync: "Senkronize" SuccessStatus: "{{ .name }} başarılı" FailedStatus: "{{ .name }} başarısız {{ .err }}" Start: "Başla" @@ -255,7 +278,7 @@ PushAppInstallTaskToNode: "Uygulama kurulum görevini düğüme [{{ .name }}] g AppInstallTask: "Uygulama kurulum görevi" PushAppFailed: "Uygulama kurulum görevi gönderilemedi" SkillHubInstallTask: "Skill yükle [{{ .name }}]" -SkillHubInstallToTarget: "Skill hedefe yükle [{{ .name }}]" +SkillHubInstallToTarget: "[{{ .name }}] skillini [{{ .target }}] hedefine yükle" # betik kitaplığı ScriptLibrary: "Betik Kütüphanesi" @@ -312,25 +335,25 @@ StartService: "Servisi başlat" NoBackupNode: "Yedek düğüm şu anda boş. Lütfen kaydetmek için bir yedek düğüm seçin ve tekrar deneyin" # düğüm dosyası ve imaj senkronizasyonu -LocalNodeIpFailed: "Failed to get master node IP. Edit the master node and add IP address and SSH authentication information." -HandlePrivateKey: "Handle node private key" -HandlePublicKey: "Handle node public key" -ExchangeFile: "Start syncing {{ .sourcePath }} from node {{ .source }} to node {{ .dest }}:{{ .destPath }}" -NodeFile: "Node file" -ImageSyncTaskName: "Image sync {{ .count }} images" -SSLSyncTaskName: "Certificate sync {{ .count }} certificates" -AppSyncTaskName: "App sync {{ .name }}" -SSLSyncToNode: "Push certificate [{{ .cert }}] to node [{{ .node }}]" -ImageSyncSave: "Save image {{ .image }}" -ImageSyncSaveTags: "Save image tags {{ .tags }}" -ImageSyncToNode: "Sync image {{ .image }} to node {{ .node }}" -ImageSyncLoad: "Load image {{ .image }} on node {{ .node }}" -ImageSyncClean: "Clean temporary files for image {{ .image }}" -ImageSyncNoTag: "Image {{ .image }} has no tag and will be saved by image ID" -ImageSyncFrontendTagsIgnored: "No tags were found for image {{ .image }} on the source node. Frontend tags were ignored." -ImageSyncHandlePrivateKey: "Handle image sync node private key" -ImageSyncHandlePublicKey: "Handle image sync node public key" -ImageSyncTransfer: "Start transferring image temporary file: {{ .source }}:{{ .sourcePath }} -> {{ .dest }}:{{ .destPath }}" +LocalNodeIpFailed: "Ana düğüm IP adresi alınamadı. Ana düğümü düzenleyip IP adresini ve SSH kimlik doğrulama bilgilerini ekleyin." +HandlePrivateKey: "Düğüm özel anahtarını işle" +HandlePublicKey: "Düğüm genel anahtarını işle" +ExchangeFile: "{{ .source }} düğümündeki {{ .sourcePath }} yolundan {{ .dest }} düğümündeki {{ .destPath }} yoluna senkronizasyonu başlat" +NodeFile: "Düğüm dosyası" +ImageSyncTaskName: "{{ .count }} imajı senkronize et" +SSLSyncTaskName: "{{ .count }} sertifikayı senkronize et" +AppSyncTaskName: "{{ .name }} uygulamasını senkronize et" +SSLSyncToNode: "[{{ .cert }}] sertifikasını [{{ .node }}] düğümüne gönder" +ImageSyncSave: "{{ .image }} imajını kaydet" +ImageSyncSaveTags: "{{ .tags }} imaj etiketlerini kaydet" +ImageSyncToNode: "{{ .image }} imajını {{ .node }} düğümüne senkronize et" +ImageSyncLoad: "{{ .image }} imajını {{ .node }} düğümüne yükle" +ImageSyncClean: "{{ .image }} imajının geçici dosyalarını temizle" +ImageSyncNoTag: "{{ .image }} imajının etiketi yok; imaj ID'si ile kaydedilecek" +ImageSyncFrontendTagsIgnored: "Kaynak düğümde {{ .image }} imajı için etiket bulunamadı. Frontend etiketleri yok sayıldı." +ImageSyncHandlePrivateKey: "İmaj senkronizasyon düğümünün özel anahtarını işle" +ImageSyncHandlePublicKey: "İmaj senkronizasyon düğümünün genel anahtarını işle" +ImageSyncTransfer: "Geçici imaj dosyasını aktarmaya başla: {{ .source }}:{{ .sourcePath }} -> {{ .dest }}:{{ .destPath }}" # komut satırı SudoHelper: "Lütfen {{ .cmd }} kullanın veya root kullanıcısına geçin" @@ -472,3 +495,33 @@ ErrLDAPSyncRunning: "Bir LDAP senkronizasyon görevi zaten çalışıyor." ErrLDAPSyncDirectoryIncomplete: "LDAP eksik bir tam sorgu sonucu döndürdü. Hiçbir kullanıcının durumu değiştirilmedi." ErrLDAPSyncFailed: "LDAP kullanıcı senkronizasyonu başarısız oldu." LDAPSyncSuccess: "LDAP kullanıcı senkronizasyonu başarıyla tamamlandı." +ErrSAML2NotEnabled: "SAML2 kimlik doğrulaması etkin değil." +ErrSAML2ConfigInvalid: "SAML2 yapılandırması geçersiz." +ErrSAML2ConfigChanged: "SAML2 yapılandırması değişti. Kimlik doğrulamayı yeniden başlatın." +ErrSAML2PanelOriginMissing: "Yalnızca şema, ana bilgisayar ve isteğe bağlı bağlantı noktası içeren geçerli bir 1Panel genel URL’si girin." +ErrSAML2MetadataInvalid: "IdP meta verileri eksik veya geçersiz." +ErrSAML2MetadataURLInvalid: "IdP meta veri URL’sine veya meta verilerdeki bir uç noktaya izin verilmiyor." +ErrSAML2MetadataFetch: "IdP meta verileri yüklenemedi." +ErrSAML2MetadataCertificate: "IdP meta verileri kullanılabilir bir imzalama sertifikası içermiyor." +ErrSAML2KeyPairInvalid: "SP özel anahtarı ve sertifikası geçersiz veya birbiriyle eşleşmiyor." +ErrSAML2NameAttributeMissing: "Yapılandırılmış SAML2 kullanıcı adı özniteliği eksik veya geçersiz." +ErrSAML2DefaultRoleInvalid: "SAML2 için yapılandırılmış varsayılan rol kullanılamıyor." +ErrSAML2SLOUnavailable: "IdP desteklenen bir Single Logout hizmeti sağlamıyor." +ErrSAML2TestExpired: "SAML2 testinin süresi doldu. Yeniden çalıştırın." +ErrSAML2LoginExpired: "SAML2 oturum açma isteğinin süresi doldu. Yeniden deneyin." +ErrSAML2InvalidState: "SAML2 oturum açma durumu geçersiz veya daha önce kullanılmış." +ErrSAML2RequestBuild: "SAML2 isteği oluşturulamadı." +ErrSAML2ResponseInvalid: "SAML2 yanıtı geçersiz." +ErrSAML2SignatureInvalid: "SAML2 imzası geçersiz." +ErrSAML2Replay: "SAML2 mesajı daha önce kullanılmış." +ErrSAML2NameIDMissing: "SAML2 NameID eksik veya geçersiz." +ErrSAML2SessionIndexMissing: "SAML2 SessionIndex eksik veya geçersiz." +ErrSAML2NameConflictLocal: "SAML2 kullanıcı adı yerel bir kullanıcıyla çakışıyor." +ErrSAML2NameConflictLDAP: "SAML2 kullanıcı adı bir LDAP kullanıcısıyla çakışıyor." +ErrSAML2NameConflictOIDC: "SAML2 kullanıcı adı bir OIDC kullanıcısıyla çakışıyor." +ErrSAML2NameConflictSAML2: "SAML2 kullanıcı adı başka bir SAML2 kimliğiyle çakışıyor." +ErrSAML2Internal: "SAML2 kimlik doğrulaması sırasında dahili bir hata oluştu. Daha sonra yeniden deneyin." +ErrSAML2LogoutExpired: "SAML2 oturum kapatma isteğinin süresi doldu." +ErrSAML2LogoutInvalid: "SAML2 oturum kapatma mesajı geçersiz." +ErrSAML2LocalCredentialsReadonly: "SAML2 kullanıcı adları ve parolaları kimlik sağlayıcı tarafından yönetilir ve yerel olarak değiştirilemez." +ErrSAML2PasswordExpirationUnsupported: "SAML2 kullanıcıları yerel parola süresi dolma ilkesini kullanmaz." diff --git a/core/i18n/lang/zh-Hant.yaml b/core/i18n/lang/zh-Hant.yaml index dc8ca4b61..d600dcb71 100644 --- a/core/i18n/lang/zh-Hant.yaml +++ b/core/i18n/lang/zh-Hant.yaml @@ -42,6 +42,29 @@ ErrPasskeyLimit: "Passkey 數量已達上限(最多 5 個)" ErrPasskeySession: "Passkey 會話已過期或無效" ErrPasskeyDuplicate: "Passkey 已存在" ErrPasskeyVerify: "Passkey 驗證失敗" +ErrOIDCNotEnabled: "OIDC 驗證尚未啟用" +ErrOIDCConfigInvalid: "OIDC 設定無效" +ErrOIDCConfigChanged: "OIDC 設定已變更,請重新發起驗證" +ErrOIDCDiscoveryFailed: "OIDC Provider 設定探索失敗" +ErrOIDCIssuerMismatch: "OIDC Issuer 與設定的 Issuer 不一致" +ErrOIDCUnsupportedPKCE: "OIDC Provider 不支援要求的 PKCE 方式" +ErrOIDCUnsupportedSigningAlgorithm: "不支援此 OIDC 簽章演算法" +ErrOIDCInvalidState: "OIDC 登入狀態無效或已被使用" +ErrOIDCLoginExpired: "OIDC 登入請求已過期,請重試" +ErrOIDCTokenExchange: "OIDC 授權碼交換 Token 失敗" +ErrOIDCTokenValidation: "OIDC Token 驗證失敗" +ErrOIDCUserInfoValidation: "OIDC 使用者資訊驗證失敗" +ErrOIDCNameClaimMissing: "設定的 OIDC 使用者名稱 Claim 缺失或無效" +ErrOIDCNameConflictLocal: "OIDC 使用者名稱與本機使用者衝突" +ErrOIDCNameConflictLDAP: "OIDC 使用者名稱與 LDAP 使用者衝突" +ErrOIDCNameConflictOIDC: "OIDC 使用者名稱與其他 OIDC 身分衝突" +ErrOIDCDefaultRoleInvalid: "OIDC 設定的預設角色不可用" +ErrOIDCPrivateAddressDenied: "OIDC 端點位址不符合網路安全原則" +ErrOIDCTLSValidation: "OIDC TLS 憑證驗證失敗" +ErrOIDCTestExpired: "OIDC 瀏覽器測試已過期,請重新測試" +ErrOIDCLocalCredentialsReadonly: "OIDC 使用者名稱和密碼由身分提供者管理,無法在本機修改。" +ErrOIDCPasswordExpirationUnsupported: "OIDC 使用者不使用本機密碼到期原則。" +ErrOIDCInternal: "OIDC 認證發生內部錯誤,請稍後重試。" # 使用者與權限 ErrNoSuchUser: "未能找到該使用者資訊,請檢查後重試!" @@ -255,7 +278,7 @@ PushAppInstallTaskToNode: "傳送應用安裝任務到節點 [{{ .name }}]" AppInstallTask: "應用安裝任務" PushAppFailed: "傳送應用安裝任務失敗" SkillHubInstallTask: "安裝技能 [{{ .name }}]" -SkillHubInstallToTarget: "安裝技能到目標 [{{ .name }}]" +SkillHubInstallToTarget: "安裝技能 [{{ .name }}] 到目標 [{{ .target }}]" # 腳本庫 ScriptLibrary: "腳本庫" @@ -472,3 +495,33 @@ ErrLDAPSyncRunning: "已有 LDAP 同步工作正在執行。" ErrLDAPSyncDirectoryIncomplete: "LDAP 全量查詢結果不完整,本次未變更任何使用者狀態。" ErrLDAPSyncFailed: "LDAP 使用者同步失敗。" LDAPSyncSuccess: "LDAP 使用者同步成功。" +ErrSAML2NotEnabled: "SAML2 驗證尚未啟用" +ErrSAML2ConfigInvalid: "SAML2 設定無效" +ErrSAML2ConfigChanged: "SAML2 設定已變更,請重新發起驗證" +ErrSAML2PanelOriginMissing: "請輸入有效的面板對外存取位址,僅包含協定、主機和選用連接埠" +ErrSAML2MetadataInvalid: "IdP Metadata 缺失或無效" +ErrSAML2MetadataURLInvalid: "IdP Metadata URL 或 Metadata 中的端點位址不符合安全策略" +ErrSAML2MetadataFetch: "取得 IdP Metadata 失敗" +ErrSAML2MetadataCertificate: "IdP Metadata 中沒有可用的簽章憑證" +ErrSAML2KeyPairInvalid: "SP 私鑰和憑證無效或不相符" +ErrSAML2NameAttributeMissing: "設定的 SAML2 使用者名稱屬性缺失或無效" +ErrSAML2DefaultRoleInvalid: "SAML2 設定的預設角色不可用" +ErrSAML2SLOUnavailable: "IdP 未提供支援的單一登出服務" +ErrSAML2TestExpired: "SAML2 測試已過期,請重新測試" +ErrSAML2LoginExpired: "SAML2 登入要求已過期,請重試" +ErrSAML2InvalidState: "SAML2 登入狀態無效或已被使用" +ErrSAML2RequestBuild: "產生 SAML2 要求失敗" +ErrSAML2ResponseInvalid: "SAML2 回應無效" +ErrSAML2SignatureInvalid: "SAML2 簽章驗證失敗" +ErrSAML2Replay: "SAML2 訊息已被使用" +ErrSAML2NameIDMissing: "SAML2 NameID 缺失或無效" +ErrSAML2SessionIndexMissing: "SAML2 SessionIndex 缺失或無效" +ErrSAML2NameConflictLocal: "SAML2 使用者名稱與本機使用者衝突" +ErrSAML2NameConflictLDAP: "SAML2 使用者名稱與 LDAP 使用者衝突" +ErrSAML2NameConflictOIDC: "SAML2 使用者名稱與 OIDC 使用者衝突" +ErrSAML2NameConflictSAML2: "SAML2 使用者名稱與其他 SAML2 身分衝突" +ErrSAML2Internal: "SAML2 驗證發生內部錯誤,請稍後重試" +ErrSAML2LogoutExpired: "SAML2 登出要求已過期" +ErrSAML2LogoutInvalid: "SAML2 登出訊息無效" +ErrSAML2LocalCredentialsReadonly: "SAML2 使用者名稱和密碼由身分提供者管理,無法在本機修改。" +ErrSAML2PasswordExpirationUnsupported: "SAML2 使用者不使用本機密碼到期原則。" diff --git a/core/i18n/lang/zh.yaml b/core/i18n/lang/zh.yaml index 339c97364..1994ca39c 100644 --- a/core/i18n/lang/zh.yaml +++ b/core/i18n/lang/zh.yaml @@ -42,6 +42,29 @@ ErrPasskeyLimit: "Passkey 数量已达上限(最多 5 个)" ErrPasskeySession: "Passkey 会话已过期或无效" ErrPasskeyDuplicate: "Passkey 已存在" ErrPasskeyVerify: "Passkey 验证失败" +ErrOIDCNotEnabled: "OIDC 认证尚未启用" +ErrOIDCConfigInvalid: "OIDC 配置无效" +ErrOIDCConfigChanged: "OIDC 配置已变更,请重新发起认证" +ErrOIDCDiscoveryFailed: "OIDC Provider 配置发现失败" +ErrOIDCIssuerMismatch: "OIDC Issuer 与配置的 Issuer 不一致" +ErrOIDCUnsupportedPKCE: "OIDC Provider 不支持要求的 PKCE 方式" +ErrOIDCUnsupportedSigningAlgorithm: "不支持该 OIDC 签名算法" +ErrOIDCInvalidState: "OIDC 登录状态无效或已被使用" +ErrOIDCLoginExpired: "OIDC 登录请求已过期,请重试" +ErrOIDCTokenExchange: "OIDC 授权码换取 Token 失败" +ErrOIDCTokenValidation: "OIDC Token 校验失败" +ErrOIDCUserInfoValidation: "OIDC 用户信息校验失败" +ErrOIDCNameClaimMissing: "配置的 OIDC 用户名 Claim 缺失或无效" +ErrOIDCNameConflictLocal: "OIDC 用户名与本地用户冲突" +ErrOIDCNameConflictLDAP: "OIDC 用户名与 LDAP 用户冲突" +ErrOIDCNameConflictOIDC: "OIDC 用户名与其他 OIDC 身份冲突" +ErrOIDCDefaultRoleInvalid: "OIDC 配置的默认角色不可用" +ErrOIDCPrivateAddressDenied: "OIDC 端点地址不符合网络安全策略" +ErrOIDCTLSValidation: "OIDC TLS 证书校验失败" +ErrOIDCTestExpired: "OIDC 浏览器测试已过期,请重新测试" +ErrOIDCLocalCredentialsReadonly: "OIDC 用户名和密码由身份提供方管理,不能在本地修改。" +ErrOIDCPasswordExpirationUnsupported: "OIDC 用户不使用本地密码过期策略。" +ErrOIDCInternal: "OIDC 认证发生内部错误,请稍后重试。" # 用户与权限 ErrNoSuchUser: "未能找到该用户信息,请检查后重试!" @@ -255,7 +278,7 @@ PushAppInstallTaskToNode: "推送应用安装任务到节点 [{{ .name }}]" AppInstallTask: "应用安装任务" PushAppFailed: "推送应用安装任务失败" SkillHubInstallTask: "安装技能 [{{ .name }}]" -SkillHubInstallToTarget: "安装技能 {{ .name }} 到目标 {{ .target }}" +SkillHubInstallToTarget: "安装技能 [{{ .name }}] 到目标 [{{ .target }}]" # 脚本库 ScriptLibrary: "脚本库" @@ -472,3 +495,33 @@ ErrLDAPSyncRunning: "已有 LDAP 同步任务正在执行。" ErrLDAPSyncDirectoryIncomplete: "LDAP 全量查询结果不完整,本次未改变任何用户状态。" ErrLDAPSyncFailed: "LDAP 用户同步失败。" LDAPSyncSuccess: "LDAP 用户同步成功。" +ErrSAML2NotEnabled: "SAML2 认证尚未启用" +ErrSAML2ConfigInvalid: "SAML2 配置无效" +ErrSAML2ConfigChanged: "SAML2 配置已变更,请重新发起认证" +ErrSAML2PanelOriginMissing: "请输入有效的面板对外访问地址,仅包含协议、主机和可选端口" +ErrSAML2MetadataInvalid: "IdP Metadata 缺失或无效" +ErrSAML2MetadataURLInvalid: "IdP Metadata URL 或 Metadata 中的端点地址不符合安全策略" +ErrSAML2MetadataFetch: "获取 IdP Metadata 失败" +ErrSAML2MetadataCertificate: "IdP Metadata 中没有可用的签名证书" +ErrSAML2KeyPairInvalid: "SP 私钥和证书无效或不匹配" +ErrSAML2NameAttributeMissing: "配置的 SAML2 用户名属性缺失或无效" +ErrSAML2DefaultRoleInvalid: "SAML2 配置的默认角色不可用" +ErrSAML2SLOUnavailable: "IdP 未提供支持的单点注销服务" +ErrSAML2TestExpired: "SAML2 测试已过期,请重新测试" +ErrSAML2LoginExpired: "SAML2 登录请求已过期,请重试" +ErrSAML2InvalidState: "SAML2 登录状态无效或已被使用" +ErrSAML2RequestBuild: "生成 SAML2 请求失败" +ErrSAML2ResponseInvalid: "SAML2 响应无效" +ErrSAML2SignatureInvalid: "SAML2 签名校验失败" +ErrSAML2Replay: "SAML2 消息已被使用" +ErrSAML2NameIDMissing: "SAML2 NameID 缺失或无效" +ErrSAML2SessionIndexMissing: "SAML2 SessionIndex 缺失或无效" +ErrSAML2NameConflictLocal: "SAML2 用户名与本地用户冲突" +ErrSAML2NameConflictLDAP: "SAML2 用户名与 LDAP 用户冲突" +ErrSAML2NameConflictOIDC: "SAML2 用户名与 OIDC 用户冲突" +ErrSAML2NameConflictSAML2: "SAML2 用户名与其他 SAML2 身份冲突" +ErrSAML2Internal: "SAML2 认证发生内部错误,请稍后重试" +ErrSAML2LogoutExpired: "SAML2 注销请求已过期" +ErrSAML2LogoutInvalid: "SAML2 注销消息无效" +ErrSAML2LocalCredentialsReadonly: "SAML2 用户名和密码由身份提供商管理,无法在本地修改。" +ErrSAML2PasswordExpirationUnsupported: "SAML2 用户不使用本地密码过期策略。" diff --git a/core/init/auth/mfa_session.go b/core/init/auth/mfa_session.go index ec27df1c3..9e3c5f6b4 100644 --- a/core/init/auth/mfa_session.go +++ b/core/init/auth/mfa_session.go @@ -21,11 +21,20 @@ func GetMFASessionStore() *mfaSessionStore { } type mfaSession struct { - Name string - Entrance string - IP string - Failures int - ExpiresAt time.Time + Name string + Entrance string + IP string + AuthSource string + AuthSourceID uint + AuthSourceConfigVersion uint64 + ExternalIssuer string + ExternalNameID string + ExternalNameIDFormat string + ExternalSessionIndex string + ExternalSessionExpiresAt time.Time + ExternalSessionRequired bool + Failures int + ExpiresAt time.Time } type mfaSessionStore struct { @@ -46,6 +55,41 @@ func (s *mfaSessionStore) Set(name, entrance, ip string) string { }) } +func (s *mfaSessionStore) SetWithAuthSource( + name, entrance, ip, authSource string, + authSourceID uint, + authSourceConfigVersion uint64, +) string { + return s.store.Set(mfaSession{ + Name: name, + Entrance: entrance, + IP: ip, + AuthSource: authSource, + AuthSourceID: authSourceID, + AuthSourceConfigVersion: authSourceConfigVersion, + }) +} + +func (s *mfaSessionStore) SetWithAuthSourceSession( + name, entrance, ip, authSource string, + authSourceID uint, + authSourceConfigVersion uint64, + externalIssuer, externalNameID, externalNameIDFormat, externalSessionIndex string, + externalSessionExpiresAt time.Time, + externalSessionRequired bool, +) string { + return s.store.Set(mfaSession{ + Name: name, Entrance: entrance, IP: ip, + AuthSource: authSource, AuthSourceID: authSourceID, + AuthSourceConfigVersion: authSourceConfigVersion, + ExternalIssuer: externalIssuer, ExternalNameID: externalNameID, + ExternalNameIDFormat: externalNameIDFormat, + ExternalSessionIndex: externalSessionIndex, + ExternalSessionExpiresAt: externalSessionExpiresAt, + ExternalSessionRequired: externalSessionRequired, + }) +} + func (s *mfaSessionStore) Get(sessionID string) (mfaSession, bool) { return s.store.Get(sessionID) } diff --git a/core/init/session/psession/psession.go b/core/init/session/psession/psession.go index 3349901d3..f570a2163 100644 --- a/core/init/session/psession/psession.go +++ b/core/init/session/psession/psession.go @@ -2,6 +2,7 @@ package psession import ( "crypto/rand" + "crypto/sha256" "encoding/hex" "errors" "net/http" @@ -220,6 +221,22 @@ func (p *PSession) DeleteByID(id string) error { return nil } +func (p *PSession) DeleteByHash(sessionHash string) error { + if sessionHash == "" { + return nil + } + p.mu.Lock() + defer p.mu.Unlock() + for sessionID := range p.sessions { + sum := sha256.Sum256([]byte(sessionID)) + if hex.EncodeToString(sum[:]) == sessionHash { + delete(p.sessions, sessionID) + return nil + } + } + return nil +} + func (p *PSession) ApplyTimeout(ttlSeconds int) { now := time.Now() ttl := time.Duration(ttlSeconds) * time.Second diff --git a/core/middleware/csrf_protect.go b/core/middleware/csrf_protect.go index 71a52d620..4cd7cc9c1 100644 --- a/core/middleware/csrf_protect.go +++ b/core/middleware/csrf_protect.go @@ -50,7 +50,14 @@ func requiresCSRFTokenCheck(c *gin.Context) bool { case "/api/v2/core/auth/login", "/api/v2/core/auth/mfalogin", "/api/v2/core/auth/passkey/begin", - "/api/v2/core/auth/passkey/finish": + "/api/v2/core/auth/passkey/finish", + "/api/v2/core/auth/oidc/begin", + "/api/v2/core/auth/oidc/finish": + return false + case "/api/v2/core/auth/saml2/begin", + "/api/v2/core/auth/saml2/acs", + "/api/v2/core/auth/saml2/finish", + "/api/v2/core/auth/saml2/logout": return false } if c.GetBool("API_AUTH") { diff --git a/core/utils/ttlstore/ttlstore.go b/core/utils/ttlstore/ttlstore.go index 3260ef1db..8c94af9b1 100644 --- a/core/utils/ttlstore/ttlstore.go +++ b/core/utils/ttlstore/ttlstore.go @@ -63,6 +63,25 @@ func (s *Store[T]) Get(itemID string) (T, bool) { return item.Value, true } +// Take atomically returns and removes an item. It is intended for one-time +// credentials such as authentication state and handoff tickets. +func (s *Store[T]) Take(itemID string) (T, bool) { + s.mu.Lock() + defer s.mu.Unlock() + + item, ok := s.items[itemID] + if !ok { + var zero T + return zero, false + } + delete(s.items, itemID) + if s.now().After(item.ExpiresAt) { + var zero T + return zero, false + } + return item.Value, true +} + func (s *Store[T]) Update(itemID string, fn func(*T) bool) bool { s.mu.Lock() defer s.mu.Unlock() diff --git a/core/utils/xpack/helper/auth_helper.go b/core/utils/xpack/helper/auth_helper.go index 06aaccc35..3dfc8094b 100644 --- a/core/utils/xpack/helper/auth_helper.go +++ b/core/utils/xpack/helper/auth_helper.go @@ -22,6 +22,10 @@ func (a *authHelper) MFALogin(c *gin.Context, info baseDto.MFALogin, entrance st return auth.MFALogin(c, info, entrance) } +func (a *authHelper) PrepareLogout(_ *gin.Context) (*baseDto.LogoutResult, error) { + return &baseDto.LogoutResult{}, nil +} + func (a *authHelper) PasskeyBeginLogin(c *gin.Context, entrance string) (*baseDto.PasskeyBeginResponse, string, error) { return auth.PasskeyBeginLogin(c, entrance) } diff --git a/core/utils/xpack/providers/auth.go b/core/utils/xpack/providers/auth.go index 83ab309a0..6e5fcc770 100644 --- a/core/utils/xpack/providers/auth.go +++ b/core/utils/xpack/providers/auth.go @@ -9,6 +9,7 @@ import ( type AuthProvider interface { Login(c *gin.Context, info dto.Login, entrance string) (*dto.UserLoginInfo, string, error) MFALogin(c *gin.Context, info dto.MFALogin, entrance string) (*dto.UserLoginInfo, string, error) + PrepareLogout(c *gin.Context) (*dto.LogoutResult, error) ResetSuperAdminUser(name, password string) error diff --git a/frontend/src/api/index.ts b/frontend/src/api/index.ts index 6d5a06f8c..449f53dba 100644 --- a/frontend/src/api/index.ts +++ b/frontend/src/api/index.ts @@ -49,7 +49,11 @@ class RequestHttp { config.url === '/core/auth/login' || config.url === '/core/auth/mfalogin' || config.url === '/core/auth/passkey/begin' || - config.url === '/core/auth/passkey/finish' + config.url === '/core/auth/passkey/finish' || + config.url === '/core/auth/oidc/begin' || + config.url === '/core/auth/oidc/finish' || + config.url === '/core/auth/saml2/begin' || + config.url === '/core/auth/saml2/finish' ) { config.headers.EntranceCode = encodeBase64(globalStore.entrance); } diff --git a/frontend/src/api/interface/auth.ts b/frontend/src/api/interface/auth.ts index 67f0ae1b5..fe3ad7f74 100644 --- a/frontend/src/api/interface/auth.ts +++ b/frontend/src/api/interface/auth.ts @@ -5,6 +5,7 @@ export namespace Login { captcha: string; captchaID: string; authMethod: string; + authSource: 'local' | 'ldap'; } export interface MFALoginForm { sessionId: string; @@ -22,6 +23,44 @@ export namespace Login { sessionId: string; publicKey: Record; } + export interface OIDCStatus { + enabled: boolean; + displayName: string; + authorizationCode: boolean; + } + export interface LDAPStatus { + enabled: boolean; + } + export interface OIDCBeginResponse { + authorizationURL: string; + } + export interface OIDCFinishRequest { + ticket: string; + } + export interface SAML2Status { + enabled: boolean; + displayName: string; + syncLogout: boolean; + } + export interface SAML2RedirectNavigation { + binding: 'redirect'; + redirectURL: string; + } + export interface SAML2PostNavigation { + binding: 'post'; + postURL: string; + fields: Record; + } + export type SAML2Navigation = SAML2RedirectNavigation | SAML2PostNavigation; + export interface SAML2BeginResponse { + navigation: SAML2Navigation; + } + export interface SAML2FinishRequest { + ticket: string; + } + export interface LogOutResponse { + saml2Navigation?: SAML2Navigation; + } export interface ResCaptcha { imagePath: string; captchaID: string; diff --git a/frontend/src/api/modules/auth.ts b/frontend/src/api/modules/auth.ts index 14aed2022..54e98a09f 100644 --- a/frontend/src/api/modules/auth.ts +++ b/frontend/src/api/modules/auth.ts @@ -19,12 +19,40 @@ export const passkeyFinishApi = (params: Record, sessionId: string) return http.post(`/core/auth/passkey/finish`, params, undefined, { 'Passkey-Session': sessionId }); }; +export const ldapStatusApi = () => { + return http.get(`/core/auth/ldap/status`, undefined, { skipErrorMessage: true }); +}; + +export const oidcStatusApi = () => { + return http.get(`/core/auth/oidc/status`, undefined, { skipErrorMessage: true }); +}; + +export const oidcBeginApi = () => { + return http.post(`/core/auth/oidc/begin`); +}; + +export const oidcFinishApi = (params: Login.OIDCFinishRequest) => { + return http.post(`/core/auth/oidc/finish`, params); +}; + +export const saml2StatusApi = () => { + return http.get(`/core/auth/saml2/status`, undefined, { skipErrorMessage: true }); +}; + +export const saml2BeginApi = () => { + return http.post(`/core/auth/saml2/begin`); +}; + +export const saml2FinishApi = (params: Login.SAML2FinishRequest) => { + return http.post(`/core/auth/saml2/finish`, params); +}; + export const getCaptcha = () => { return http.get(`/core/auth/captcha`); }; export const logOutApi = () => { - return http.post(`/core/auth/logout`); + return http.post(`/core/auth/logout`); }; export const getLoginSetting = () => { diff --git a/frontend/src/lang/fu.ts b/frontend/src/lang/fu.ts index 424dd0e0e..15c02b128 100644 --- a/frontend/src/lang/fu.ts +++ b/frontend/src/lang/fu.ts @@ -61,7 +61,7 @@ const fuLocales: Record = { fu: { table: { more: 'ເບິ່ງຕື່ມ', - custom_table_rows: 'ກຳນົດແຖວຕາຕະລາງເອງ', + custom_table_rows: 'ຖັນກຳນົດເອງ', }, steps: { cancel: 'ຍົກເລີກ', diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index c08d3174f..6e84f2d74 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -167,6 +167,7 @@ const message = { deleteSuccess: 'Deleted successfully', loginSuccess: 'Logged in successfully', operationSuccess: 'Completed successfully', + operationFailed: 'Operation failed', copySuccess: 'Copied successfully', notSupportOperation: 'This operation is not supported', requestTimeout: 'Request timed out, try again later', @@ -208,6 +209,7 @@ const message = { username: 'Username', password: 'Password', passkey: 'Passkey Login', + otherLoginMethods: 'Other sign-in methods', welcome: 'Welcome back. Sign in with your username and password.', errorAuthInfo: 'Incorrect username or password, try again.', errorMfaInfo: 'Invalid authentication info, try again.', @@ -477,7 +479,7 @@ const message = { cpuSteal: 'Steal', cpuTop: 'Top 5 Processes by CPU Usage', memTop: 'Top 5 Processes by Memory Usage', - loadAverage: 'Load average in the last 1 minute | Load average in the last {n} minutes', + loadAverage: 'Load average over the last {0} minutes', load: 'Load', mount: 'Mount point', fileSystem: 'File system', @@ -1758,7 +1760,8 @@ const message = { dockerStatus: 'Docker Service', daemonJsonPathHelper: 'Ensure that the configuration path is the same as that specified in docker.service.', mirrors: 'Registry mirrors', - mirrorsHelper: '', + mirrorsHelper: + 'Use registry mirror URLs first for image operations. Leave this empty to disable registry mirrors.', mirrorsHelper2: 'For details, see the official documentation.', registries: 'Insecure registries', ipv6Helper: @@ -3754,9 +3757,9 @@ const message = { staticChangePHPHelper: 'Currently a static website, you can switch to a PHP website', proxyCache: 'Reverse Proxy Cache', cacheLimit: 'Cache Space Limit', - shareCahe: 'Cache Count Memory Size', + shareCache: 'Cache Count Memory Size', cacheExpire: 'Cache Expiration Time', - shareCaheHelper: 'Approximately 8000 cache objects can be stored per 1M of memory', + shareCacheHelper: 'Approximately 8000 cache objects can be stored per 1M of memory', cacheLimitHelper: 'Old cache will be automatically deleted when the limit is exceeded', cacheExpireJHelper: 'Cache will be deleted if it misses after the expiration time', realIP: 'Real IP', @@ -4105,6 +4108,7 @@ const message = { }, runtime: { runtime: 'Runtime', + default: 'Default', workDir: 'Working directory', localHelper: 'For local environment installation and offline environment usage issues, see ', versionHelper: 'PHP version, e.g. v8.0', @@ -4907,6 +4911,14 @@ const message = { authManage: 'Authentication', auth: { providerNavigation: 'Authentication providers', + defaultNode: 'Default node', + defaultNodePlaceholder: 'Select a node', + defaultNodeHelper: 'Only for new users.', + defaultNodeRequired: 'Select a valid default node.', + nodesLoadFailed: 'Failed to load nodes. Retry before selecting the default node.', + nodeHandling: 'Node handling', + assignDefaultNode: 'Assign default node: {node}', + keepExistingNode: 'Keep the existing node permissions', providers: { ldap: 'AD/LDAP', passkey: 'Passkey', @@ -4934,7 +4946,395 @@ const message = { planned: 'Planned', plannedTitle: '{0} authentication settings', plannedDesc: 'This authentication provider is planned and is not available yet.', + oidc: { + accessMode: 'Connection mode', + accessModeDesc: 'Use standard Discovery whenever the identity provider supports it.', + actionCreate: 'Create user', + actionKeepName: 'Keep the current name', + actionPending: 'Waiting for result', + actionReject: 'Reject login', + actionUpdate: 'Update identity information', + advanced: 'Advanced settings', + advancedDesc: 'Keep the secure defaults unless the provider requires a compatibility option.', + assignDefaultRole: 'Assign default role: {role}', + authorizationEndpoint: 'Authorization Endpoint', + authorizationEndpointInvalid: 'Enter a valid Authorization Endpoint.', + authorizationFlow: 'Authorization flow', + automatic: 'Automatic', + automaticPolicy: 'Automatic handling policy', + automaticPolicyDesc: 'These rules are enforced by the backend and are not administrator switches.', + basic: 'Basic settings', + basicDesc: 'Select the provider mode, then configure the client and callback.', + browserTest: 'Browser test login', + browserTestConflict: 'Identity verified, but the name conflicts', + browserTestConflictHelper: 'The mapped name belongs to another identity and will not be claimed.', + browserTestExpired: 'Browser test expired', + browserTestExpiredHelper: 'Start a new browser test and complete authorization before it expires.', + browserTestFailed: 'Browser test failed', + browserTestFailedHelper: + 'The identity preview could not be completed. Review the localized backend error.', + browserTestIsolation: + 'This performs a real authorization round trip but does not create or update users, assign roles, or create an authenticated panel session.', + browserTestPopupBlocked: 'Allow pop-ups for this site, then start the browser test again.', + browserTestPopupClosed: 'The authorization window was closed before the test completed.', + browserTestSuccess: 'Provider verification succeeded', + browserTestSuccessHelper: 'Identity mapping was previewed without changing users or sessions.', + browserTestTitle: 'OIDC browser test login', + browserTestWaiting: 'Waiting for Provider authorization', + browserTestWaitingHelper: + 'Complete sign-in in the new browser window. This page will update automatically.', + callbackCopied: 'OIDC callback URL copied.', + callbackURL: 'Callback URL', + callbackURLHelper: "Add this URL to the client's allowed callback URLs in the identity provider.", + cancelClearSecret: 'Cancel clearing', + clearSecret: 'Clear secret', + clearSecretConfirm: 'The Client Secret will be removed only after you save. Continue?', + clientAuthMethod: 'Client authentication method', + clientAuthMethodHelper: + 'Select the authentication method configured for this client in the identity provider.', + clientAuthMethodRequired: 'Select a client authentication method.', + clientID: 'Client ID', + clientIDRequired: 'Enter the Client ID.', + clientSecret: 'Client Secret', + clockSkew: 'Token time tolerance', + clockSkewHelper: + 'Allows a small time difference between the identity provider and 1Panel. Keep the default 60 seconds.', + clockSkewRequired: 'Enter the token time tolerance.', + compatibilityMode: 'Compatibility mode', + compatibilityModeHelper: + 'Use only for incomplete Discovery or rewritten endpoints. Core OIDC validation remains enabled.', + configurationFailedHelper: 'The test failed. The page only displays the localized backend error.', + configurationFailedTag: 'Test failed', + configurationHighRiskPassed: + 'The configuration passed, but contains high-risk compatibility options.', + configurationHighRiskTag: 'High-risk configuration passed', + configurationNotTested: 'The current configuration has not been tested.', + configurationNotTestedTag: 'Not tested', + configurationPassed: 'The current configuration passed the security and capability checks.', + configurationPassedTag: 'Test passed', + configurationStaleHelper: 'Configuration changed. Test it again before saving.', + configurationStaleTag: 'Result expired', + configurationTestMeta: + 'Tested at {time}; completed in {duration} ms. Raw Provider responses are not stored.', + configurationTestResult: 'Configuration test result', + configurationTestResultDesc: + 'This checks Discovery and capabilities only; it does not exchange an authorization code or prove the Client Secret. Use browser test login for end-to-end verification.', + configurationTestSuccess: 'OIDC configuration test succeeded.', + configurationTesting: 'Testing the current OIDC configuration…', + configurationTestingTag: 'Testing', + configureSecret: 'Configure secret', + conflictExistingRename: 'A bound subject returns a new name that is occupied', + conflictExistingRenameResult: 'Keep the existing User.Name and allow the bound user to sign in', + conflictLDAP: 'LDAP user', + conflictLocal: 'Local user', + conflictNewAvailable: 'New subject and the mapped name are available', + conflictNewAvailableResult: 'Create an enterprise user and assign the default role', + conflictNone: 'No conflict', + conflictOIDC: 'Another OIDC identity', + conflictOccupied: 'The mapped name belongs to a local, LDAP, or another OIDC identity', + conflictOccupiedResult: 'Reject the new identity; never bind or merge automatically', + conflictType: 'Conflict type', + connectionSecurity: 'Connection security', + connectionSecurityDesc: + 'Certificates are verified by default; private IdP addresses are detected automatically.', + connectionTest: 'Connection and configuration test', + connectionTestCompatibilityDesc: 'Validate custom endpoints and the protocol security policy.', + connectionTestStandardDesc: + 'Endpoints and capabilities are discovered automatically from the Issuer.', + connectionTestTab: 'Connection test', + customCA: 'Custom CA', + customCAHelper: 'Applies only to this authentication source and is never written to logs.', + customCARequired: 'Provide the custom CA certificate.', + defaultRole: 'Default role', + defaultRoleHelper: + 'Assigned only when the user is first created; later sign-ins do not change the role.', + defaultRolePlaceholder: 'Select a role', + defaultRoleRequired: 'Select a valid default role.', + disableAfterSave: 'OIDC will be disabled after saving.', + disableConfirm: 'Disabling OIDC immediately invalidates access for users of this source. Continue?', + disableDiscardConfirm: + 'Disabling OIDC is an emergency action: it only closes the login entry and immediately invalidates access for users of this source. Other unsaved changes on this page, including Client Secret changes, will be discarded. Continue?', + disableTitle: 'Disable OIDC', + disabled: 'Disabled', + discoveryAllowlist: 'Discovery ∩ security allowlist', + enable: 'Enable', + enableAfterSave: 'OIDC will be enabled after a successful save.', + enabled: 'Enabled', + endSessionEndpoint: 'End Session Endpoint', + endSessionEndpointHelper: + 'Saved for future use; Provider-initiated logout is not included in this release.', + endSessionEndpointInvalid: 'Enter a valid End Session Endpoint.', + endpointDiscoveryPlaceholder: 'Shown after connection test', + firstLogin: 'First login', + firstLoginPolicy: 'Create a local enterprise user and assign the configured default role.', + fixedAuthorizationCode: 'Authorization Code Flow', + fixedNoTokenPersistence: 'Tokens, Claims, and the verifier are never persisted', + fixedSecurityPolicy: 'Always enforced; no configuration required', + fixedStateNonce: 'One-time state and nonce', + fixedTokenValidation: 'ID Token signature and Claims validation', + highRiskSaveConfirm: + 'This enabled configuration contains high-risk compatibility options. Confirm that the isolated environment requires them.', + highRiskTitle: 'High-risk OIDC configuration', + hs256Compatibility: 'HS256 (compatibility)', + hs256KeyHelper: + 'HS256 always uses this source’s Client Secret and does not accept a separate signing key.', + hs256Warning: + 'HS256 uses a shared symmetric secret for ID Token signatures. Use it only when the Provider cannot use an asymmetric algorithm.', + identityBindingPolicy: + 'Identity is fixed to AuthSourceID + issuer + subject. A matching user name never claims another account.', + identityMissing: 'Identity inactive', + issuer: 'Issuer URL', + issuerHelper: 'The ID Token iss value and Discovery issuer must match this value exactly.', + issuerInvalid: 'Enter a valid HTTP or HTTPS Issuer URL without query or fragment.', + issuerRequired: 'Enter the Issuer URL.', + jwksRotation: 'Automatic JWKS rotation', + jwksURI: 'JWKS URI', + jwksURIHelper: 'Required for asymmetric signing when the key source is JWKS.', + jwksURIInvalid: 'Enter a valid JWKS URI for the selected signing key source.', + keepExistingRole: 'Keep existing roles and local permissions', + localSecurityData: 'Local security data', + localSecurityDataPolicy: 'Never overwrite roles, MFA, API Keys, Passkeys, or local permissions.', + localCredentialsManaged: + 'The user name and local password are managed by OIDC and cannot be edited here. Roles, permissions, MFA, API Keys, and Passkeys remain local.', + localUserFields: 'Local user fields', + localUserFieldsDesc: + 'The first release maps only User.Name and does not use a JSON mapping expression.', + loginWith: 'Sign in with {provider}', + manualEndpoints: 'Custom endpoints', + manualEndpointsDesc: + 'Use only when Discovery is incomplete or an upstream gateway rewrites endpoints.', + mappingResult: 'Mapping result', + mode: 'Connection mode', + modeRequired: 'Select a connection mode.', + nameClaim: 'Username Claim', + nameClaimHelper: 'Enter the field containing the username, such as preferred_username.', + nameClaimRequired: 'Enter the Username Claim.', + nameConflict: 'Name conflict policy', + panelURL: '1Panel public URL', + panelURLHTTPWarning: + 'HTTP does not protect the authorization response. Use it only in an isolated private environment accepted by the Provider.', + panelURLHelper: + 'Enter the address users use to access 1Panel. It is used to generate the callback URL.', + panelURLInvalid: 'Enter an origin containing only scheme, host, and optional port.', + panelURLRequired: 'Enter the 1Panel public URL.', + pkceDisabled: 'Disabled (compatibility only)', + pkceDisabledWarning: 'Disabling PKCE reduces protection against authorization-code interception.', + pkceHelper: 'Prefer S256. The plain challenge method is never offered.', + pkceS256: 'S256 (recommended)', + plannedHandling: 'Planned handling', + privateNetworkIdP: 'Private-network IdP', + privateNetworkIdPHelper: + 'Explicitly permits private addresses; metadata, loopback, link-local, redirects, and DNS rebinding remain blocked.', + privateNetworkWarning: 'Private-network access is enabled for this authentication source.', + protocolCompatibility: 'Protocol compatibility', + protocolCompatibilityDesc: 'ID Token signature validation can never be disabled.', + providerAndClient: 'Provider and client', + providerAndClientDesc: + 'The Client Secret can only be replaced or cleared and is never returned by the page.', + providerCapabilities: 'Provider capabilities', + recentTestSuccess: 'Last test succeeded: {0}', + recommended: 'Recommended', + rejectPlain: 'plain rejected', + replaceSecret: 'Replace secret', + requestAndClaims: 'Requests and attributes', + requestAndClaimsDesc: 'Configure authorization scopes, UserInfo fallback, and request parameters.', + requestTimeout: 'Request timeout', + requestTimeoutRequired: 'Enter the request timeout.', + restore: 'Restore', + restored: 'The last saved OIDC settings were restored.', + result: 'Result', + rolesLoadFailed: 'Roles could not be loaded. Retry before selecting the default role.', + roleHandling: 'Role handling', + scenario: 'Scenario', + scopes: 'Authorization scopes', + scopesHelper: 'Must include openid. Separate multiple scopes with spaces.', + scopesRequired: 'Scopes must include openid.', + seconds: 'seconds', + secretClearHelper: + 'After clearing, a new Client Secret is required before OIDC can be enabled again.', + secretConfigured: 'Configured', + secretNotConfigured: 'Not configured', + secretPlaceholder: 'Enter a new Client Secret', + secretReplaceHelper: + 'The new secret replaces the saved value when you save. Update the Client Secret in the OIDC Provider as well.', + secretRequiredHelper: 'Configure a Client Secret before enabling OIDC.', + secretRequiredToEnable: 'Configure a Client Secret before enabling OIDC.', + secretSavedHelper: 'Stored encrypted. Leave blank to keep the current client secret.', + secretWaiting: 'Waiting for input', + secretWillClear: 'Will be cleared', + secretWillReplace: 'Will be replaced', + signingAlgorithm: 'ID Token signing algorithm', + signingAlgorithmHelper: 'Only algorithms in the backend security allowlist are available.', + signingKey: 'Signing key', + signingKeyClientSecret: 'Client Secret (HS256 only)', + signingKeyJWKS: 'JWKS URI with automatic rotation', + signingKeySource: 'Signing key source', + signingKeySourceHelper: 'Prefer JWKS. A static public key cannot rotate automatically.', + signingKeyStatic: 'Static JWK or PEM public key', + standardDiscovery: 'Standard OIDC Discovery', + standardDiscoveryDesc: + '1Panel discovers endpoints and capabilities and does not store the raw document.', + standardMode: 'Standard mode', + standardModeHelper: 'Discover endpoints, signing capabilities, and PKCE support from the Issuer.', + standardProtocolPolicy: 'Standard protocol policy', + standardProtocolPolicyDesc: + 'Signing capabilities are negotiated automatically; no signing key is entered here.', + staticSigningKey: 'Static signing public key', + staticSigningKeyHelper: + 'Only public-key material is accepted. Rotate it manually when the Provider key changes.', + staticSigningKeyPlaceholder: 'Paste a JWK, JWKS JSON, or PEM public key', + staticSigningKeyRequired: 'Provide the static signing public key.', + staticSigningKeyWarning: + 'A static signing key cannot rotate automatically; update it before the Provider rotates keys.', + settingLoadFailed: 'OIDC settings could not be loaded', + settingLoadFailedHelper: + 'The form is locked to avoid saving an empty default configuration over the current settings. Retry after the connection recovers.', + subsequentLogin: 'Subsequent login', + subsequentLoginPolicy: + 'Find the binding by subject and update only User.Name when the new name is available.', + testBeforeBrowserTest: 'Test the current configuration before starting a browser login test.', + testBeforeEnable: 'Test the current configuration before saving configuration changes.', + testConfiguration: 'Test configuration', + testDiscovery: 'Test Discovery', + tlsCustomCA: 'HTTPS · Custom CA certificate', + tlsPrivateHTTP: 'HTTP · Private network only (dangerous)', + tlsPrivateHTTPWarning: + 'HTTP provides no transport encryption and is restricted to explicitly allowed private targets.', + tlsSkipVerify: 'Ignore SSL certificate verification', + tlsSystem: 'HTTPS · System certificate verification (recommended)', + tokenEndpoint: 'Token Endpoint', + tokenEndpointInvalid: 'Enter a valid Token Endpoint.', + transportSecurity: 'Transport security', + transportSecurityHelper: + 'Prefer HTTPS. Private HTTP also requires explicit private-network access.', + unsavedChanges: 'There are unsaved OIDC setting changes.', + usedClaim: 'Claim used', + userInfoEndpoint: 'UserInfo Endpoint', + userInfoEndpointHelper: + 'When the username field is missing, the system retrieves it from this endpoint. Leave blank to skip fallback.', + userInfoEndpointInvalid: 'Enter a valid UserInfo Endpoint.', + userMapping: 'User settings', + userMappingDesc: + 'Configure OIDC username mapping and the default node and role used to create a user on first sign-in.', + }, + saml2: { + actionCreate: 'Create user', + actionPending: 'Waiting for result', + actionReject: 'Reject sign-in', + actionReuse: 'Use bound user', + assignDefaultRole: 'Assign default role: {role}', + basic: 'Basic settings', + basicDesc: 'Configure the common options required by most standard SAML2 identity providers.', + browserTest: 'Test sign-in', + browserTestConflict: 'Identity verified, but the username conflicts', + browserTestConflictHelper: + 'The mapped username belongs to another identity and will not be linked automatically.', + browserTestExpired: 'Browser test expired', + browserTestExpiredHelper: 'Start a new test and complete sign-in before it expires.', + browserTestFailed: 'Browser test failed', + browserTestFailedHelper: + 'The identity preview could not be completed. Check the localized backend error.', + browserTestIsolation: + 'Performs a real SAML2 round trip without creating users, assigning roles, or creating a session.', + browserTestPopupBlocked: 'Allow pop-ups for this site, then run the test again.', + browserTestPopupClosed: 'The sign-in window was closed before the test completed.', + browserTestSuccess: 'SAML2 identity verified', + browserTestSuccessHelper: + 'The identity mapping preview completed without modifying users or sessions.', + browserTestTitle: 'SAML2 test sign-in', + browserTestWaiting: 'Waiting for IdP sign-in', + browserTestWaitingHelper: 'Complete sign-in in the new window. This page updates automatically.', + certificateFileInvalid: 'Select a valid PEM, CRT, or CER certificate file.', + configured: 'Configured', + configurationFailedHelper: 'The test failed. Only the localized backend error is displayed.', + configurationNotTested: 'The current configuration has not been tested.', + configurationPassed: 'The current configuration passed validation.', + configurationStaleHelper: 'Authentication settings changed. Test the current draft again.', + configurationTestSuccess: 'SAML2 configuration test succeeded.', + configurationTesting: 'Testing the current SAML2 configuration…', + conflictLDAP: 'LDAP user', + conflictLocal: 'Local user', + conflictNone: 'No conflict', + conflictOIDC: 'OIDC identity', + conflictSAML2: 'Another SAML2 identity', + conflictType: 'Conflict type', + credentialFileReadFailed: 'The credential file could not be read.', + credentialFileTooLarge: 'Credential files must not exceed 256 KiB.', + credentialsRequired: 'Configure both the SP private key and certificate.', + defaultRole: 'New user role', + defaultRoleHelper: + 'Assigned only when the user is first created. Later sign-ins keep local roles, MFA, and permissions.', + defaultRolePlaceholder: 'Select a role', + defaultRoleRequired: 'Select a valid new-user role.', + disableConfirm: + 'Disabling SAML2 immediately rejects new sign-ins and invalidates its user sessions. Continue?', + disableDiscardConfirm: + 'Disabling SAML2 discards other unsaved changes on this page and immediately invalidates its user sessions. Continue?', + disableTitle: 'Disable SAML2', + disabled: 'Disabled', + enable: 'Enable', + enabled: 'Enabled', + idpMetadata: 'IdP Metadata', + idpMetadataDesc: 'Enter a URL or paste XML. When both are present, the URL takes precedence.', + keepExistingRole: 'Keep the existing role and local permissions', + loginWith: 'Sign in with {provider}', + mappingResult: 'Mapping result', + metadataRequired: 'Enter an IdP Metadata URL or XML.', + metadataURLHelper: 'The backend downloads and validates Metadata during testing and saving.', + metadataURLInvalid: 'Enter a valid HTTPS Metadata URL without credentials or a fragment.', + metadataURLRecommended: 'Metadata URL (recommended)', + metadataXML: 'Metadata XML', + metadataXMLHelper: 'Use this when the IdP does not expose a reachable Metadata URL.', + metadataXMLInvalid: 'Enter valid EntityDescriptor Metadata XML.', + metadataXMLPlaceholder: 'Paste ...', + nameAttribute: 'Username attribute', + nameAttributeHelper: + 'Reads this Attribute from the verified SAML Assertion and maps it to the 1Panel username.', + nameAttributePlaceholder: 'For example: uid, username, or account', + nameAttributeRequired: 'Enter the username attribute.', + notConfigured: 'Not configured', + or: 'or', + pageDesc: + 'Connect enterprise single sign-on through IdP Metadata with the common settings on one page.', + plannedHandling: 'Planned handling', + privateKeyFileInvalid: 'Select a valid PEM private-key file.', + recentTestSuccess: 'Last successful test: {0}', + restore: 'Restore', + restored: 'Restored the last saved SAML2 configuration.', + roleHandling: 'Role handling', + rolesLoadFailed: 'Failed to load roles. Retry before selecting the new-user role.', + selectFile: 'Select file', + serviceStatus: 'Service status', + serviceStatusDesc: 'The current configuration must pass a test before SAML2 can be enabled.', + settingLoadFailed: 'Failed to load SAML2 settings', + settingLoadFailedHelper: + 'The form is locked to avoid overwriting saved settings with empty defaults. Retry after connectivity is restored.', + spCertificate: 'SP certificate', + spCertificateHelper: 'Published in SP Metadata so the IdP can verify sign-in and logout requests.', + spCredentials: 'SP private key and certificate', + spCredentialsDesc: + 'Used to sign sign-in and logout messages. Signature and validation policy is fixed by the backend.', + spPrivateKey: 'SP private key', + spPrivateKeyHelper: + 'Used to sign AuthnRequest and logout messages. It is encrypted at rest and never displayed.', + syncLogout: 'Synchronized logout', + syncLogoutHelper: + 'Signing out of either 1Panel or the identity provider also signs out the other side.', + testBeforeBrowserTest: 'Test the current configuration before running a browser sign-in test.', + testBeforeEnable: + 'Test the current configuration before enabling SAML2 or saving authentication-sensitive changes.', + testConfiguration: 'Test configuration', + unsavedChanges: 'The SAML2 configuration has unsaved changes.', + usedAttribute: 'Username mapping', + usersAndRoles: 'Users and roles', + usersAndRolesDesc: + 'Configure panel username mapping and the default node and role used to create a user on first sign-in.', + }, ldap: { + basic: 'Basic settings', + loginTitle: 'LDAP sign-in', + loginWith: 'Sign in with LDAP', + backToLocalLogin: 'Back to panel sign-in', enable: 'Enable', enabled: 'Enabled', disabled: 'Disabled', @@ -5152,6 +5552,7 @@ const message = { deleteConfirm: 'Delete this export record and file?', }, waf: { + WAF: 'WAF', name: 'WAF', blackWhite: 'Black and White List', globalSetting: 'Global Settings', diff --git a/frontend/src/lang/modules/es-es.ts b/frontend/src/lang/modules/es-es.ts index 19e7a6672..d4c4cdc54 100644 --- a/frontend/src/lang/modules/es-es.ts +++ b/frontend/src/lang/modules/es-es.ts @@ -14,6 +14,7 @@ const message = { next: 'Siguiente', create: 'Crear', add: 'Agregar', + select: 'Seleccionar', save: 'Guardar', set: 'Configuración', sync: 'Sincronizar', @@ -27,7 +28,6 @@ const message = { setDefault: 'Restaurar valores predeterminados', restart: 'Reiniciar', conn: 'Conectar', - disconn: 'Desconectar', clean: 'Limpiar', cleanAll: 'Limpiar todo', selectAll: 'Seleccionar todo', @@ -91,6 +91,7 @@ const message = { disConn: 'Desconectar', visit: 'Abrir', tip: 'Aviso', + reconnect: 'Reconectar', }, operate: { start: 'Iniciar', @@ -166,6 +167,7 @@ const message = { deleteSuccess: 'Eliminación completada correctamente', loginSuccess: 'Inicio de sesión completado correctamente', operationSuccess: 'Operación completada correctamente', + operationFailed: 'Operación fallida', copySuccess: 'Copiado completado correctamente', notSupportOperation: 'Esta operación no es compatible', requestTimeout: 'La solicitud caducó, inténtalo más tarde', @@ -208,6 +210,7 @@ const message = { username: 'Usuario', password: 'Contraseña', passkey: 'Inicio de sesión con Passkey', + otherLoginMethods: 'Otros métodos de inicio de sesión', welcome: 'Bienvenido de nuevo. Inicia sesión con tu usuario y contraseña.', errorAuthInfo: 'Usuario o contraseña incorrectos, inténtalo nuevamente.', errorMfaInfo: 'Información de autenticación inválida, inténtalo nuevamente.', @@ -291,6 +294,9 @@ const message = { authBasicPassword: 'Admite letras, números y caracteres especiales comunes, longitud de 1 a 72', length128Err: 'La longitud no puede exceder los 128 caracteres', maxLength: 'La longitud no puede exceder los {0} caracteres', + vmName: 'Admite letras inglesas, números, ".", "-" y "_"; longitud de 1 a 64; debe comenzar con una letra o un número.', + vmNetwork: + 'Admite letras inglesas, números, ".", ":", "-" y "_"; longitud de 1 a 64; debe comenzar con una letra o un número.', alias: 'Soporta A->Z, números, - and _, largo 1-128 carácteres, no puede empezar ni terminar con -_.', }, res: { @@ -388,7 +394,7 @@ const message = { semicolon: ';', }, log: { - noLog: 'No logs available', + noLog: 'No hay registros disponibles', }, }, menu: { @@ -473,7 +479,7 @@ const message = { cpuSteal: 'Robado', cpuTop: 'Top 5 de Procesos por Uso de CPU', memTop: 'Top 5 de Procesos por Uso de Memoria', - loadAverage: 'Promedio de carga en el último minuto | Promedio de carga en los últimos {n} minutos', + loadAverage: 'Promedio de carga en el último minuto | Promedio de carga en los últimos {0} minutos', load: 'Carga', mount: 'Punto de montaje', fileSystem: 'Sistema de archivos', @@ -510,6 +516,7 @@ const message = { deleteBackupHelper: 'Eliminar copias de seguridad de la base de datos simultáneamente', delete: 'La operación de eliminación no se puede revertir, por favor introduzca "', deleteHelper: '" para eliminar esta base de datos', + deleteUserHelper: '" para eliminar este usuario', userBoundDatabases: 'tiene acceso a las siguientes bases de datos:', noMysql: 'Servicio de base de datos (MySQL o MariaDB)', noPostgresql: 'Servicio de base de datos PostgreSQL', @@ -549,6 +556,7 @@ const message = { 'Este puerto es el puerto expuesto del contenedor. Debe guardar la modificación por separado y reiniciar el contenedor.', loadFromRemote: 'Sincronizar desde el servidor', userBind: 'Vincular usuario', + noUserBind: 'Sin vinculación', userAuthorization: 'Autorización de usuario', noUserAuthorization: 'No autorizar', authorizedDatabaseCount: '{0} base(s) de datos autorizada(s)', @@ -568,7 +576,6 @@ const message = { passwordHelper: 'No se puede obtener, haga clic para modificar', remote: 'Remoto', remoteDB: 'Servidor remoto | Servidores remotos', - manageRemoteDB: 'Administrar servidores remotos', createRemoteDB: 'Vincular @.lower:database.remoteDB', unBindRemoteDB: 'Desvincular @.lower:database.remoteDB', unBindForce: 'Forzar desvinculación', @@ -816,19 +823,12 @@ const message = { roleMarkdownDescriptions: { 'AGENTS.md': [ 'Instrucciones operativas para el agente y cómo debe usar la memoria.', - 'Se carga al inicio de cada sesión.', 'Buen lugar para reglas, prioridades y detalles sobre cómo debe comportarse.', ], - 'SOUL.md': ['Personalidad, tono y límites.', 'Se carga en cada sesión.'], - 'USER.md': ['Quién es el usuario y cómo dirigirse a él.', 'Se carga en cada sesión.'], - 'IDENTITY.md': [ - 'El nombre, estilo y emoji del agente.', - 'Se crea o actualiza durante el ritual de inicio.', - ], - 'TOOLS.md': [ - 'Notas sobre las herramientas locales y las convenciones.', - 'No controla la disponibilidad de herramientas; solo sirve de guía.', - ], + 'SOUL.md': ['Personalidad, tono y límites.'], + 'USER.md': ['Quién es el usuario y cómo dirigirse a él.'], + 'IDENTITY.md': ['El nombre, estilo y emoji del agente.'], + 'TOOLS.md': ['Notas sobre las herramientas locales y las convenciones.'], 'HEARTBEAT.md': [ 'Lista de comprobación opcional para ejecuciones heartbeat.', 'Manténgala corta para evitar gastar tokens.', @@ -840,7 +840,6 @@ const message = { 'BOOTSTRAP.md': [ 'Ritual único de la primera ejecución.', 'Solo se crea para un espacio de trabajo completamente nuevo.', - 'Elimínelo cuando el ritual se complete.', ], }, duplicateBinding: 'La combinacion de canal e ID de cuenta debe ser unica', @@ -1009,9 +1008,6 @@ const message = { failureCount: 'Fallos', lastError: 'Último error', modelMap: 'Mapeo de modelos', - apiKeyKeepEmpty: 'API Key (dejar vacío para no cambiar)', - apiKeyOnceHint: 'La API Key solo se muestra una vez al crearla. Cópiela y guárdela ahora.', - apiKeyOnceSave: 'La API Key solo se muestra una vez. Guárdela ahora:', qpsLimit: 'Límite de QPS', tokenLimit: 'Límite de tokens', tokenUsed: 'Tokens usados', @@ -1153,23 +1149,23 @@ const message = { modelGroupGuide: 'Los grupos de modelos contienen los nombres de modelo expuestos por el gateway de IA. Configure los modelos upstream en el mapeo de modelos del pool de cuentas. auto es un nombre de modelo virtual y no debe añadirse al grupo.', modelGroupModelCount: '{0} modelos', - contentCompliance: 'Content Compliance', - contentAction: 'Action', - actionBlock: 'Block', - actionAuditOnly: 'Audit only', + contentCompliance: 'Cumplimiento de contenido', + contentAction: 'Acción', + actionBlock: 'Bloquear', + actionAuditOnly: 'Solo auditar', actionDropHistory: 'Eliminar historial', - severity: 'Severity', - severityHigh: 'High', - severityMedium: 'Medium', - severityLow: 'Low', - sensitiveWord: 'Sensitive word', - sensitiveGroup: 'Sensitive word group', - sensitiveWordCount: 'Words', - normalizedWord: 'Normalized word', - matchedWords: 'Matched words', - matchedGroups: 'Matched groups', - importResult: 'Imported {0}, duplicated {1}, invalid {2}', - auditLogs: 'Audit Logs', + severity: 'Gravedad', + severityHigh: 'Alta', + severityMedium: 'Media', + severityLow: 'Baja', + sensitiveWord: 'Palabra sensible', + sensitiveGroup: 'Grupo de palabras sensibles', + sensitiveWordCount: 'Palabras', + normalizedWord: 'Palabra normalizada', + matchedWords: 'Palabras coincidentes', + matchedGroups: 'Grupos coincidentes', + importResult: 'Importadas {0}, duplicadas {1}, no válidas {2}', + auditLogs: 'Registros de auditoría', smartRoute: 'Enrutamiento inteligente', smartRouteGuideTitle: 'Use model=auto en el cliente para entrar al enrutamiento inteligente', smartRouteGuideReady: @@ -1235,7 +1231,7 @@ const message = { latencyMs: 'Latencia(ms)', smartRouteSettingGuide: 'Después de activarlo, solo las solicitudes con model=auto usan enrutamiento inteligente. El grupo simple es para tareas de bajo costo; el complejo para análisis de código, arquitectura y diagnóstico.', - sampleLabelPlaceholder: 'simple / complex / high', + sampleLabelPlaceholder: 'simple / complejo / alto', sampleImportPlaceholder: 'Una muestra por línea', apiKeyCount: 'Cantidad', }, @@ -1494,14 +1490,14 @@ const message = { 'Por ejemplo: /mcp, tenga en cuenta que no debe superponerse con otros servidores', npxHelper: 'Adecuado para mcp iniciado con npx o binario', uvxHelper: 'Adecuado para mcp iniciado con uvx', - protocolVersion: 'Protocol Version', + protocolVersion: 'Versión del protocolo', protocolVersionHelper: - 'Only used by stateless Streamable HTTP to auto-initialize the downstream stdio MCP Server', + 'Solo se utiliza con Streamable HTTP sin estado para inicializar automáticamente el servidor MCP stdio descendente', gatewayArgsHelper: 'Los argumentos se añaden al comando supergateway. No se pueden cambiar los argumentos de transporte, puerto, ruta y protocolo gestionados por 1Panel', - testConnection: 'Test Connection', - connectionSuccess: 'Connection succeeded', - connectionFailed: 'Connection failed', + testConnection: 'Probar conexión', + connectionSuccess: 'Conexión correcta', + connectionFailed: 'Error de conexión', }, tensorRT: { llm: 'TensorRT LLM', @@ -1578,9 +1574,10 @@ const message = { last4Hour: 'Últimas 4 horas', lastHour: 'Última hora', last10Min: 'Últimos 10 minutos', + cleanLogscope: 'Tipo de limpieza', cleanLog: 'Limpiar logs', downLogHelper1: 'Esto descargará todos los logs del contenedor {0}. ¿Desea continuar?', - downLogHelper2: 'Esto descargará los últimos {0} logs del contenedor {0}. ¿Desea continuar?', + downLogHelper2: 'Esto descargará los últimos {1} logs del contenedor {0}. ¿Desea continuar?', cleanLogHelper: 'Esto requerirá reiniciar el contenedor y no se puede deshacer. ¿Desea continuar?', newName: 'Nuevo nombre', workingDir: 'Directorio de trabajo', @@ -1695,7 +1692,7 @@ const message = { 'Admite seleccionar múltiples imágenes para descargar, presione Enter después de ingresar cada imagen para continuar', imagePush: 'Subir', imagePushHelper: - 'Detected that this image has multiple tags. Please confirm that the image name used for pushing is: {0}', + 'Se detectó que esta imagen tiene varias etiquetas. Confirme que el nombre de imagen utilizado para enviarla es: {0}', imageDelete: 'Eliminar imagen', repoName: 'Repositorio de contenedores', imageName: 'Nombre de la imagen', @@ -1773,7 +1770,7 @@ const message = { containerNumber: 'Número de contenedores', containerStatus: 'Estado del contenedor', exited: 'Finalizado', - running: 'En ejecución', + running: 'En ejecución ({0}/{1})', composeDetailHelper: 'La composición fue creada externamente a 1Panel. Las operaciones de inicio y detención no son compatibles.', composeOperatorHelper: 'La operación {1} se realizará en {0}. ¿Desea continuar?', @@ -1790,7 +1787,8 @@ const message = { daemonJsonPathHelper: 'Asegúrese de que la ruta de configuración sea la misma que la especificada en docker.service.', mirrors: 'Mirrors del registro', - mirrorsHelper: '', + mirrorsHelper: + 'Utilice primero las URL de los mirrors del registro para las operaciones con imágenes. Déjelo vacío para desactivar los mirrors del registro.', mirrorsHelper2: 'Para más detalles, consulte la documentación oficial.', registries: 'Registros inseguros', ipv6Helper: @@ -1852,7 +1850,6 @@ const message = { stopHelper: 'Esta operación forzará la detención de la ejecución de la tarea actual. ¿Continuar?', log: 'Registros de respaldo', logHelper: 'Registro del sistema de copias de seguridad', - ogHelper1: '1. Registro del sistema de 1Panel', logHelper2: '2. Registro de inicio de sesión SSH del servidor', logHelper3: '3. Todos los registros del sitio web', containerCheckBox: 'En contenedor (no necesita introducir el comando del contenedor)', @@ -2318,6 +2315,7 @@ const message = { nodes: 'Nodo', commands: 'Comandos rápidos', opsReport: 'Informe de operaciones', + ops_report: 'Informe de operaciones', users: 'Gestión de usuarios', roles: 'Rol', auth: 'Autenticación de inicio de sesión', @@ -2508,42 +2506,43 @@ const message = { 'versión del archivo seleccionado', copyDir: 'Copiar', shareFile: 'Compartir archivo', - shareExpire: 'Expires in', - shareExpire1h: '1 hour', - shareExpire6h: '6 hours', - shareExpire24h: '24 hours', - shareExpire3d: '3 days', - shareExpire7d: '7 days', - sharePassword: 'Password', - sharePasswordPlaceholder: 'Leave empty for no password', - shareMaxDownloads: 'Max downloads', - shareMaxDownloadsHint: '0 means unlimited', - shareGenerate: 'Create link', - shareRegenerate: 'Share again', - shareClose: 'Close', + shareExpire: 'Caduca en', + shareExpire1h: '1 hora', + shareExpire6h: '6 horas', + shareExpire24h: '24 horas', + shareExpire3d: '3 días', + shareExpire7d: '7 días', + sharePassword: 'Contraseña', + sharePasswordPlaceholder: 'Déjelo vacío para no usar contraseña', + shareMaxDownloads: 'Descargas máximas', + shareMaxDownloadsHint: '0 significa sin límite', + shareGenerate: 'Crear enlace', + shareRegenerate: 'Volver a compartir', + shareClose: 'Cerrar', shareCancel: 'Cancelar uso compartido', shareCancelConfirm: '¿Seguro que quieres cancelar este uso compartido de archivo?', - shareDetail: 'Details', - shareCopyLink: 'Copy link', - shareLinkLabel: 'Share link', - shareQrCode: 'QR code', - shareQrDialogTitle: 'Share link QR code', - shareQrDialogHelper: 'Scan this QR code with your mobile device', - shareSaveImage: 'Save image', - shareOpenImage: 'Open image', - shareExtractFile: 'Extract file', - shareDownloadingHint: 'Preparing your file, download will begin shortly.', - shareInvalid: 'Invalid or expired share link', - shareDownloadFailed: 'Download failed, please try again later', - sharePasswordRequired: 'Password', - sharePasswordRequiredInput: 'Please enter the share password', - sharePasswordLengthHint: 'Share password length must be 4-256 characters', - shareDownloadPasswordTip: 'This link is password-protected. Enter the password before downloading.', + shareDetail: 'Detalles', + shareCopyLink: 'Copiar enlace', + shareLinkLabel: 'Enlace compartido', + shareQrCode: 'Código QR', + shareQrDialogTitle: 'Código QR del enlace compartido', + shareQrDialogHelper: 'Escanee este código QR con su dispositivo móvil', + shareSaveImage: 'Guardar imagen', + shareOpenImage: 'Abrir imagen', + shareExtractFile: 'Extraer archivo', + shareDownloadingHint: 'Preparando el archivo; la descarga comenzará en breve.', + shareInvalid: 'El enlace compartido no es válido o ha caducado', + shareDownloadFailed: 'La descarga falló; inténtelo de nuevo más tarde', + sharePasswordRequired: 'Contraseña', + sharePasswordRequiredInput: 'Introduzca la contraseña del enlace compartido', + sharePasswordLengthHint: 'La contraseña debe tener entre 4 y 256 caracteres', + shareDownloadPasswordTip: + 'Este enlace está protegido con contraseña. Introduzca la contraseña antes de descargar.', shareRiskAlert: - 'Shared links may carry security risks. Only share with trusted people and avoid exposing sensitive information.', + 'Los enlaces compartidos pueden conllevar riesgos de seguridad. Compártalos solo con personas de confianza y evite exponer información sensible.', sharePasswordSeparate: - 'A password is set. Share it securely. Recipients must add &password=... to the URL or use a client that can pass the password query parameter.', - shareExpiresAt: 'Expires at', + 'Se ha establecido una contraseña. Compártala de forma segura. Los destinatarios deben añadir &password=... a la URL o usar un cliente que admita el parámetro de consulta de contraseña.', + shareExpiresAt: 'Caduca el', paste: 'Pegar', changeOwner: 'Modificar usuario y grupo', containSub: 'Aplicar cambio de permisos recursivamente', @@ -3299,6 +3298,7 @@ const message = { app: 'La edición comercial permite ver información de servicio, monitoreo, etc. vía app móvil.', cluster: 'Actualizar a la edición comercial permite gestionar clústeres primario-réplica de MySQL/Postgres/Redis.', + vllm: 'Actualiza a la edición comercial para gestionar servicios vLLM en 1Panel con despliegue, configuración, operaciones del ciclo de vida y seguimiento de tareas centralizados.', 'model-downloader': 'Actualiza a la edición comercial para buscar, descargar y gestionar archivos de modelos locales desde HuggingFace, ModelScope o espejos compatibles, con directorios de modelos y tareas de descarga centralizados.', offLine: 'Sin conexión', @@ -3799,16 +3799,16 @@ const message = { strategy: 'Estrategia', strategyDown: 'Baja', strategyBackup: 'Backup', - ipHashBackupErr: 'IP hash does not support backup nodes', + ipHashBackupErr: 'IP hash no admite nodos de respaldo', failTimeout: 'Tiempo de espera de fallo', failTimeoutHelper: 'La duración de la ventana de tiempo para las comprobaciones de estado del servidor. Cuando el número acumulado de fallos alcanza el umbral dentro de este período, el servidor se eliminará temporalmente y se reintentará después de la misma duración. Por defecto 10 segundos', staticChangePHPHelper: 'Actualmente es un sitio estático, puedes cambiarlo a PHP', proxyCache: 'Caché de proxy inverso', cacheLimit: 'Límite de espacio de caché', - shareCahe: 'Tamaño de memoria para conteo de caché', + shareCache: 'Tamaño de memoria para conteo de caché', cacheExpire: 'Expiración de caché', - shareCaheHelper: '1M de memoria almacena aprox. 8000 objetos', + shareCacheHelper: '1M de memoria almacena aprox. 8000 objetos', cacheLimitHelper: 'Se eliminará caché antigua al superar el límite', cacheExpireJHelper: 'Caché eliminada al expirar si no se usa', realIP: 'IP real', @@ -4150,6 +4150,7 @@ const message = { }, runtime: { runtime: 'Runtime', + default: 'Predeterminado', workDir: 'Directorio de trabajo', localHelper: 'Para problemas de instalación en entorno local y uso en entorno sin conexión, consulte ', versionHelper: 'Versión de PHP, ej. v8.0', @@ -4459,8 +4460,10 @@ const message = { scorePanelHTTPSDisabled: 'HTTPS del panel deshabilitado', scoreSSHRootLogin: 'El acceso SSH como root está permitido', scoreSSHPasswordAuth: 'Autenticación por contraseña SSH habilitada sin autenticación por clave', + scoreSSLExpired: 'El certificado {0} ha caducado', scoreSSLHigh: 'El certificado {0} expira en {1} días', scoreSSLMedium: 'El certificado {0} expira en {1} días', + scoreWebsiteExpired: 'El sitio web {0} ha caducado', scoreWebsiteExpire: 'El sitio web {0} expira en {1} días', scoreWebsiteHTTP: '{0} no usa HTTPS', scoreWebsiteStopped: 'Estado anormal de {0}', @@ -4508,6 +4511,7 @@ const message = { panelLogin: 'Acceso al panel', sshLogin: 'Acceso SSH', failedRecord: 'Registros fallidos', + expired: 'Caducado', expiredDays: 'Expiró hace {0} días', remainingDays: '{0} · {1} días restantes', enabled: 'Habilitado', @@ -4781,9 +4785,9 @@ const message = { abnormalSites: 'Sitios anómalos', count5xxSource: 'Contabilizado por solicitudes 5xx', wafIntercept: 'Bloqueos WAF', - highRiskHit: 'Detecciones de alto riesgo', websiteMonitorDisabledOrNoData: 'El monitoreo web está deshabilitado o no hay datos disponibles', wafDisabledOrNoData: 'WAF deshabilitado o sin datos de bloqueos', + serviceEnabledButAbnormal: 'Habilitado, pero en estado anómalo', noWafData: 'Sin datos de bloqueos WAF', sourceIP: 'IP de origen', hitCount: 'Detecciones', @@ -4844,6 +4848,7 @@ const message = { successRate: 'Tasa de éxito', failedJobs: 'Tareas fallidas', recentRecoveryPoint: 'Último punto de recuperación', + disabledCronjobTasks: 'Tareas programadas deshabilitadas', remoteCoverage: 'Cobertura remota', recent7Days: 'Últimos 7 días', taskTypeStats: 'Estadísticas por tipo de tarea', @@ -4866,6 +4871,7 @@ const message = { cronjobReasonDisabled: '{0} tareas deshabilitadas', cronjobReasonLocalOnlyBackup: '{0} copias solo locales', cronjobReasonNormal: 'La ejecución de tareas y la cobertura de copias son normales', + riskLow: 'Riesgo bajo', viewFailedRecords: 'Ver tareas fallidas', viewCronjobTasks: 'Ver tareas programadas', checkBackupTasks: 'Comprobar tareas de copia', @@ -4966,6 +4972,15 @@ const message = { authManage: 'Gestión de autenticación', auth: { providerNavigation: 'Proveedores de autenticación', + defaultNode: 'Nodo predeterminado', + defaultNodePlaceholder: 'Selecciona un nodo', + defaultNodeHelper: 'Solo para usuarios nuevos.', + defaultNodeRequired: 'Selecciona un nodo predeterminado válido.', + nodesLoadFailed: + 'No se pudieron cargar los nodos. Reinténtalo antes de seleccionar el nodo predeterminado.', + nodeHandling: 'Gestión del nodo', + assignDefaultNode: 'Asignar nodo predeterminado: {node}', + keepExistingNode: 'Mantener los permisos de nodo existentes', providers: { ldap: 'AD/LDAP', passkey: 'Passkey', @@ -4993,7 +5008,425 @@ const message = { planned: 'Planificado', plannedTitle: 'Configuración de autenticación {0}', plannedDesc: 'Este proveedor de autenticación está planificado y aún no está disponible.', + oidc: { + accessMode: 'Modo de conexión', + accessModeDesc: 'Usar Discovery estándar siempre que el proveedor de identidad lo admita.', + actionCreate: 'Crear usuario', + actionKeepName: 'Mantener el nombre actual', + actionPending: 'Esperando resultado', + actionReject: 'Rechazar inicio de sesión', + actionUpdate: 'Actualizar información de identidad', + advanced: 'Configuración avanzada', + advancedDesc: + 'Mantener los valores predeterminados seguros a menos que el proveedor requiera una opción de compatibilidad.', + assignDefaultRole: 'Asignar rol predeterminado: {role}', + authorizationEndpoint: 'Authorization Endpoint', + authorizationEndpointInvalid: 'Ingrese un Authorization Endpoint válido.', + authorizationFlow: 'Flujo de autorización', + automatic: 'Automático', + automaticPolicy: 'Política de manejo automático', + automaticPolicyDesc: 'Estas reglas las aplica el backend y no son conmutadores de administrador.', + basic: 'Configuración básica', + basicDesc: + 'Seleccione el modo de proveedor, luego configure el cliente y la devolución de llamada.', + browserTest: 'Prueba de inicio de sesión en el navegador', + browserTestConflict: 'Identidad verificada, pero el nombre de usuario está en conflicto', + browserTestConflictHelper: + 'El nombre de usuario asignado pertenece a otra identidad y no se vinculará.', + browserTestExpired: 'La prueba del navegador expiró', + browserTestExpiredHelper: + 'Inicie una nueva prueba del navegador y complete la autorización antes de que caduque.', + browserTestFailed: 'La prueba del navegador falló', + browserTestFailedHelper: + 'No se pudo completar la vista previa de la identidad. Revise el error de backend localizado.', + browserTestIsolation: + 'Esto realiza un flujo de autorización real de ida y vuelta, pero no crea ni actualiza usuarios, no asigna roles ni crea una sesión de autenticación real.', + browserTestPopupBlocked: + 'Permite ventanas emergentes para este sitio, luego inicia la prueba del navegador nuevamente.', + browserTestPopupClosed: 'La ventana de autorización se cerró antes de completar la prueba.', + browserTestSuccess: 'Verificación del proveedor correcta', + browserTestSuccessHelper: + 'Se obtuvo una vista previa de la asignación de identidad sin cambiar usuarios o sesiones.', + browserTestTitle: 'Inicio de sesión de prueba del navegador OIDC', + browserTestWaiting: 'Esperando la autorización del proveedor', + browserTestWaitingHelper: + 'Inicio de sesión completo en la nueva ventana del navegador. Esta página se actualizará automáticamente.', + callbackCopied: 'URL de devolución de llamada OIDC copiada.', + callbackURL: 'URL de devolución de llamada', + callbackURLHelper: + 'Añada esta URL a las URL de retorno permitidas del cliente en el proveedor de identidad.', + cancelClearSecret: 'Cancelar limpieza', + clearSecret: 'Borrar secreto', + clearSecretConfirm: 'El Client Secret se eliminará solo después de guardar. ¿Continuar?', + clientAuthMethod: 'Método de autenticación del cliente', + clientAuthMethodHelper: + 'Seleccione el método de autenticación configurado para este cliente en el proveedor de identidad.', + clientAuthMethodRequired: 'Seleccione un método de autenticación del cliente.', + clientID: 'Client ID', + clientIDRequired: 'Ingrese el Client ID.', + clientSecret: 'Client Secret', + clockSkew: 'Tolerancia de tiempo del token', + clockSkewHelper: + 'Permite una pequeña diferencia horaria entre el proveedor de identidad y 1Panel. Mantenga el valor predeterminado de 60 segundos.', + clockSkewRequired: 'Ingrese la tolerancia de tiempo del token.', + compatibilityMode: 'Modo de compatibilidad', + compatibilityModeHelper: + 'Úselo solo para Discovery incompleto o puntos finales reescritos. La validación principal de OIDC permanece habilitada.', + configurationFailedHelper: + 'La prueba falló. La página solo muestra el error de backend localizado.', + configurationFailedTag: 'Prueba fallida', + configurationHighRiskPassed: + 'La configuración fue aprobada, pero contiene opciones de compatibilidad de alto riesgo.', + configurationHighRiskTag: 'Configuración de alto riesgo aprobada', + configurationNotTested: 'La configuración actual no se ha probado.', + configurationNotTestedTag: 'No probado', + configurationPassed: 'La configuración actual pasó las comprobaciones de seguridad y capacidad.', + configurationPassedTag: 'Prueba aprobada', + configurationStaleHelper: 'La configuración se modificó. Vuelva a probarla antes de guardar.', + configurationStaleTag: 'Resultado caducado', + configurationTestMeta: + 'Probado el {time}; completado en {duration} ms. Las respuestas sin procesar del proveedor no se almacenan.', + configurationTestResult: 'Resultado de la prueba de configuración', + configurationTestResultDesc: + 'Esto verifica Discovery y sus capacidades únicamente; no intercambia un código de autorización ni prueba el Client Secret. Utilice el inicio de sesión de prueba del navegador para la verificación de un extremo a otro.', + configurationTestSuccess: 'La prueba de configuración del OIDC fue exitosa.', + configurationTesting: 'Probando la configuración actual del OIDC…', + configurationTestingTag: 'Probando', + configureSecret: 'Configurar secreto', + conflictExistingRename: + 'Un subject vinculado devuelve un nombre de usuario nuevo que ya está ocupado', + conflictExistingRenameResult: + 'Mantenga el User.Name existente y permita que el usuario vinculado inicie sesión', + conflictLDAP: 'Usuario LDAP', + conflictLocal: 'Usuario local', + conflictNewAvailable: 'El subject nuevo y el nombre de usuario asignado están disponibles', + conflictNewAvailableResult: 'Cree un usuario empresarial y asigne el rol predeterminado', + conflictNone: 'Sin conflicto', + conflictOIDC: 'Otra identidad OIDC', + conflictOccupied: + 'El nombre de usuario asignado pertenece a un usuario local, LDAP u otra identidad OIDC', + conflictOccupiedResult: 'Rechazar la nueva identidad; nunca se vincule ni fusione automáticamente', + conflictType: 'Tipo de conflicto', + connectionSecurity: 'Seguridad de la conexión', + connectionSecurityDesc: + 'La política TLS se aplica a las solicitudes Discovery, Token, JWKS y UserInfo.', + connectionTest: 'Prueba de conexión y configuración', + connectionTestCompatibilityDesc: + 'Valide los endpoints personalizados y la política de seguridad del protocolo.', + connectionTestStandardDesc: + 'Los puntos finales y las capacidades se descubren automáticamente desde el Issuer.', + connectionTestTab: 'Prueba de conexión', + customCA: 'CA personalizada', + customCAHelper: + 'Se aplica solo a esta fuente de autenticación y nunca se escribe en los registros.', + customCARequired: 'Proporcione el certificado de la CA personalizada.', + defaultRole: 'Rol predeterminado', + defaultRoleHelper: + 'Se asigna solo al crear el usuario por primera vez; los siguientes inicios de sesión no cambian el rol.', + defaultRolePlaceholder: 'Seleccione un rol', + defaultRoleRequired: 'Seleccione un rol predeterminado válido.', + disableAfterSave: 'OIDC se deshabilitará después de guardar.', + disableConfirm: + 'Deshabilitar OIDC inmediatamente invalida el acceso de los usuarios de esta fuente. ¿Continuar?', + disableDiscardConfirm: + 'Desactivar OIDC es una acción de emergencia: solo cierra la entrada de inicio de sesión e inmediatamente invalida el acceso de los usuarios de esta fuente. Se descartarán otros cambios no guardados en esta página, incluidos los cambios Client Secret. ¿Continuar?', + disableTitle: 'Desactivar OIDC', + disabled: 'Desactivado', + discoveryAllowlist: 'Lista segura de Discovery', + enable: 'Activar', + enableAfterSave: 'OIDC se habilitará después de guardar correctamente.', + enabled: 'Activado', + endSessionEndpoint: 'End Session Endpoint', + endSessionEndpointHelper: + 'Se guarda para uso futuro; el cierre de sesión iniciado por el proveedor no está incluido en esta versión.', + endSessionEndpointInvalid: 'Ingrese un End Session Endpoint válido.', + endpointDiscoveryPlaceholder: 'Se muestra después de probar la conexión', + firstLogin: 'Primer inicio de sesión', + firstLoginPolicy: 'Cree un usuario empresarial local y asigne el rol predeterminado configurado.', + fixedAuthorizationCode: 'Authorization Code Flow', + fixedNoTokenPersistence: 'Token, Claims y verifier nunca persisten', + fixedSecurityPolicy: 'Siempre se aplican; no se requiere configuración', + fixedStateNonce: 'state y nonce por única vez', + fixedTokenValidation: 'Firma ID Token y validación de Claims', + highRiskSaveConfirm: + 'Esta configuración habilitada contiene opciones de compatibilidad de alto riesgo. Confirme que el entorno aislado los requiere.', + highRiskTitle: 'Configuración de OIDC de alto riesgo', + hs256Compatibility: 'HS256 (compatibilidad)', + hs256KeyHelper: + 'HS256 siempre usa el Client Secret de esta fuente y no admite una clave de firma separada.', + hs256Warning: + 'HS256 utiliza un secreto simétrico compartido para las firmas ID Token. Úselo solo cuando el proveedor no pueda usar un algoritmo asimétrico.', + identityBindingPolicy: + 'La identidad se fija en AuthSourceID + issuer + subject. La coincidencia por nombre de usuario nunca reclama otra cuenta.', + identityMissing: 'Identidad inactiva', + issuer: 'Issuer URL', + issuerHelper: + 'El valor iss de ID Token y Discovery issuer deben coincidir exactamente con este valor.', + issuerInvalid: 'Ingrese un valor válido HTTP o HTTPS Issuer URL sin consulta ni fragmento.', + issuerRequired: 'Ingrese el Issuer URL.', + jwksRotation: 'Rotación automática de JWKS', + jwksURI: 'JWKS URI', + jwksURIHelper: 'Requerido para la firma asimétrica cuando la fuente de clave es JWKS.', + jwksURIInvalid: 'Ingrese un JWKS URI válido para la fuente de clave de firma seleccionada.', + keepExistingRole: 'Mantener los roles y permisos locales existentes', + localSecurityData: 'Datos de seguridad locales', + localSecurityDataPolicy: 'Nunca sobrescriba roles, MFA, API Keys, Passkeys o permisos locales.', + localCredentialsManaged: + 'El nombre de usuario y la contraseña local se administran mediante OIDC y no se pueden editar aquí. Los roles, permisos, MFA, API Keys y Passkeys permanecen locales.', + localUserFields: 'Campos de usuario locales', + localUserFieldsDesc: + 'La primera versión asigna solo User.Name y no utiliza una expresión de asignación JSON.', + loginWith: 'Iniciar sesión con {provider}', + manualEndpoints: 'Endpoints personalizados', + manualEndpointsDesc: + 'Úselo solo cuando Discovery esté incompleto o una puerta de enlace ascendente reescriba los endpoints.', + mappingResult: 'Resultado de la asignación', + mode: 'Modo de conexión', + modeRequired: 'Seleccione un modo de conexión.', + nameClaim: 'Claim de nombre de usuario', + nameClaimHelper: 'Introduzca el campo que contiene el nombre de usuario, como preferred_username.', + nameClaimRequired: 'Introduzca el Claim del nombre de usuario.', + nameConflict: 'Política de conflicto de nombres', + panelURL: 'URL pública de 1Panel', + panelURLHTTPWarning: + 'HTTP no protege la respuesta de autorización. Úselo solo en un entorno privado aislado aceptado por el proveedor.', + panelURLHelper: + 'Introduzca la dirección que usan los usuarios para acceder a 1Panel. Se utiliza para generar la URL de retorno.', + panelURLInvalid: 'Ingrese un origen que contenga solo esquema, host y puerto opcional.', + panelURLRequired: 'Introduzca la URL pública de 1Panel.', + pkceDisabled: 'Deshabilitado (solo compatibilidad)', + pkceDisabledWarning: + 'Deshabilitar PKCE reduce la protección contra la interceptación de códigos de autorización.', + pkceHelper: 'Prefiere S256. El método de desafío plain nunca se ofrece.', + pkceS256: 'S256 (recomendado)', + plannedHandling: 'Manejo planificado', + privateNetworkIdP: 'IdP de red privada', + privateNetworkIdPHelper: + 'Permite explícitamente direcciones privadas; las direcciones de metadatos, loopback y link-local, las redirecciones y el rebinding DNS permanecen bloqueados.', + privateNetworkWarning: + 'El acceso a la red privada está habilitado para esta fuente de autenticación.', + protocolCompatibility: 'Compatibilidad de protocolo', + protocolCompatibilityDesc: 'La validación de la firma del ID Token no se puede deshabilitar.', + providerAndClient: 'Proveedor y cliente', + providerAndClientDesc: + 'El Client Secret solo se puede reemplazar o borrar y la página nunca lo devuelve.', + providerCapabilities: 'Capacidades del proveedor', + recentTestSuccess: 'Última prueba correcta: {0}', + recommended: 'Recomendado', + rejectPlain: 'plain rechazado', + replaceSecret: 'Reemplazar secreto', + requestAndClaims: 'Solicitudes y atributos', + requestAndClaimsDesc: + 'Configure los alcances de autorización, la información de usuario complementaria y los parámetros de solicitud.', + requestTimeout: 'Tiempo de espera de solicitud', + requestTimeoutRequired: 'Ingrese el tiempo de espera de solicitud.', + restore: 'Restaurar', + restored: 'Se restauró la última configuración de OIDC guardada.', + result: 'Resultado', + rolesLoadFailed: + 'No se pudieron cargar los roles. Vuelva a intentarlo antes de seleccionar el rol predeterminado.', + roleHandling: 'Gestión de roles', + scenario: 'Escenario', + scopes: 'Alcances de autorización', + scopesHelper: 'Debe incluir openid. Separe varios alcances con espacios.', + scopesRequired: 'Scopes debe incluir openid.', + seconds: 'segundos', + secretClearHelper: + 'Después de borrarlo, se requiere un Client Secret nuevo para volver a habilitar OIDC.', + secretConfigured: 'Configurado', + secretNotConfigured: 'No configurado', + secretPlaceholder: 'Ingrese un nuevo Client Secret', + secretReplaceHelper: + 'El nuevo secreto sustituirá el valor guardado al guardar. Actualice también el Client Secret en el Provider OIDC.', + secretRequiredHelper: 'Configure un Client Secret antes de habilitar OIDC.', + secretRequiredToEnable: 'Configure un Client Secret antes de habilitar OIDC.', + secretSavedHelper: 'Se almacena cifrado. Deje el campo vacío para conservar el secreto actual.', + secretWaiting: 'Esperando entrada', + secretWillClear: 'Se borrará', + secretWillReplace: 'Será reemplazado', + signingAlgorithm: 'Algoritmo de firma ID Token', + signingAlgorithmHelper: + 'Solo están disponibles los algoritmos de la lista de seguridad de backend.', + signingKey: 'Clave de firma', + signingKeyClientSecret: 'Client Secret (solo HS256)', + signingKeyJWKS: 'JWKS URI con rotación automática', + signingKeySource: 'Fuente de clave de firma', + signingKeySourceHelper: 'Prefiere JWKS. Una clave pública estática no puede rotar automáticamente.', + signingKeyStatic: 'Clave pública JWK o PEM estática', + standardDiscovery: 'OIDC Discovery estándar', + standardDiscoveryDesc: + '1Panel descubre los endpoints y las capacidades, pero no almacena el documento sin procesar.', + standardMode: 'Modo estándar', + standardModeHelper: + 'Descubra puntos finales, capacidades de firma y compatibilidad con PKCE del Issuer.', + standardProtocolPolicy: 'Política de protocolo estándar', + standardProtocolPolicyDesc: + 'Las capacidades de firma se negocian automáticamente; aquí no se ingresa ninguna clave de firma.', + staticSigningKey: 'Clave pública de firma estática', + staticSigningKeyHelper: + 'Solo se acepta material de clave pública. Rótela manualmente cuando cambie la clave del proveedor.', + staticSigningKeyPlaceholder: 'Pegue una clave pública JWK, JWKS JSON o PEM', + staticSigningKeyRequired: 'Proporcione la clave pública de firma estática.', + staticSigningKeyWarning: + 'Una clave de firma estática no puede rotar automáticamente; actualícela antes de que el proveedor rote sus claves.', + settingLoadFailed: 'La configuración del OIDC no se pudo cargar', + settingLoadFailedHelper: + 'El formulario está bloqueado para evitar guardar una configuración predeterminada vacía sobre la configuración actual. Vuelva a intentarlo después de que se recupere la conexión.', + subsequentLogin: 'Inicio de sesión posterior', + subsequentLoginPolicy: + 'Busque el vínculo por subject y actualice User.Name solo cuando el nombre nuevo esté disponible.', + testBeforeBrowserTest: + 'Pruebe la configuración actual antes de iniciar la prueba de inicio de sesión en el navegador.', + testBeforeEnable: 'Prueba la configuración actual antes de guardar los cambios de configuración.', + testConfiguration: 'Probar configuración', + testDiscovery: 'Probar Discovery', + tlsCustomCA: 'HTTPS · Certificado CA personalizado', + tlsPrivateHTTP: 'HTTP · Solo red privada (peligroso)', + tlsPrivateHTTPWarning: + 'HTTP no proporciona cifrado de transporte y está restringido a objetivos privados permitidos explícitamente.', + tlsSkipVerify: 'HTTPS · Omitir verificación de certificado (peligroso)', + tlsSystem: 'HTTPS · Verificación del certificado del sistema (recomendado)', + tokenEndpoint: 'Token Endpoint', + tokenEndpointInvalid: 'Ingrese un Token Endpoint válido.', + transportSecurity: 'Seguridad en el transporte', + transportSecurityHelper: + 'Se recomienda HTTPS. El HTTP privado también requiere permitir explícitamente el acceso a la red privada.', + unsavedChanges: 'Hay cambios de OIDC sin guardar.', + usedClaim: 'Claim usado', + userInfoEndpoint: 'UserInfo Endpoint', + userInfoEndpointHelper: + 'Si falta el campo de nombre de usuario, el sistema lo obtiene de este endpoint. Déjelo vacío para omitir el complemento.', + userInfoEndpointInvalid: 'Ingrese un UserInfo Endpoint válido.', + userMapping: 'Configuración de usuarios', + userMappingDesc: + 'Configure la asignación del nombre de usuario OIDC y el nodo y rol predeterminados usados al crear un usuario en el primer inicio de sesión.', + }, + saml2: { + actionCreate: 'Crear usuario', + actionPending: 'Esperando resultado', + actionReject: 'Rechazar inicio de sesión', + actionReuse: 'Usar usuario vinculado', + assignDefaultRole: 'Asignar rol predeterminado: {role}', + basic: 'Configuración básica', + basicDesc: + 'Configure las opciones comunes requeridas por la mayoría de los proveedores SAML2 estándar.', + browserTest: 'Probar inicio de sesión', + browserTestConflict: 'Identidad verificada, pero el nombre de usuario está en conflicto', + browserTestConflictHelper: + 'El nombre de usuario asignado pertenece a otra identidad y no se vinculará.', + browserTestExpired: 'La prueba del navegador expiró', + browserTestExpiredHelper: + 'Inicie una nueva prueba del navegador y complete la autorización antes de que caduque.', + browserTestFailed: 'La prueba del navegador falló', + browserTestFailedHelper: + 'No se pudo completar la vista previa de la identidad. Revise el error de backend localizado.', + browserTestIsolation: + 'Esto realiza un flujo de autorización real de ida y vuelta, pero no crea ni actualiza usuarios, no asigna roles ni crea una sesión de autenticación real.', + browserTestPopupBlocked: + 'Permite ventanas emergentes para este sitio, luego inicia la prueba del navegador nuevamente.', + browserTestPopupClosed: 'La ventana de autorización se cerró antes de completar la prueba.', + browserTestSuccess: 'Verificación del proveedor correcta', + browserTestSuccessHelper: + 'Se obtuvo una vista previa de la asignación de identidad sin cambiar usuarios o sesiones.', + browserTestTitle: 'Inicio de sesión de prueba del navegador SAML2', + browserTestWaiting: 'Esperando la autorización del proveedor', + browserTestWaitingHelper: + 'Inicio de sesión completo en la nueva ventana del navegador. Esta página se actualizará automáticamente.', + certificateFileInvalid: 'Seleccione un archivo de certificado PEM, CRT o CER válido.', + configured: 'Configurado', + configurationFailedHelper: + 'La prueba falló. La página solo muestra el error de backend localizado.', + configurationNotTested: 'La configuración actual no se ha probado.', + configurationPassed: 'La configuración actual pasó las comprobaciones de seguridad y capacidad.', + configurationStaleHelper: + 'Se cambiaron las configuraciones sensibles a la autenticación. Pruebe el borrador actual nuevamente.', + configurationTestSuccess: 'La prueba de configuración del SAML2 fue exitosa.', + configurationTesting: 'Probando la configuración actual del SAML2…', + conflictLDAP: 'Usuario LDAP', + conflictLocal: 'Usuario local', + conflictNone: 'Sin conflicto', + conflictOIDC: 'Otra identidad OIDC', + conflictSAML2: 'Otra identidad SAML2', + conflictType: 'Tipo de conflicto', + credentialFileReadFailed: 'No se pudo leer el archivo de credenciales.', + credentialFileTooLarge: 'Los archivos de credenciales no deben superar los 256 KiB.', + credentialsRequired: 'Configure la clave privada y el certificado del SP.', + defaultRole: 'Rol del nuevo usuario', + defaultRoleHelper: + 'Se asigna solo en la primera creación; los inicios posteriores conservan roles, MFA y permisos locales.', + defaultRolePlaceholder: 'Seleccione un rol', + defaultRoleRequired: 'Seleccione un rol predeterminado válido.', + disableConfirm: + 'Desactivar SAML2 rechaza inmediatamente los nuevos inicios de sesión e invalida sus sesiones de usuario. ¿Continuar?', + disableDiscardConfirm: + 'Desactivar SAML2 descarta otros cambios no guardados de esta página e invalida de inmediato sus sesiones de usuario. ¿Continuar?', + disableTitle: 'Desactivar SAML2', + disabled: 'Desactivado', + enable: 'Activar', + enabled: 'Activado', + idpMetadata: 'Metadatos del IdP', + idpMetadataDesc: 'Introduzca una URL o pegue el XML. Si existen ambos, la URL tiene prioridad.', + keepExistingRole: 'Mantener los roles y permisos locales existentes', + loginWith: 'Iniciar sesión con {provider}', + mappingResult: 'Resultado de la asignación', + metadataRequired: 'Introduzca la URL o el XML de metadatos del IdP.', + metadataURLHelper: 'El backend descarga y valida los metadatos durante la prueba y el guardado.', + metadataURLInvalid: 'Introduzca una URL HTTPS de metadatos válida, sin credenciales ni fragmento.', + metadataURLRecommended: 'URL de metadatos (recomendada)', + metadataXML: 'XML de metadatos', + metadataXMLHelper: 'Úselo cuando el IdP no exponga una URL de metadatos accesible.', + metadataXMLInvalid: 'Introduzca un XML de metadatos EntityDescriptor válido.', + metadataXMLPlaceholder: 'Pegue ...', + nameAttribute: 'Atributo de nombre de usuario', + nameAttributeHelper: + 'Lee este atributo de la aserción SAML verificada y lo asigna al nombre de usuario de 1Panel.', + nameAttributePlaceholder: 'Por ejemplo: uid, username o account', + nameAttributeRequired: 'Introduzca el atributo de nombre de usuario.', + notConfigured: 'Sin configurar', + or: 'o', + pageDesc: + 'Conecte el SSO empresarial mediante metadatos del IdP con las opciones comunes en una sola página.', + plannedHandling: 'Manejo planificado', + privateKeyFileInvalid: 'Seleccione un archivo de clave privada PEM válido.', + recentTestSuccess: 'Última prueba correcta: {0}', + restore: 'Restaurar', + restored: 'Se restauró la última configuración de SAML2 guardada.', + roleHandling: 'Gestión de roles', + rolesLoadFailed: + 'No se pudieron cargar los roles. Vuelva a intentarlo antes de seleccionar el rol predeterminado.', + selectFile: 'Seleccionar archivo', + serviceStatus: 'Estado del servicio', + serviceStatusDesc: 'La configuración actual debe superar una prueba antes de activar SAML2.', + settingLoadFailed: 'La configuración del SAML2 no se pudo cargar', + settingLoadFailedHelper: + 'El formulario está bloqueado para evitar guardar una configuración predeterminada vacía sobre la configuración actual. Vuelva a intentarlo después de que se recupere la conexión.', + spCertificate: 'Certificado del SP', + spCertificateHelper: + 'Se publica en los metadatos del SP para que el IdP pueda verificar las solicitudes de inicio y cierre de sesión.', + spCredentials: 'Clave privada y certificado del SP', + spCredentialsDesc: + 'Se usan para firmar mensajes de inicio y cierre de sesión. El backend fija la política de firma y validación.', + spPrivateKey: 'Clave privada del SP', + spPrivateKeyHelper: + 'Se usa para firmar AuthnRequest y mensajes de cierre de sesión. Se cifra en reposo y nunca se muestra.', + syncLogout: 'Cierre de sesión sincronizado', + syncLogoutHelper: + 'Cerrar sesión en 1Panel o en el proveedor de identidad también cierra la sesión del otro lado.', + testBeforeBrowserTest: + 'Pruebe la configuración actual antes de iniciar la prueba de inicio de sesión en el navegador.', + testBeforeEnable: 'Prueba la configuración actual antes de habilitar o guardar cambios sensibles.', + testConfiguration: 'Probar configuración', + unsavedChanges: 'Hay cambios de SAML2 sin guardar.', + usedAttribute: 'Mapeo de nombre de usuario', + usersAndRoles: 'Usuarios y roles', + usersAndRolesDesc: + 'Configure la asignación del nombre de usuario del panel y el nodo y rol predeterminados usados al crear un usuario en el primer inicio de sesión.', + }, ldap: { + basic: 'Configuración básica', + loginTitle: 'Inicio de sesión LDAP', + loginWith: 'Iniciar sesión con LDAP', + backToLocalLogin: 'Volver al inicio de sesión del panel', enable: 'Habilitar', enabled: 'Habilitado', disabled: 'Deshabilitado', @@ -5215,6 +5648,7 @@ const message = { deleteConfirm: '¿Eliminar este registro y archivo de exportación?', }, waf: { + WAF: 'WAF', name: 'WAF', blackWhite: 'Lista Blanca y Negra', globalSetting: 'Configuración Global', @@ -5443,7 +5877,7 @@ const message = { attackCountNum: 'Cantidad', percent: 'Porcentaje', addblackUrlHelper: '¿Añadir URL {0} a la blacklist?', - rce: 'Remote Code Execution', + rce: 'Ejecución remota de código', software: 'Software', cveHelper: 'Incluye vulnerabilidades de software y frameworks comunes', vulnCheck: 'Reglas adicionales', @@ -5452,7 +5886,7 @@ const message = { ua: 'Acceso no autorizado', id: 'Divulgación de información', aa: 'Bypass de autenticación', - dr: 'Directory Traversal', + dr: 'Recorrido de directorios', xxe: 'Vulnerabilidad XXE', suid: 'Vulnerabilidad de serialización', dos: 'Denegación de servicio', @@ -5826,6 +6260,14 @@ const message = { 'Se limpiarán todos los paquetes de actualización de versiones anteriores. ¿Continuar?', nodeUpgradeOfflinePackageHelper: 'En entornos sin conexión, los nodos con arquitecturas diferentes deben subir primero el paquete de actualización correspondiente.', + healthCheck: 'Comprobación de estado', + healthCheckFrequency: 'Frecuencia de comprobación', + healthCheckFrequencyHelper: + 'Comprueba periódicamente el estado de los nodos backend. Introduzca 0 para deshabilitar las comprobaciones.', + healthCheckFrequencyLimit: 'La frecuencia no puede superar un día y debe ser un número entero no negativo.', + loadFailedNodeResources: 'Cargar recursos de nodos con error', + loadFailedNodeResourcesHelper: + 'Al abrir la lista de nodos, carga también la información de recursos de los nodos con error.', nodeUnhealthy: 'Estado del nodo anómalo', deletedNode: 'El nodo eliminado {0} no soporta operaciones de actualización.', nodeUnhealthyHelper: @@ -5915,6 +6357,8 @@ const message = { offlineHelper: 'Usado cuando el nodo está en un entorno sin conexión', appUpgrade: 'Actualización de la aplicación', appUpgradeHelper: 'Hay {0} aplicaciones que necesitan ser actualizadas', + dashboardSetting: 'Configuración del resumen', + keepOneDashboardComponent: 'Mantenga al menos una sección del resumen', addPanel: 'Añadir panel', addPanelHelper: 'Tras añadir el panel, podrás acceder rápidamente en [Resumen - Paneles].', panel: 'Panel 1Panel', @@ -6317,35 +6761,36 @@ const message = { cpu: 'CPU', memory: 'Memoria', disk: 'Disco', - overview: 'Overview', - kvmUnavailable: 'No available KVM hardware virtualization capability was detected.', - kvmCheckCpu: 'Confirm that the host CPU supports Intel VT-x or AMD-V virtualization.', - kvmCheckBios: 'Enable virtualization options in BIOS/UEFI.', - kvmCheckModule: 'Confirm that the kvm, kvm_intel, or kvm_amd kernel module is loaded correctly.', + overview: 'Resumen', + kvmUnavailable: 'No se detectó ninguna capacidad de virtualización KVM disponible.', + kvmCheckCpu: 'Confirme que la CPU del host admite virtualización Intel VT-x o AMD-V.', + kvmCheckBios: 'Active las opciones de virtualización en BIOS/UEFI.', + kvmCheckModule: 'Confirme que el módulo del kernel kvm, kvm_intel o kvm_amd esté cargado correctamente.', kvmCheckDevice: - 'Confirm that /dev/kvm exists and the current environment is not a container or cloud host without KVM support.', - abnormal: 'Abnormal', - resourceOverview: 'Resource Overview', - cpuAllocated: 'CPU Allocated', - memoryAllocated: 'Memory Allocated', - storageUsed: 'Storage Used', - riskReminder: 'Risk Reminders', - noRisk: 'No risks', - runtimeHealth: 'Runtime Health', - runtimeAbnormal: 'VM runtime is abnormal', - noDependency: 'No dependency check data', - storageOverview: 'Storage Overview', - totalAllocated: 'Calculated by total VM configuration', - runningAllocated: 'Running allocation: {0}', - storageAvailable: 'Available: {0}', - inProgress: 'In progress', - needAttention: 'Needs attention', + 'Confirme que /dev/kvm existe y que el entorno actual no sea un contenedor o un host en la nube sin compatibilidad con KVM.', + abnormal: 'Anormal', + resourceOverview: 'Resumen de recursos', + cpuAllocated: 'CPU asignada', + memoryAllocated: 'Memoria asignada', + storageUsed: 'Almacenamiento usado', + riskReminder: 'Avisos de riesgo', + noRisk: 'Sin riesgos', + runtimeHealth: 'Estado del entorno de ejecución', + runtimeAbnormal: 'El entorno de ejecución de la VM presenta anomalías', + noDependency: 'No hay datos de comprobación de dependencias', + storageOverview: 'Resumen del almacenamiento', + totalAllocated: 'Calculado a partir de la configuración total de las VM', + runningAllocated: 'Asignación en ejecución: {0}', + storageAvailable: 'Disponible: {0}', + inProgress: 'En curso', + needAttention: 'Requiere atención', normal: 'Normal', - environmentRisk: 'The VM runtime is not ready. Fix dependencies or virtualization services.', - storageRisk: 'Storage pool {0} usage has reached {1}%.', - abnormalRisk: '{0} VMs are in an abnormal state.', - pausedRisk: '{0} VMs are paused.', - memoryRisk: 'VM memory allocation has reached {0}%.', + environmentRisk: + 'El entorno de ejecución de VM no está listo. Corrija las dependencias o los servicios de virtualización.', + storageRisk: 'El uso del pool de almacenamiento {0} ha alcanzado el {1}%.', + abnormalRisk: '{0} VM se encuentran en un estado anormal.', + pausedRisk: '{0} VM están pausadas.', + memoryRisk: 'La asignación de memoria de las VM ha alcanzado el {0}%.', cpuLimitHelper: 'CPU disponible actualmente: {0} núcleos', cpuLimitExceeded: 'La CPU supera el límite. Máximo disponible actual: {0} núcleos.', memoryLimitHelper: 'Memoria actualmente asignable: {0} (el host debe reservar {1} de memoria)', @@ -6354,11 +6799,11 @@ const message = { storageLimitExceeded: 'La capacidad del disco supera el límite. Máximo disponible actual: {0}.', iso: 'ISO', createFromTemplate: 'Crear desde plantilla', - template: 'Template', - templateName: 'Template Name', - convertToTemplate: 'Convert to Template', - sourceVM: 'Source VM', - templateSize: 'Template Size', + template: 'Plantilla', + templateName: 'Nombre de la plantilla', + convertToTemplate: 'Convertir en plantilla', + sourceVM: 'VM de origen', + templateSize: 'Tamaño de la plantilla', deleteTemplateConfirm: 'Eliminar plantilla {0}. Esta operación no se puede revertir. ¿Continuar?', orphanClean: 'Limpieza de datos huérfanos', orphanScan: 'Volver a escanear', @@ -6402,21 +6847,21 @@ const message = { available: 'Disponible', vmCount: 'VM vinculadas', usedIPs: 'IP usadas', - monitor: 'Monitor', - monitorNotReady: 'The virtual machine is not running. Monitoring data is unavailable.', - monitorLoadFailed: 'Failed to get VM monitoring data.', - monitorLoadFailedWithReason: 'Failed to get VM monitoring data: {0}', - rename: 'Rename', + monitor: 'Supervisión', + monitorNotReady: 'La máquina virtual no está en ejecución. Los datos de supervisión no están disponibles.', + monitorLoadFailed: 'No se pudieron obtener los datos de supervisión de la VM.', + monitorLoadFailedWithReason: 'No se pudieron obtener los datos de supervisión de la VM: {0}', + rename: 'Renombrar', newName: 'Nuevo nombre', - renameHelper: 'Enter a new VM name. The VM must be shut down before renaming.', - renameConfirm: 'Rename virtual machine [{0}] to [{1}]?', - renameRunningHelper: 'Shut down the virtual machine before renaming it.', - cpuUsage: 'CPU Usage', - memoryUsage: 'Memory Usage', - diskIO: 'Disk IO', - networkIO: 'Network IO', - diskReadWrite: 'Disk Read / Write', - networkRxTx: 'Network RX / TX', + renameHelper: 'Introduzca un nuevo nombre. La VM debe estar apagada antes de renombrarla.', + renameConfirm: '¿Renombrar la máquina virtual [{0}] como [{1}]?', + renameRunningHelper: 'Apague la máquina virtual antes de renombrarla.', + cpuUsage: 'Uso de CPU', + memoryUsage: 'Uso de memoria', + diskIO: 'E/S de disco', + networkIO: 'E/S de red', + diskReadWrite: 'Lectura/escritura de disco', + networkRxTx: 'Recepción/transmisión de red', rx: 'RX', tx: 'TX', console: 'Consola', @@ -6426,16 +6871,18 @@ const message = { consoleConnectFailed: 'No se pudo conectar a la consola VNC. Compruebe el servicio proxy de consola.', consoleCredentialsRequired: 'La consola VNC requiere credenciales. Compruebe la configuración del proxy backend.', - snapshot: 'Snapshot', - createSnapshot: 'Create Snapshot', - recoverSnapshot: 'Recover Snapshot', + snapshot: 'Instantánea', + createSnapshot: 'Crear instantánea', + recoverSnapshot: 'Restaurar instantánea', snapshotSize: 'Uso', - currentSnapshot: 'Current', - snapshotEmpty: 'No snapshots', + currentSnapshot: 'Actual', + snapshotEmpty: 'No hay instantáneas', snapshotHelper: - 'A snapshot saves the current VM state as a restore point. Subsequent data changes are recorded in a delta file without changing the original disk. Restoring a snapshot returns the VM to that point in time.', + 'Una instantánea guarda el estado actual de la VM como punto de restauración. Los cambios posteriores se registran en un archivo delta sin modificar el disco original. Al restaurarla, la VM vuelve a ese momento.', + snapshotOperationHelper: + 'La instantánea actual no se puede eliminar. Las instantáneas solo se pueden restaurar cuando la máquina virtual está apagada.', snapshotRecoverConfirm: - 'Recover virtual machine [{1}] to snapshot [{0}]? The VM disk will be restored to the snapshot state.', + '¿Restaurar la máquina virtual [{1}] a la instantánea [{0}]? El disco de la VM volverá al estado de la instantánea.', interface: 'Interfaz de red', device: 'Dispositivo', path: 'Ruta', diff --git a/frontend/src/lang/modules/fa.ts b/frontend/src/lang/modules/fa.ts index f6978bac1..3b47058ec 100644 --- a/frontend/src/lang/modules/fa.ts +++ b/frontend/src/lang/modules/fa.ts @@ -14,6 +14,7 @@ const message = { next: 'بعدی', create: 'ایجاد', add: 'افزودن', + select: 'انتخاب', save: 'ذخیره', set: 'تنظیمات', sync: 'همگام‌سازی', @@ -90,6 +91,7 @@ const message = { visit: 'باز کردن', migrate: 'مهاجرت', tip: 'نکته', + reconnect: 'اتصال مجدد', }, operate: { start: 'شروع', @@ -115,6 +117,8 @@ const message = { total: 'مجموع {0}', name: 'نام', type: 'نوع', + card: 'کارت', + table: 'جدول', status: 'وضعیت', statusSuccess: 'موفق', statusFailed: 'ناموفق', @@ -163,6 +167,7 @@ const message = { deleteSuccess: 'حذف با موفقیت انجام شد', loginSuccess: 'ورود با موفقیت انجام شد', operationSuccess: 'عملیات با موفقیت انجام شد', + operationFailed: 'عملیات ناموفق بود', copySuccess: 'کپی با موفقیت انجام شد', notSupportOperation: 'این عملیات پشتیبانی نمی‌شود', requestTimeout: 'زمان درخواست به پایان رسید، بعداً تلاش کنید', @@ -204,6 +209,7 @@ const message = { username: 'نام کاربری', password: 'رمز عبور', passkey: 'ورود با کلید عبور', + otherLoginMethods: 'سایر روش‌های ورود', welcome: 'خوش آمدید. با نام کاربری و رمز عبور خود وارد شوید.', errorAuthInfo: 'نام کاربری یا رمز عبور اشتباه است، دوباره تلاش کنید.', errorMfaInfo: 'اطلاعات احراز هویت نامعتبر است، دوباره تلاش کنید.', @@ -283,6 +289,9 @@ const message = { authBasicPassword: 'پشتیبانی از حروف، اعداد و کاراکترهای ویژه رایج، طول ۱-۷۲', length128Err: 'طول نمی‌تواند از ۱۲۸ کاراکتر بیشتر باشد', maxLength: 'طول نمی‌تواند از {0} کاراکتر بیشتر باشد', + vmName: 'از حروف انگلیسی، اعداد، "."، "-" و "_" پشتیبانی می‌کند؛ طول ۱ تا ۶۴؛ باید با حرف یا عدد شروع شود.', + vmNetwork: + 'از حروف انگلیسی، اعداد، "."، ":"، "-" و "_" پشتیبانی می‌کند؛ طول ۱ تا ۶۴؛ باید با حرف یا عدد شروع شود.', alias: 'پشتیبانی از حروف انگلیسی، اعداد، - و _، طول ۱-۱۲۸، و نمی‌تواند با -_ شروع یا پایان یابد.', }, res: { @@ -466,7 +475,7 @@ const message = { cpuSteal: 'ربایش', cpuTop: '۵ فرآیند برتر بر اساس مصرف CPU', memTop: '۵ فرآیند برتر بر اساس مصرف حافظه', - loadAverage: 'میانگین بار در دقیقه آخر | میانگین بار در {n} دقیقه گذشته', + loadAverage: 'میانگین بار در دقیقه آخر | میانگین بار در {0} دقیقه گذشته', load: 'بار', mount: 'نقطه اتصال', fileSystem: 'سیستم فایل', @@ -502,6 +511,7 @@ const message = { deleteBackupHelper: 'همزمان پشتیبان‌های پایگاه داده را حذف کنید', delete: 'عملیات حذف قابل بازگشت نیست، لطفاً عبارت "', deleteHelper: '" را برای حذف این پایگاه داده وارد کنید', + deleteUserHelper: '" را برای حذف این کاربر وارد کنید', userBoundDatabases: 'به پایگاه‌های داده زیر دسترسی دارد:', noMysql: 'سرویس پایگاه داده (MySQL یا MariaDB)', noPostgresql: 'سرویس پایگاه داده PostgreSQL', @@ -540,6 +550,7 @@ const message = { 'این پورت، پورت نمایش داده شده کانتینر است. باید تغییرات را جداگانه ذخیره و کانتینر را مجدداً راه‌اندازی کنید!', loadFromRemote: 'همگام‌سازی از سرور', userBind: 'اتصال کاربر', + noUserBind: 'بدون اتصال', userAuthorization: 'مجوز کاربر', noUserAuthorization: 'بدون اعطای مجوز', authorizedDatabaseCount: '{0} پایگاه داده مجاز', @@ -803,16 +814,12 @@ const message = { roleMarkdownDescriptions: { 'AGENTS.md': [ 'دستورالعمل‌های عملیاتی برای عامل و نحوه استفاده از حافظه.', - 'در ابتدای هر جلسه بارگذاری می‌شود.', 'مکان خوب برای قوانین، اولویت‌ها و جزئیات "نحوه رفتار".', ], - 'SOUL.md': ['شخصیت، لحن و مرزها.', 'هر جلسه بارگذاری می‌شود.'], - 'USER.md': ['کاربر کیست و چگونه خطاب شود.', 'هر جلسه بارگذاری می‌شود.'], - 'IDENTITY.md': ['نام، حالت و ایموجی عامل.', 'در طول مراسم بوت‌استرپ ایجاد یا به‌روزرسانی می‌شود.'], - 'TOOLS.md': [ - 'یادداشت‌هایی درباره ابزارها و قراردادهای محلی شما.', - 'کنترل در دسترس بودن ابزار را ندارد؛ فقط راهنما است.', - ], + 'SOUL.md': ['شخصیت، لحن و مرزها.'], + 'USER.md': ['کاربر کیست و چگونه خطاب شود.'], + 'IDENTITY.md': ['نام، حالت و ایموجی عامل.'], + 'TOOLS.md': ['یادداشت‌هایی درباره ابزارها و قراردادهای محلی شما.'], 'HEARTBEAT.md': [ 'لیست کوچک اختیاری برای اجرای ضربان قلب.', 'برای جلوگیری از سوختن توکن، کوتاه نگه دارید.', @@ -821,11 +828,7 @@ const message = { 'لیست شروع اختیاری که هنگام راه‌اندازی مجدد دروازه و فعال بودن هوک‌های داخلی اجرا می‌شود.', 'کوتاه نگه دارید؛ برای ارسال‌های خروجی از ابزار پیام استفاده کنید.', ], - 'BOOTSTRAP.md': [ - 'مراسم یک‌باره اولین اجرا.', - 'فقط برای یک فضای کار کاملاً جدید ایجاد می‌شود.', - 'پس از اتمام مراسم، آن را حذف کنید.', - ], + 'BOOTSTRAP.md': ['مراسم یک‌باره اولین اجرا.', 'فقط برای یک فضای کار کاملاً جدید ایجاد می‌شود.'], }, duplicateBinding: 'ترکیب کانال و شناسه حساب باید یکتا باشد', accountIdOptional: 'شناسه حساب (اختیاری)', @@ -905,6 +908,8 @@ const message = { scanConnectHelper: 'برای شروع کار ورود با QR کلیک کنید. کد QR در لاگ وظیفه ظاهر می‌شود و پس از اسکان موفق، کانتینر به طور خودکار مجدداً راه‌اندازی می‌شود.', channelAutoRestartHelper: 'ذخیره به طور خودکار کانتینر را مجدداً راه‌اندازی می‌کند تا تغییرات اعمال شوند.', + dashboardAuthAutoRebuildHelper: + 'ذخیره نام کاربری یا رمز عبور، کانتینر را به‌طور خودکار بازسازی می‌کند تا تغییرات اعمال شوند.', channelDeleteConfirm: 'پیکربندی کانال {0} حذف شود؟', apiTypeBaseURLHelper: 'این نوع درخواست‌ها را به {0} ارسال می‌کند. Base URL پیشنهادی: {1}', apiTypeBaseURLMismatch: 'Base URL فعلی شبیه مسیر {0} است، اما {1} انتخاب شده است. URL پیشنهادی: {2}', @@ -1209,13 +1214,11 @@ const message = { latencyMs: 'تاخیر(ms)', smartRouteSettingGuide: 'پس از فعال‌سازی، فقط درخواست‌های model=auto مسیریابی هوشمند را فعال می‌کنند. گروه ساده برای وظایف کم‌هزینه و گروه پیچیده برای تحلیل کد، طراحی معماری و عیب‌یابی است.', - sampleLabelPlaceholder: 'simple / complex / high', + sampleLabelPlaceholder: 'ساده / پیچیده / بالا', sampleImportPlaceholder: 'هر خط یک نمونه', }, skillsHub: { title: 'مرکز مهارت', - skillList: 'لیست مهارت', - serverTab: 'سرور', upload: 'بارگذاری مهارت', importSkill: 'واردات مهارت', repositoryAddress: 'آدرس مخزن', @@ -1228,6 +1231,13 @@ const message = { importSuccess: 'مهارت با موفقیت وارد شد و در انتظار بررسی است.', source: 'منبع', applicableAgent: 'عامل قابل اجرا', + overview: 'نمای کلی', + versionHistory: 'تاریخچه نسخه', + publishedAt: 'زمان انتشار', + versionMarker: 'نشان', + currentVersion: 'فعلی', + latestVersion: 'آخرین نسخه', + latestPublished: 'آخرین نسخه منتشرشده', riskLevel: 'سطح ریسک', riskReferenceHint: 'سطح ریسک به طور خودکار از محتوای بسته مهارت تولید می‌شود و فقط برای مرجع بررسی است.\nکم: هیچ ریسک آشکاری یافت نشد\nمتوسط: اسکریپت، وابستگی‌ها، URL‌های خارجی یا متغیرهای محیطی\nبالا: اجرای از راه دور، اطلاعات حساس یا دستورات خطرناک', @@ -1262,6 +1272,12 @@ const message = { onlySupportedArchive: 'فقط بسته‌های مهارت .zip, .7z, .tar, .tar.gz قابل بارگذاری هستند', uploadSizeExceeded: 'یک بسته مهارت نباید از ۵ مگابایت بیشتر باشد', uploadSuccess: 'مهارت با موفقیت بارگذاری شد و در انتظار بررسی است.', + versionAutoFillPlaceholder: + 'در صورت امکان از نام فایل به‌طور خودکار تشخیص داده می‌شود؛ آن را تأیید یا به‌صورت دستی وارد کنید', + metadataOverwriteConfirm: + 'نسخه موجود در بسته Skill با مقدار فعلی متفاوت است. از مقدار واردشده فعلی استفاده شود؟', + metadataOverwriteConfirmWithVersions: + 'نسخه موجود در بسته Skill با مقدار فعلی متفاوت است. نسخه بسته: {packageVersion}؛ نسخه واردشده: {inputVersion}. از مقدار واردشده فعلی استفاده شود؟', offlineNotice: 'محیط فعلی آفلاین است. فقط مهارت‌های فروشگاه محلی مهارت قابل نصب هستند.', publishConfirm: 'این مهارت منتشر شود؟ مهارت‌های منتشر شده از فروشگاه محلی مهارت قابل نصب هستند.', disableConfirm: 'انتشار این مهارت لغو شود؟ مهارت‌های نصب شده در عامل‌ها تحت تأثیر قرار نمی‌گیرند.', @@ -1272,24 +1288,6 @@ const message = { deleteTargetConfirm: 'این عامل سفارشی حذف شود؟ کاربران دیگر نمی‌توانند آن را انتخاب کنند.', noInstallTarget: 'هیچ عامل سفارشی در دسترس نیست. ابتدا یک هدف نصب پیکربندی کنید.', postInstallConfirm: 'این هدف دارای دستور پس از نصب است. قبل از اجرا مطمئن شوید که دستور قابل اعتماد است.', - serverStatusTitle: 'سرور مرکز مهارت', - serverServiceOperateConfirm: 'آیا مطمئن هستید که می‌خواهید سرور مرکز مهارت را {0} کنید؟', - serverAccessSetting: 'تنظیمات دسترسی سرویس', - serverInfo: 'اطلاعات سرور', - tokenSetting: 'تنظیمات توکن', - externalUrl: 'URL خارجی', - externalUrlRequired: 'ابتدا URL خارجی را وارد کنید.', - skillctlDownloadUrl: 'URL دانلود skillctl', - skillctlArchitecture: 'معماری سرور', - registryUrl: 'URL ثبت‌نامه', - loginCommand: 'دستور ورود', - installCommand: 'دستور نصب', - createToken: 'ایجاد توکن', - tokenCreated: 'توکن ایجاد شد', - tokenVisibleOnce: 'توکن فقط یک بار نشان داده می‌شود. اکنون آن را کپی و ذخیره کنید.', - disableTokenConfirm: - 'این توکن غیرفعال شود؟ کلاینت‌های skillctl که از آن استفاده می‌کنند دیگر نمی‌توانند مهارت نصب کنند.', - deleteTokenConfirm: 'این توکن حذف شود؟ این عمل قابل بازگشت نیست.', status: { pending: 'در انتظار', approved: 'تأیید شده', @@ -1747,7 +1745,8 @@ const message = { dockerStatus: 'سرویس Docker', daemonJsonPathHelper: 'اطمینان حاصل کنید که مسیر پیکربندی با مسیر مشخص شده در docker.service یکسان است.', mirrors: 'آینه‌های مخزن', - mirrorsHelper: '', + mirrorsHelper: + 'برای عملیات ایمیج ابتدا از URLهای آینه رجیستری استفاده کنید. برای غیرفعال کردن آینه‌ها این بخش را خالی بگذارید.', mirrorsHelper2: 'برای جزئیات، به مستندات رسمی مراجعه کنید.', registries: 'مخازن ناامن', ipv6Helper: @@ -2060,7 +2059,7 @@ const message = { 'از حساب مدل انتخاب شده برای تولید و پر کردن دستورات استفاده کنید. برای مدل‌های محلی مانند Ollama و vLLM، از یک حساب مدل سفارشی استفاده کنید.', aiPrefix: 'پیشوند محرک', aiPrefixHelper: - '"{0} + space" را وارد کرده و Enter را بزنید تا تولید دستور AI فعال شود، مثلاً: {0} کمک کن استفاده از دیسک را بررسی کنم.', + '«پیشوند + فاصله» را وارد کرده و Enter را بزنید تا تولید دستور AI فعال شود؛ برای نمونه: {0} کمک کن میزان استفاده از دیسک را بررسی کنم.', aiRiskCommands: 'راه‌اندازی دستورات پرخطر', aiRiskCommandsHelper: 'دستورات پرخطر را برای راه‌اندازی پیکربندی کنید، هر خط یک دستور. در صورت تطابق، تولید مسدود شده و به عنوان نظر بازگردانده می‌شود.', @@ -2259,6 +2258,7 @@ const message = { nodes: 'گره', commands: 'دستورات سریع', opsReport: 'گزارش عملیات', + ops_report: 'گزارش عملیات', users: 'مدیریت کاربران', roles: 'نقش', auth: 'احراز هویت ورود', @@ -3724,9 +3724,9 @@ const message = { staticChangePHPHelper: 'در حال حاضر یک وب‌سایت استاتیک است، می‌توانید به وب‌سایت PHP تغییر دهید', proxyCache: 'کش پراکسی معکوس', cacheLimit: 'محدودیت فضای کش', - shareCahe: 'اندازه حافظه کش شمارش', + shareCache: 'اندازه حافظه کش شمارش', cacheExpire: 'زمان انقضای کش', - shareCaheHelper: 'تقریباً ۸۰۰۰ شیء کش در هر ۱ مگابایت حافظه قابل ذخیره است', + shareCacheHelper: 'تقریباً ۸۰۰۰ شیء کش در هر ۱ مگابایت حافظه قابل ذخیره است', cacheLimitHelper: 'کش قدیمی در صورت تجاوز از حد به طور خودکار حذف می‌شود', cacheExpireJHelper: 'کش در صورت عدم بازدید پس از زمان انقضا حذف می‌شود', realIP: 'IP واقعی', @@ -4075,6 +4075,7 @@ const message = { }, runtime: { runtime: 'محیط اجرا', + default: 'پیش‌فرض', workDir: 'دایرکتوری کاری', localHelper: 'برای مشکلات نصب محیط محلی و استفاده در محیط آفلاین، به ', versionHelper: 'نسخه PHP، مثلاً v8.0', @@ -4875,6 +4876,14 @@ const message = { authManage: 'مدیریت احراز هویت', auth: { providerNavigation: 'ارائه دهندگان احراز هویت', + defaultNode: 'گره پیش فرض', + defaultNodePlaceholder: 'یک گره انتخاب کنید', + defaultNodeHelper: 'فقط برای کاربران جدید.', + defaultNodeRequired: 'یک گره پیش فرض معتبر انتخاب کنید.', + nodesLoadFailed: 'بارگیری گره ها ناموفق بود. پیش از انتخاب گره پیش فرض دوباره تلاش کنید.', + nodeHandling: 'مدیریت گره', + assignDefaultNode: 'اختصاص گره پیش فرض: {node}', + keepExistingNode: 'حفظ مجوزهای گره موجود', providers: { ldap: 'AD/LDAP', passkey: 'Passkey', @@ -4902,7 +4911,399 @@ const message = { planned: 'برنامه ریزی شده است', plannedTitle: 'تنظیمات احراز هویت {0}', plannedDesc: 'این ارائه دهنده احراز هویت برنامه ریزی شده است و هنوز در دسترس نیست.', + oidc: { + accessMode: 'حالت اتصال', + accessModeDesc: + 'هر زمان که ارائه دهنده هویت از آن پشتیبانی می کند، از Discovery استاندارد استفاده کنید.', + actionCreate: 'کاربر ایجاد کنید', + actionKeepName: 'نام کاربری فعلی را حفظ کنید', + actionPending: 'منتظر نتیجه', + actionReject: 'رد ورود', + actionUpdate: 'اطلاعات هویتی را به روز کنید', + advanced: 'تنظیمات پیشرفته', + advancedDesc: + 'پیش فرض های ایمن را حفظ کنید مگر اینکه ارائه دهنده به گزینه سازگاری نیاز داشته باشد.', + assignDefaultRole: 'نقش پیش فرض را تعیین کنید: {role}', + authorizationEndpoint: 'Authorization Endpoint', + authorizationEndpointInvalid: 'یک Authorization Endpoint معتبر وارد کنید.', + authorizationFlow: 'جریان مجوز', + automatic: 'خودکار', + automaticPolicy: 'سیاست کنترل خودکار', + automaticPolicyDesc: 'این قوانین توسط بک‌اند اجرا می‌شوند و گزینه‌های قابل تنظیم توسط مدیر نیستند.', + basic: 'تنظیمات پایه', + basicDesc: 'حالت ارائه دهنده را انتخاب کنید، سپس مشتری و پاسخ به تماس را پیکربندی کنید.', + browserTest: 'آزمون ورود در مرورگر', + browserTestConflict: 'هویت تأیید شد، اما نام کاربری تداخل دارد', + browserTestConflictHelper: + 'نام کاربری نگاشت‌شده متعلق به هویت دیگری است و به‌طور خودکار متصل نمی‌شود.', + browserTestExpired: 'تست مرورگر منقضی شد', + browserTestExpiredHelper: 'یک آزمایش مرورگر جدید را شروع کنید و مجوز را قبل از انقضا کامل کنید.', + browserTestFailed: 'تست مرورگر ناموفق بود', + browserTestFailedHelper: + 'پیش‌نمایش هویت تکمیل نشد. خطای بومی‌سازی‌شده بازگشتی از بک‌اند را بررسی کنید.', + browserTestIsolation: + 'این فرایند یک رفت‌وبرگشت واقعی مجوز را انجام می‌دهد، اما کاربری ایجاد یا به‌روزرسانی نمی‌کند، نقشی اختصاص نمی‌دهد و نشست ورود واقعی ایجاد نمی‌کند.', + browserTestPopupBlocked: + 'به پنجره‌های بازشو برای این سایت اجازه دهید، سپس تست مرورگر را دوباره شروع کنید.', + browserTestPopupClosed: 'پنجره مجوز قبل از اتمام آزمایش بسته شد.', + browserTestSuccess: 'تأیید ارائه‌دهنده با موفقیت انجام شد', + browserTestSuccessHelper: 'نگاشت هویت بدون تغییر کاربران یا جلسات پیش نمایش شد.', + browserTestTitle: 'ورود آزمایشی مرورگر OIDC', + browserTestWaiting: 'در انتظار تأیید ارائه‌دهنده', + browserTestWaitingHelper: + 'ورود به سیستم را در پنجره مرورگر جدید کامل کنید. این صفحه به طور خودکار به روز می شود.', + callbackCopied: 'URL بازگشت OIDC کپی شد.', + callbackURL: 'URL بازگشت', + callbackURLHelper: + 'این نشانی را به فهرست نشانی‌های بازگشت مجاز کلاینت در ارائه‌دهنده هویت اضافه کنید.', + cancelClearSecret: 'لغو پاکسازی', + clearSecret: 'پاک کردن Client Secret', + clearSecretConfirm: 'Client Secret فقط پس از ذخیره حذف خواهد شد. ادامه دهید؟', + clientAuthMethod: 'روش احراز هویت مشتری', + clientAuthMethodHelper: + 'روش احراز هویت پیکربندی‌شده برای این کلاینت در ارائه‌دهنده هویت را انتخاب کنید.', + clientAuthMethodRequired: 'یک روش احراز هویت مشتری را انتخاب کنید.', + clientID: 'Client ID', + clientIDRequired: 'Client ID را وارد کنید.', + clientSecret: 'Client Secret', + clockSkew: 'تحمل اختلاف زمانی توکن', + clockSkewHelper: + 'اختلاف زمانی اندکی میان ارائه‌دهنده هویت و 1Panel را مجاز می‌کند. مقدار پیش‌فرض 60 ثانیه را حفظ کنید.', + clockSkewRequired: 'تحمل اختلاف زمانی توکن را وارد کنید.', + compatibilityMode: 'حالت سازگاری', + compatibilityModeHelper: + 'فقط برای Discovery ناقص یا نقاط پایانی بازنویسی شده استفاده کنید. اعتبار سنجی Core OIDC همچنان فعال است.', + configurationFailedHelper: + 'آزمایش ناموفق بود. صفحه فقط خطای بومی‌سازی‌شده بازگشتی از بک‌اند را نمایش می‌دهد.', + configurationFailedTag: 'تست ناموفق بود', + configurationHighRiskPassed: 'پیکربندی تصویب شد، اما حاوی گزینه‌های سازگاری پرخطر است.', + configurationHighRiskTag: 'پیکربندی پرخطر تصویب شد', + configurationNotTested: 'پیکربندی فعلی آزمایش نشده است.', + configurationNotTestedTag: 'تست نشده', + configurationPassed: 'پیکربندی فعلی بررسی‌های امنیتی و قابلیت را پشت سر گذاشت.', + configurationPassedTag: 'آزمون قبول شد', + configurationStaleHelper: 'پیکربندی تغییر کرده است. پیش از ذخیره دوباره آن را آزمایش کنید.', + configurationStaleTag: 'نتیجه منقضی شده است', + configurationTestMeta: + 'در {time} آزمایش شد و در {duration} میلی‌ثانیه تکمیل شد. پاسخ خام ارائه‌دهنده ذخیره نمی‌شود.', + configurationTestResult: 'نتیجه تست پیکربندی', + configurationTestResultDesc: + 'این فقط Discovery و قابلیت ها را بررسی می کند. کد مجوز را مبادله نمی کند یا Client Secret را اثبات نمی کند. از لاگین آزمایشی مرورگر برای تایید سرتاسر استفاده کنید.', + configurationTestSuccess: 'تست پیکربندی OIDC با موفقیت انجام شد.', + configurationTesting: 'آزمایش پیکربندی فعلی OIDC…', + configurationTestingTag: 'تست کردن', + configureSecret: 'پیکربندی Client Secret', + conflictExistingRename: 'subject متصل، نام کاربری جدیدی را برمی‌گرداند که قبلاً استفاده شده است.', + conflictExistingRenameResult: + 'User.Name موجود را حفظ کنید و به کاربر مقید اجازه ورود به سیستم را بدهید', + conflictLDAP: 'کاربر LDAP', + conflictLocal: 'کاربر محلی', + conflictNewAvailable: 'subject جدید و نام کاربری نگاشت‌شده در دسترس هستند', + conflictNewAvailableResult: 'یک کاربر سازمانی ایجاد کنید و نقش پیش فرض را تعیین کنید', + conflictNone: 'بدون درگیری', + conflictOIDC: 'هویت دیگر OIDC', + conflictOccupied: 'نام کاربری نگاشت‌شده متعلق به کاربر محلی، کاربر LDAP یا هویت OIDC دیگری است.', + conflictOccupiedResult: 'رد هویت جدید؛ هرگز به طور خودکار متصل یا ادغام نمی شود', + conflictType: 'نوع تضاد', + connectionSecurity: 'امنیت اتصال', + connectionSecurityDesc: + 'خط‌مشی TLS برای درخواست‌های Discovery، Token، JWKS، و UserInfo اعمال می‌شود.', + connectionTest: 'تست اتصال و پیکربندی', + connectionTestCompatibilityDesc: 'نقاط پایانی سفارشی و خط‌مشی امنیتی پروتکل را اعتبارسنجی کنید.', + connectionTestStandardDesc: 'نقاط پایانی و قابلیت ها به طور خودکار از Issuer کشف می شوند.', + connectionTestTab: 'آزمون اتصال', + customCA: 'CA سفارشی', + customCAHelper: 'فقط برای این منبع احراز هویت اعمال می شود و هرگز در گزارش ها نوشته نمی شود.', + customCARequired: 'گواهی سفارشی CA را ارائه دهید.', + defaultRole: 'نقش پیش فرض', + defaultRoleHelper: + 'فقط هنگام ایجاد کاربر برای نخستین بار اختصاص می‌یابد؛ ورودهای بعدی نقش را تغییر نمی‌دهند.', + defaultRolePlaceholder: 'یک نقش را انتخاب کنید', + defaultRoleRequired: 'یک نقش پیش فرض معتبر انتخاب کنید.', + disableAfterSave: 'OIDC پس از ذخیره غیرفعال می شود.', + disableConfirm: 'غیرفعال کردن OIDC بلافاصله دسترسی کاربران این منبع را باطل می کند. ادامه دهید؟', + disableDiscardConfirm: + 'غیرفعال کردن OIDC یک اقدام اضطراری است: فقط ورودی ورود به سیستم را می بندد و بلافاصله دسترسی کاربران این منبع را باطل می کند. سایر تغییرات ذخیره نشده در این صفحه، از جمله تغییرات Client Secret، نادیده گرفته خواهند شد. ادامه دهید؟', + disableTitle: 'OIDC را غیرفعال کنید', + disabled: 'غیرفعال', + discoveryAllowlist: 'فهرست مجاز امنیتی Discovery', + enable: 'فعال‌سازی', + enableAfterSave: 'OIDC پس از ذخیره موفقیت آمیز فعال می شود.', + enabled: 'فعال', + endSessionEndpoint: 'End Session Endpoint', + endSessionEndpointHelper: + 'برای استفاده در آینده ذخیره می‌شود؛ خروج از سیستم آغازشده توسط ارائه‌دهنده در این نسخه گنجانده نشده است.', + endSessionEndpointInvalid: 'یک End Session Endpoint معتبر وارد کنید.', + endpointDiscoveryPlaceholder: 'پس از آزمایش اتصال نمایش داده می‌شود', + firstLogin: 'ابتدا وارد شوید', + firstLoginPolicy: 'یک کاربر سازمانی محلی ایجاد کنید و نقش پیش فرض پیکربندی شده را تعیین کنید.', + fixedAuthorizationCode: 'Authorization Code Flow', + fixedNoTokenPersistence: 'Token، Claims، و verifier هرگز باقی نمی مانند', + fixedSecurityPolicy: 'همیشه اجرا می شود؛ بدون نیاز به پیکربندی', + fixedStateNonce: 'یکبار مصرف state و nonce', + fixedTokenValidation: 'امضای ID Token و اعتبار Claims', + highRiskSaveConfirm: + 'این پیکربندی فعال شامل گزینه‌های سازگاری پرخطر است. تأیید کنید که محیط ایزوله به آنها نیاز دارد.', + highRiskTitle: 'پیکربندی پرخطر OIDC', + hs256Compatibility: 'HS256 (سازگاری)', + hs256KeyHelper: + 'HS256 همیشه از Client Secret این منبع استفاده می کند و کلید امضای جداگانه را نمی پذیرد.', + hs256Warning: + 'HS256 برای امضای ID Token از یک راز متقارن مشترک استفاده می‌کند. فقط زمانی از آن استفاده کنید که ارائه‌دهنده نتواند از الگوریتم نامتقارن استفاده کند.', + identityBindingPolicy: + 'هویت به AuthSourceID + issuer + subject متصل است. تطابق نام کاربری هرگز حساب دیگری را به‌طور خودکار متصل نمی‌کند.', + identityMissing: 'هویت غیرفعال', + issuer: 'Issuer URL', + issuerHelper: 'مقدار ID Token است و Discovery issuer باید دقیقاً با این مقدار مطابقت داشته باشد.', + issuerInvalid: 'یک HTTP یا HTTPS Issuer URL معتبر بدون پرس و جو یا قطعه وارد کنید.', + issuerRequired: 'Issuer URL را وارد کنید.', + jwksRotation: 'چرخش خودکار JWKS', + jwksURI: 'JWKS URI', + jwksURIHelper: 'زمانی که منبع کلید JWKS باشد برای امضای نامتقارن مورد نیاز است.', + jwksURIInvalid: 'یک JWKS URI معتبر برای منبع کلید امضای انتخاب شده وارد کنید.', + keepExistingRole: 'نقش های موجود و مجوزهای محلی را حفظ کنید', + localSecurityData: 'داده های امنیتی محلی', + localSecurityDataPolicy: 'هرگز نقش‌ها، MFA، API Keys، Passkeys یا مجوزهای محلی را بازنویسی نکنید.', + localCredentialsManaged: + 'نام کاربری و رمز عبور محلی توسط OIDC مدیریت می‌شوند و در اینجا قابل ویرایش نیستند. نقش‌ها، مجوزها، MFA، API Keys و Passkeys محلی باقی می‌مانند.', + localUserFields: 'فیلدهای کاربری محلی', + localUserFieldsDesc: + 'اولین نسخه فقط User.Name را نقشه برداری می کند و از عبارت نقشه برداری JSON استفاده نمی کند.', + loginWith: 'ورود با {provider}', + manualEndpoints: 'نقاط پایانی سفارشی', + manualEndpointsDesc: + 'فقط زمانی استفاده کنید که Discovery ناقص باشد یا یک دروازه بالادست نقاط انتهایی را بازنویسی کند.', + mappingResult: 'نتیجه نقشه برداری', + mode: 'حالت اتصال', + modeRequired: 'یک حالت اتصال را انتخاب کنید.', + nameClaim: 'Claim نام کاربری', + nameClaimHelper: 'فیلد حاوی نام کاربری، مانند preferred_username، را وارد کنید.', + nameClaimRequired: 'Claim نام کاربری را وارد کنید.', + nameConflict: 'خط مشی تضاد نام', + panelURL: 'URL عمومی 1Panel', + panelURLHTTPWarning: + 'HTTP از پاسخ مجوز محافظت نمی‌کند. فقط در محیط خصوصی ایزوله‌ای که ارائه‌دهنده می‌پذیرد از آن استفاده کنید.', + panelURLHelper: + 'نشانی دسترسی کاربران به 1Panel را وارد کنید. این نشانی برای ایجاد نشانی بازگشت استفاده می‌شود.', + panelURLInvalid: 'مبدایی را وارد کنید که فقط شامل طرح، میزبان و پورت اختیاری است.', + panelURLRequired: 'URL عمومی 1Panel را وارد کنید.', + pkceDisabled: 'غیرفعال (فقط سازگاری)', + pkceDisabledWarning: 'غیرفعال کردن PKCE حفاظت در برابر رهگیری کد مجوز را کاهش می دهد.', + pkceHelper: 'S256 را ترجیح دهید. روش چالش plain هرگز ارائه نمی شود.', + pkceS256: 'S256 (توصیه می شود)', + plannedHandling: 'جابجایی برنامه ریزی شده', + privateNetworkIdP: 'IdP شبکه خصوصی', + privateNetworkIdPHelper: + 'به صراحت آدرس های خصوصی را مجاز می کند. ابرداده، لوپ بک، پیوند محلی، تغییر مسیرها و پیوند مجدد DNS مسدود می‌مانند.', + privateNetworkWarning: 'دسترسی به شبکه خصوصی برای این منبع احراز هویت فعال است.', + protocolCompatibility: 'سازگاری پروتکل', + protocolCompatibilityDesc: 'اعتبار سنجی امضای ID Token هرگز نمی تواند غیرفعال شود.', + providerAndClient: 'ارائه‌دهنده و کلاینت', + providerAndClientDesc: + 'Client Secret فقط می تواند جایگزین یا پاک شود و هرگز توسط صفحه بازگردانده نمی شود.', + providerCapabilities: 'قابلیت‌های ارائه‌دهنده', + recentTestSuccess: 'آخرین آزمایش موفق: {0}', + recommended: 'توصیه می شود', + rejectPlain: 'plain رد شد', + replaceSecret: 'راز را جایگزین کنید', + requestAndClaims: 'درخواست ها و صفات', + requestAndClaimsDesc: 'دامنه‌های مجوز، تکمیل اطلاعات کاربر و پارامترهای درخواست را پیکربندی کنید.', + requestTimeout: 'مهلت زمانی درخواست', + requestTimeoutRequired: 'زمان درخواست را وارد کنید.', + restore: 'بازیابی', + restored: 'آخرین تنظیمات ذخیره شده OIDC بازیابی شدند.', + result: 'نتیجه', + rolesLoadFailed: 'نقش ها بارگیری نشدند. قبل از انتخاب نقش پیش فرض، دوباره امتحان کنید.', + roleHandling: 'رسیدگی به نقش', + scenario: 'سناریو', + scopes: 'دامنه‌های مجوز', + scopesHelper: 'باید شامل openid باشد. دامنه‌های متعدد را با فاصله جدا کنید.', + scopesRequired: 'Scopes باید شامل openid باشد.', + seconds: 'ثانیه', + secretClearHelper: + 'پس از پاکسازی، قبل از اینکه OIDC بتواند دوباره فعال شود، یک Client Secret جدید لازم است.', + secretConfigured: 'پیکربندی شده است', + secretNotConfigured: 'پیکربندی نشده است', + secretPlaceholder: 'یک Client Secret جدید وارد کنید', + secretReplaceHelper: + 'مقدار جدید هنگام ذخیره جایگزین مقدار قبلی می‌شود. Client Secret را در Provider OIDC نیز به‌روزرسانی کنید.', + secretRequiredHelper: 'قبل از فعال کردن OIDC یک Client Secret را پیکربندی کنید.', + secretRequiredToEnable: 'قبل از فعال کردن OIDC یک Client Secret را پیکربندی کنید.', + secretSavedHelper: 'به‌صورت رمزگذاری‌شده ذخیره می‌شود. برای حفظ رمز فعلی، فیلد را خالی بگذارید.', + secretWaiting: 'در انتظار ورودی', + secretWillClear: 'پاک خواهد شد', + secretWillReplace: 'جایگزین خواهد شد', + signingAlgorithm: 'الگوریتم امضای ID Token', + signingAlgorithmHelper: 'فقط الگوریتم‌های موجود در لیست مجوزهای امنیتی Backend در دسترس هستند.', + signingKey: 'کلید امضا', + signingKeyClientSecret: 'Client Secret (فقط HS256)', + signingKeyJWKS: 'JWKS URI با چرخش خودکار', + signingKeySource: 'منبع کلید امضا', + signingKeySourceHelper: 'JWKS را ترجیح دهید. یک کلید عمومی ثابت نمی تواند به طور خودکار بچرخد.', + signingKeyStatic: 'کلید عمومی ثابت JWK یا PEM', + standardDiscovery: 'استاندارد OIDC Discovery', + standardDiscoveryDesc: '1Panel نقاط پایانی و قابلیت‌ها را کشف می‌کند و سند خام را ذخیره نمی‌کند.', + standardMode: 'حالت استاندارد', + standardModeHelper: 'نقاط پایانی، قابلیت‌های امضا و پشتیبانی PKCE را از Issuer کشف کنید.', + standardProtocolPolicy: 'خط مشی پروتکل استاندارد', + standardProtocolPolicyDesc: + 'قابلیت های امضا به طور خودکار مذاکره می شود. هیچ کلید امضایی در اینجا وارد نشده است.', + staticSigningKey: 'کلید عمومی امضای ایستا', + staticSigningKeyHelper: + 'فقط کلید عمومی پذیرفته می‌شود. هنگام تغییر کلید ارائه‌دهنده، آن را به‌صورت دستی جایگزین کنید.', + staticSigningKeyPlaceholder: 'یک کلید عمومی JWK، JWKS JSON، یا PEM جایگذاری کنید', + staticSigningKeyRequired: 'کلید عمومی امضای ثابت را ارائه دهید.', + staticSigningKeyWarning: + 'کلید امضای ثابت نمی‌تواند خودکار بچرخد. پیش از چرخش کلیدهای ارائه‌دهنده، آن را به‌روزرسانی کنید.', + settingLoadFailed: 'تنظیمات OIDC بارگیری نشد', + settingLoadFailedHelper: + 'فرم قفل شده است تا از ذخیره یک پیکربندی پیش فرض خالی روی تنظیمات فعلی جلوگیری شود. پس از بازیابی اتصال دوباره سعی کنید.', + subsequentLogin: 'ورود بعدی', + subsequentLoginPolicy: + 'اتصال را با subject پیدا کنید و فقط زمانی که نام کاربری جدید در دسترس است User.Name را به‌روزرسانی کنید.', + testBeforeBrowserTest: 'قبل از شروع تست ورود به مرورگر، پیکربندی فعلی را آزمایش کنید.', + testBeforeEnable: 'پیش از ذخیره تغییرات پیکربندی، پیکربندی فعلی را آزمایش کنید.', + testConfiguration: 'آزمون پیکربندی', + testDiscovery: 'آزمون Discovery', + tlsCustomCA: 'HTTPS · گواهی سفارشی CA', + tlsPrivateHTTP: 'HTTP · فقط شبکه خصوصی (خطرناک)', + tlsPrivateHTTPWarning: + 'HTTP هیچ رمزگذاری حمل و نقلی ارائه نمی دهد و محدود به اهداف خصوصی مجاز است.', + tlsSkipVerify: 'HTTPS · رد شدن از تأیید گواهی (خطرناک)', + tlsSystem: 'HTTPS · تأیید گواهی سیستم (توصیه می شود)', + tokenEndpoint: 'Token Endpoint', + tokenEndpointInvalid: 'یک Token Endpoint معتبر وارد کنید.', + transportSecurity: 'امنیت حمل و نقل', + transportSecurityHelper: + 'HTTPS را ترجیح دهید. HTTP خصوصی همچنین به دسترسی صریح private-network نیاز دارد.', + unsavedChanges: 'تغییرات ذخیره‌نشده OIDC وجود دارد.', + usedClaim: 'Claim استفاده شده است', + userInfoEndpoint: 'UserInfo Endpoint', + userInfoEndpointHelper: + 'اگر فیلد نام کاربری موجود نباشد، سیستم آن را از این نقطه پایانی دریافت می‌کند؛ برای عدم تکمیل، خالی بگذارید.', + userInfoEndpointInvalid: 'یک UserInfo Endpoint معتبر وارد کنید.', + userMapping: 'تنظیمات کاربر', + userMappingDesc: + 'نگاشت نام کاربری OIDC و گره و نقش پیش‌فرض مورد استفاده برای ایجاد کاربر در نخستین ورود را تنظیم کنید.', + }, + saml2: { + actionCreate: 'کاربر ایجاد کنید', + actionPending: 'منتظر نتیجه', + actionReject: 'رد ورود', + actionReuse: 'استفاده از کاربر پیوندخورده', + assignDefaultRole: 'نقش پیش فرض را تعیین کنید: {role}', + basic: 'تنظیمات پایه', + basicDesc: 'گزینه‌های رایج مورد نیاز بیشتر ارائه‌دهندگان استاندارد SAML2 را پیکربندی کنید.', + browserTest: 'آزمایش ورود', + browserTestConflict: 'هویت تأیید شد، اما نام کاربری تداخل دارد', + browserTestConflictHelper: + 'نام کاربری نگاشت‌شده متعلق به هویت دیگری است و به‌طور خودکار متصل نمی‌شود.', + browserTestExpired: 'تست مرورگر منقضی شد', + browserTestExpiredHelper: 'یک آزمایش مرورگر جدید را شروع کنید و مجوز را قبل از انقضا کامل کنید.', + browserTestFailed: 'تست مرورگر ناموفق بود', + browserTestFailedHelper: + 'پیش‌نمایش هویت تکمیل نشد. خطای بومی‌سازی‌شده بازگشتی از بک‌اند را بررسی کنید.', + browserTestIsolation: + 'این فرایند یک رفت‌وبرگشت واقعی مجوز را انجام می‌دهد، اما کاربری ایجاد یا به‌روزرسانی نمی‌کند، نقشی اختصاص نمی‌دهد و نشست ورود واقعی ایجاد نمی‌کند.', + browserTestPopupBlocked: + 'به پنجره‌های بازشو برای این سایت اجازه دهید، سپس تست مرورگر را دوباره شروع کنید.', + browserTestPopupClosed: 'پنجره مجوز قبل از اتمام آزمایش بسته شد.', + browserTestSuccess: 'تأیید ارائه‌دهنده با موفقیت انجام شد', + browserTestSuccessHelper: 'نگاشت هویت بدون تغییر کاربران یا جلسات پیش نمایش شد.', + browserTestTitle: 'ورود آزمایشی مرورگر SAML2', + browserTestWaiting: 'در انتظار تأیید ارائه‌دهنده', + browserTestWaitingHelper: + 'ورود به سیستم را در پنجره مرورگر جدید کامل کنید. این صفحه به طور خودکار به روز می شود.', + certificateFileInvalid: 'یک فایل گواهی معتبر با فرمت PEM، CRT یا CER انتخاب کنید.', + configured: 'پیکربندی شده', + configurationFailedHelper: + 'آزمایش ناموفق بود. صفحه فقط خطای بومی‌سازی‌شده بازگشتی از بک‌اند را نمایش می‌دهد.', + configurationNotTested: 'پیکربندی فعلی آزمایش نشده است.', + configurationPassed: 'پیکربندی فعلی بررسی‌های امنیتی و قابلیت را پشت سر گذاشت.', + configurationStaleHelper: 'تنظیمات حساس به احراز هویت تغییر کرد. دوباره پیش نویس فعلی را تست کنید.', + configurationTestSuccess: 'تست پیکربندی SAML2 با موفقیت انجام شد.', + configurationTesting: 'آزمایش پیکربندی فعلی SAML2…', + conflictLDAP: 'کاربر LDAP', + conflictLocal: 'کاربر محلی', + conflictNone: 'بدون درگیری', + conflictOIDC: 'هویت دیگر OIDC', + conflictSAML2: 'هویت SAML2 دیگر', + conflictType: 'نوع تضاد', + credentialFileReadFailed: 'فایل اطلاعات اعتبارسنجی قابل خواندن نیست.', + credentialFileTooLarge: 'حجم فایل‌های اطلاعات اعتبارسنجی نباید از 256 KiB بیشتر باشد.', + credentialsRequired: 'کلید خصوصی و گواهی SP را پیکربندی کنید.', + defaultRole: 'نقش کاربر جدید', + defaultRoleHelper: + 'فقط هنگام ایجاد اولیه اختصاص می‌یابد؛ ورودهای بعدی نقش‌ها، MFA و مجوزهای محلی را حفظ می‌کنند.', + defaultRolePlaceholder: 'یک نقش را انتخاب کنید', + defaultRoleRequired: 'یک نقش پیش فرض معتبر انتخاب کنید.', + disableConfirm: + 'غیرفعال کردن SAML2 بلافاصله ورودهای جدید را رد و نشست‌های کاربران آن را بی‌اعتبار می‌کند. ادامه می‌دهید؟', + disableDiscardConfirm: + 'غیرفعال کردن SAML2 سایر تغییرات ذخیره‌نشده این صفحه را کنار می‌گذارد و بلافاصله نشست‌های کاربران آن را بی‌اعتبار می‌کند. ادامه می‌دهید؟', + disableTitle: 'SAML2 را غیرفعال کنید', + disabled: 'غیرفعال', + enable: 'فعال‌سازی', + enabled: 'فعال', + idpMetadata: 'فراداده IdP', + idpMetadataDesc: 'یک URL وارد کنید یا XML را بچسبانید. اگر هر دو موجود باشند URL اولویت دارد.', + keepExistingRole: 'نقش های موجود و مجوزهای محلی را حفظ کنید', + loginWith: 'ورود با {provider}', + mappingResult: 'نتیجه نقشه برداری', + metadataRequired: 'URL یا XML فراداده IdP را وارد کنید.', + metadataURLHelper: 'بخش پشتیبان هنگام آزمایش و ذخیره، فراداده را دانلود و اعتبارسنجی می‌کند.', + metadataURLInvalid: 'یک URL فراداده HTTPS معتبر و بدون اطلاعات ورود یا قطعه وارد کنید.', + metadataURLRecommended: 'URL فراداده (پیشنهادی)', + metadataXML: 'XML فراداده', + metadataXMLHelper: 'وقتی IdP یک URL فراداده در دسترس ارائه نمی‌کند از این گزینه استفاده کنید.', + metadataXMLInvalid: 'XML فراداده EntityDescriptor معتبری وارد کنید.', + metadataXMLPlaceholder: '... را جای‌گذاری کنید', + nameAttribute: 'ویژگی نام کاربری', + nameAttributeHelper: + 'این ویژگی را از SAML Assertion تأییدشده می‌خواند و به نام کاربری 1Panel نگاشت می‌کند.', + nameAttributePlaceholder: 'برای مثال: uid، username یا account', + nameAttributeRequired: 'ویژگی نام کاربری را وارد کنید.', + notConfigured: 'پیکربندی نشده', + or: 'یا', + pageDesc: 'ورود یکپارچه سازمانی را از طریق فراداده IdP با تنظیمات رایج در یک صفحه متصل کنید.', + plannedHandling: 'جابجایی برنامه ریزی شده', + privateKeyFileInvalid: 'یک فایل کلید خصوصی PEM معتبر انتخاب کنید.', + recentTestSuccess: 'آخرین آزمایش موفق: {0}', + restore: 'بازیابی', + restored: 'آخرین تنظیمات ذخیره شده SAML2 بازیابی شدند.', + roleHandling: 'رسیدگی به نقش', + rolesLoadFailed: 'نقش ها بارگیری نشدند. قبل از انتخاب نقش پیش فرض، دوباره امتحان کنید.', + selectFile: 'انتخاب فایل', + serviceStatus: 'وضعیت سرویس', + serviceStatusDesc: 'پیکربندی فعلی باید پیش از فعال‌سازی SAML2 آزمایش را با موفقیت بگذراند.', + settingLoadFailed: 'تنظیمات SAML2 بارگیری نشد', + settingLoadFailedHelper: + 'فرم قفل شده است تا از ذخیره یک پیکربندی پیش فرض خالی روی تنظیمات فعلی جلوگیری شود. پس از بازیابی اتصال دوباره سعی کنید.', + spCertificate: 'گواهی SP', + spCertificateHelper: + 'در فراداده SP منتشر می‌شود تا IdP بتواند درخواست‌های ورود و خروج را تأیید کند.', + spCredentials: 'کلید خصوصی و گواهی SP', + spCredentialsDesc: + 'برای امضای پیام‌های ورود و خروج استفاده می‌شود. سیاست امضا و اعتبارسنجی در بخش پشتیبان ثابت است.', + spPrivateKey: 'کلید خصوصی SP', + spPrivateKeyHelper: + 'برای امضای AuthnRequest و پیام‌های خروج استفاده می‌شود. در حالت ذخیره رمزنگاری شده و هرگز نمایش داده نمی‌شود.', + syncLogout: 'خروج همگام', + syncLogoutHelper: 'خروج از 1Panel یا ارائه‌دهنده هویت، نشست سمت دیگر را نیز خاتمه می‌دهد.', + testBeforeBrowserTest: 'قبل از شروع تست ورود به مرورگر، پیکربندی فعلی را آزمایش کنید.', + testBeforeEnable: 'قبل از فعال کردن یا ذخیره تغییرات حساس، پیکربندی فعلی را آزمایش کنید.', + testConfiguration: 'آزمایش پیکربندی', + unsavedChanges: 'تغییرات ذخیره‌نشده SAML2 وجود دارد.', + usedAttribute: 'نگاشت نام کاربری', + usersAndRoles: 'کاربران و نقش‌ها', + usersAndRolesDesc: + 'نگاشت نام کاربری پنل و گره و نقش پیش‌فرض مورد استفاده برای ایجاد کاربر در نخستین ورود را تنظیم کنید.', + }, ldap: { + basic: 'تنظیمات پایه', + loginTitle: 'ورود LDAP', + loginWith: 'ورود با LDAP', + backToLocalLogin: 'بازگشت به ورود پنل', enable: 'فعال کردن', enabled: 'فعال شد', disabled: 'غیرفعال', @@ -4931,7 +5332,7 @@ const message = { strictSyncTooltip: 'پس از وارد کردن کامل، کاربرانی که از این منبع LDAP غایب هستند غیرفعال می شوند اما حذف نمی شوند.', strictSyncHelper: - 'فقط برای یک واردات کامل کامل اعمال می شود. وارد کردن کاربران انتخابی هرگز سایر کاربران را غیرفعال نمی کند.', + 'فقط برای یک واردات کامل اعمال می‌شود. وارد کردن کاربران انتخابی هرگز سایر کاربران را غیرفعال نمی‌کند.', skipTLSVerify: 'رد شدن از تأیید TLS', skipTLSVerifyTooltip: 'تأیید گواهی را برای اتصالات LDAPS غیرفعال کنید.', skipTLSVerifyHelper: @@ -4986,7 +5387,7 @@ const message = { defaultRoleHelper: 'فقط برای کاربران ایجاد شده توسط همگام سازی برنامه ریزی شده اعمال می شود.', defaultRoleRequired: 'نقشی را برای کاربران جدید LDAP انتخاب کنید.', strictSyncHelper: - 'کاربرانی که از یک پرس و جو کامل کامل غایب هستند غیرفعال می شوند و جلسات آنها پاک می شود. کاربران، نقش‌ها و مجوزها حذف نمی‌شوند.', + 'کاربرانی که در یک پرس‌وجوی کامل وجود ندارند غیرفعال می‌شوند و نشست‌های آنها پاک می‌شود. کاربران، نقش‌ها و مجوزها حذف نمی‌شوند.', safetyTitle: 'کاربران گمشده فقط پس از یک پرس و جو کامل LDAP پردازش می شوند', safetyDescription: 'پرس و جو ناموفق، مهلت زمانی، یا نتیجه صفحه ناقص هرگز وضعیت کاربر را تغییر نمی دهد. محدوده همگام سازی از نگاشت کاربر Base DN، فیلتر و ویژگی پیروی می کند.', @@ -4999,7 +5400,7 @@ const message = { saveBeforeRun: 'قبل از اجرای کار، تنظیمات همگام سازی را ذخیره کنید.', runConfirmTitle: 'همگام سازی دقیق را اجرا کنید', runConfirmDescription: - 'کاربران LDAP که یک پرس و جو کامل کامل ندارند غیرفعال می شوند و جلسات فعال آنها پاک می شود. ادامه دهید؟', + 'کاربران LDAP که در یک پرس‌وجوی کامل وجود ندارند غیرفعال می‌شوند و نشست‌های فعال آنها پاک می‌شود. ادامه دهید؟', runSuccess: 'همگام سازی LDAP تکمیل شد.', weekdays: { 0: 'یکشنبه', @@ -5118,6 +5519,7 @@ const message = { deleteConfirm: 'این سابقه و فایل خروجی حذف شود؟', }, waf: { + WAF: 'WAF', name: 'WAF', blackWhite: 'لیست سیاه و سفید', globalSetting: 'تنظیمات جهانی', @@ -5178,7 +5580,9 @@ const message = { geoRule: 'محدودیت دسترسی منطقه‌ای', geoHelper: 'دسترسی به وب‌سایت خود را از برخی مناطق محدود کنید، مثلاً: اگر دسترسی از سرزمین اصلی چین مجاز است، درخواست‌های خارج از سرزمین اصلی چین مسدود می‌شوند', + regionPolicy: 'سیاست منطقه', provincePolicy: 'سیاست استان', + provinceRuleLabel: 'استان', openRestyFeatureVersionAlert: 'برای فعال شدن {0}، نسخه OpenResty باید جدیدتر از 1.31.1.1-0 باشد.', ipLocation: 'مکان IP', ipLocationSearchHelper: 'موقعیت IP را وارد کنید؛ جست‌وجوی تقریبی پشتیبانی می‌شود', @@ -5213,6 +5617,7 @@ const message = { fileExtHelper: 'پسوندهای فایل ممنوع برای آپلود', deny: 'ممنوع', allow: 'مجاز', + allowOnly: 'فقط مجاز', field: 'شیء', pattern: 'شرط', ruleContent: 'محتوا', @@ -5383,9 +5788,11 @@ const message = { protectionMode: 'حالت محافظت', observationMode: 'حالت مشاهده', standardMode: 'حالت استاندارد', + observationModeHelper: 'درخواست‌ها را بدون مسدود کردن شناسایی و ثبت می‌کند', observationModeConfirm: 'در حالت مشاهده، تمام موارد منطبق WAF فقط ثبت می‌شوند و درخواست‌ها مسدود نمی‌شوند. ادامه می‌دهید؟', globalStrictRequired: 'ابتدا حالت سخت‌گیرانه را در تنظیمات سراسری فعال کنید', + observe: 'مشاهده', websiteSearchHelper: 'دامنه، نام مستعار یا توضیحات وب‌سایت را وارد کنید', configReadFailed: 'بارگذاری پیکربندی ناموفق بود', detailSetting: 'تنظیمات دقیق', @@ -5724,6 +6131,13 @@ const message = { nodeUpgradePackageCleanHelper: 'همه بسته‌های به‌روزرسانی نسخه پایین‌تر پاک‌سازی می‌شوند. ادامه می‌دهید؟', nodeUpgradeOfflinePackageHelper: 'در محیط‌های آفلاین، گره‌های با معماری‌های مختلف باید قبل از به‌روزرسانی، بسته به‌روزرسانی متناسب را آپلود کنند.', + healthCheck: 'بررسی سلامت', + healthCheckFrequency: 'دوره بررسی', + healthCheckFrequencyHelper: + 'سلامت گره‌های پشتیبان را به‌صورت دوره‌ای بررسی می‌کند. برای غیرفعال‌سازی، ۰ را وارد کنید.', + healthCheckFrequencyLimit: 'دوره بررسی نباید بیش از یک روز باشد و باید یک عدد صحیح نامنفی باشد.', + loadFailedNodeResources: 'بارگیری منابع گره‌های ناموفق', + loadFailedNodeResourcesHelper: 'هنگام باز کردن فهرست گره‌ها، اطلاعات منابع گره‌های ناموفق نیز بارگیری شود.', nodeUnhealthy: 'وضعیت گره غیرعادی', deletedNode: 'گره حذف شده {0} در حال حاضر از عملیات ارتقاء پشتیبانی نمی‌کند!', nodeUnhealthyHelper: @@ -6211,35 +6625,34 @@ const message = { cpu: 'CPU', memory: 'حافظه', disk: 'دیسک', - overview: 'Overview', - kvmUnavailable: 'No available KVM hardware virtualization capability was detected.', - kvmCheckCpu: 'Confirm that the host CPU supports Intel VT-x or AMD-V virtualization.', - kvmCheckBios: 'Enable virtualization options in BIOS/UEFI.', - kvmCheckModule: 'Confirm that the kvm, kvm_intel, or kvm_amd kernel module is loaded correctly.', - kvmCheckDevice: - 'Confirm that /dev/kvm exists and the current environment is not a container or cloud host without KVM support.', - abnormal: 'Abnormal', - resourceOverview: 'Resource Overview', - cpuAllocated: 'CPU Allocated', - memoryAllocated: 'Memory Allocated', - storageUsed: 'Storage Used', - riskReminder: 'Risk Reminders', - noRisk: 'No risks', - runtimeHealth: 'Runtime Health', - runtimeAbnormal: 'VM runtime is abnormal', - noDependency: 'No dependency check data', - storageOverview: 'Storage Overview', - totalAllocated: 'Calculated by total VM configuration', - runningAllocated: 'Running allocation: {0}', - storageAvailable: 'Available: {0}', - inProgress: 'In progress', - needAttention: 'Needs attention', - normal: 'Normal', - environmentRisk: 'The VM runtime is not ready. Fix dependencies or virtualization services.', - storageRisk: 'Storage pool {0} usage has reached {1}%.', - abnormalRisk: '{0} VMs are in an abnormal state.', - pausedRisk: '{0} VMs are paused.', - memoryRisk: 'VM memory allocation has reached {0}%.', + overview: 'نمای کلی', + kvmUnavailable: 'هیچ قابلیت مجازی‌سازی سخت‌افزاری KVM در دسترس شناسایی نشد.', + kvmCheckCpu: 'بررسی کنید CPU میزبان از مجازی‌سازی Intel VT-x یا AMD-V پشتیبانی می‌کند.', + kvmCheckBios: 'گزینه‌های مجازی‌سازی را در BIOS/UEFI فعال کنید.', + kvmCheckModule: 'بررسی کنید ماژول کرنل kvm، kvm_intel یا kvm_amd به‌درستی بارگذاری شده است.', + kvmCheckDevice: 'بررسی کنید /dev/kvm وجود دارد و محیط فعلی کانتینر یا میزبان ابری فاقد پشتیبانی KVM نیست.', + abnormal: 'غیرعادی', + resourceOverview: 'نمای کلی منابع', + cpuAllocated: 'CPU تخصیص‌یافته', + memoryAllocated: 'حافظه تخصیص‌یافته', + storageUsed: 'فضای ذخیره‌سازی استفاده‌شده', + riskReminder: 'هشدارهای خطر', + noRisk: 'بدون خطر', + runtimeHealth: 'سلامت محیط اجرا', + runtimeAbnormal: 'محیط اجرای VM غیرعادی است', + noDependency: 'داده‌ای از بررسی وابستگی‌ها وجود ندارد', + storageOverview: 'نمای کلی فضای ذخیره‌سازی', + totalAllocated: 'بر اساس مجموع پیکربندی VMها محاسبه شده است', + runningAllocated: 'تخصیص در حال اجرا: {0}', + storageAvailable: 'در دسترس: {0}', + inProgress: 'در حال انجام', + needAttention: 'نیازمند توجه', + normal: 'عادی', + environmentRisk: 'محیط اجرای VM آماده نیست. وابستگی‌ها یا سرویس‌های مجازی‌سازی را اصلاح کنید.', + storageRisk: 'استفاده از مخزن ذخیره‌سازی {0} به {1}% رسیده است.', + abnormalRisk: '{0} ماشین مجازی در وضعیت غیرعادی هستند.', + pausedRisk: '{0} ماشین مجازی متوقف موقت هستند.', + memoryRisk: 'تخصیص حافظه ماشین‌های مجازی به {0}% رسیده است.', cpuLimitHelper: 'CPU در حال حاضر در دسترس: {0} هسته', cpuLimitExceeded: 'CPU از حد مجاز بیشتر است. حداکثر فعلی قابل استفاده: {0} هسته.', memoryLimitHelper: 'حافظه قابل تخصیص فعلی: {0} (میزبان باید {1} حافظه رزرو کند)', @@ -6326,7 +6739,9 @@ const message = { currentSnapshot: 'فعلی', snapshotEmpty: 'اسنپ‌شاتی وجود ندارد', snapshotHelper: - 'A snapshot saves the current VM state as a restore point. Subsequent data changes are recorded in a delta file without changing the original disk. Restoring a snapshot returns the VM to that point in time.', + 'اسنپ‌شات وضعیت فعلی VM را به‌عنوان نقطه بازیابی ذخیره می‌کند. تغییرات بعدی بدون تغییر دیسک اصلی در یک فایل دلتا ثبت می‌شوند. بازیابی اسنپ‌شات، VM را به همان زمان بازمی‌گرداند.', + snapshotOperationHelper: + 'اسنپ‌شات فعلی قابل حذف نیست. بازیابی اسنپ‌شات فقط زمانی ممکن است که ماشین مجازی خاموش باشد.', snapshotRecoverConfirm: 'ماشین مجازی [{1}] به اسنپ‌شات [{0}] بازیابی شود؟ پس از بازیابی، دیسک ماشین مجازی به وضعیت آن اسنپ‌شات برمی‌گردد.', interface: 'رابط شبکه', diff --git a/frontend/src/lang/modules/ja.ts b/frontend/src/lang/modules/ja.ts index 56038b03c..7c9641910 100644 --- a/frontend/src/lang/modules/ja.ts +++ b/frontend/src/lang/modules/ja.ts @@ -11,6 +11,7 @@ const message = { button: { run: '実行', add: '追加', + select: '選択', save: '保存', set: '設定', sync: '同期', @@ -29,7 +30,6 @@ const message = { selectAll: 'すべて選択', login: 'サインイン', close: '閉じる', - off: '閉じる', stop: '停止', start: '開始', view: '表示', @@ -91,6 +91,7 @@ const message = { setDefault: '既定値に戻す', bind: 'バインド', tip: 'ヒント', + reconnect: '再接続', }, operate: { start: '開始', @@ -119,6 +120,9 @@ const message = { card: 'カード', table: 'テーブル', status: '状態', + statusSuccess: '成功', + statusFailed: '失敗', + statusWaiting: '待機中...', records: '記録', group: 'グループ', createdAt: '作成時間', @@ -163,6 +167,7 @@ const message = { deleteSuccess: '正常に削除されました', loginSuccess: '正常にログインしました', operationSuccess: '正常に完了', + operationFailed: '操作に失敗しました', copySuccess: '正常にコピーされました', notSupportOperation: 'この操作はサポートされていません', requestTimeout: 'リクエストがタイムアウトしました。後でもう一度やり直してください', @@ -207,6 +212,7 @@ const message = { username: 'ユーザー名', password: 'パスワード', passkey: 'パスキーでログイン', + otherLoginMethods: 'その他のログイン方法', welcome: 'ようこそ、ユーザー名とパスワードを入力してログインしてください!', errorAuthInfo: '入力したユーザー名またはパスワードは間違っています。再入力してください!', errorMfaInfo: '認証情報が誤っていない、もう一度やり直してください!', @@ -287,6 +293,9 @@ const message = { authBasicPassword: '英字、数字、一般的な特殊文字をサポート、長さ1-72', length128Err: '長さは128文字を超えることはできません', maxLength: '長さは {0} 文字を超えることはできません', + vmName: '英字、数字、"."、"-"、"_"を使用できます。長さは1~64文字で、英字または数字で始める必要があります。', + vmNetwork: + '英字、数字、"."、":"、"-"、"_"を使用できます。長さは1~64文字で、英字または数字で始める必要があります。', alias: '英字、数字、-と_をサポート、長さ1-128、-_で始まるまたは終わることはできません。', }, res: { @@ -306,7 +315,6 @@ const message = { success: '成功', waiting: '待っている', waitForUpgrade: 'アップグレード待機中', - waiting1: '待っている', failed: '失敗した', stopped: '停止', error: 'エラー', @@ -330,7 +338,6 @@ const message = { deny: '拒否されました', accept: '受け入れられました', used: '使用済み', - unUsed: '未使用', starting: '起動', recreating: '再作成', creating: '作成', @@ -472,7 +479,7 @@ const message = { cpuSteal: 'Steal', cpuTop: 'CPU使用率トップ5のプロセス情報', memTop: 'メモリ使用率トップ5のプロセス情報', - loadAverage: '最後の1分で平均を積み込みます|最後の{n}分で平均を読み込みます', + loadAverage: '直近1分の平均負荷 | 直近{0}分の平均負荷', load: '負荷', mount: 'マウントポイント', fileSystem: 'ファイルシステム', @@ -508,6 +515,7 @@ const message = { deleteBackupHelper: 'データベースのバックアップを同時に削除します', delete: '削除操作はロールバックできません、入力してください」', deleteHelper: '「このデータベースを削除します', + deleteUserHelper: '「このユーザーを削除するには入力してください', userBoundDatabases: 'は次のデータベースへのアクセス権があります:', noMysql: 'データベースサービス(mysqlまたはmariadb)', noPostgresql: 'データベースサービスpostgreSql', @@ -547,6 +555,7 @@ const message = { 'このポートは、コンテナの露出したポートです。変更を個別に保存して、コンテナを再起動する必要があります!', loadFromRemote: '同期', userBind: 'バインドユーザー', + noUserBind: '未バインド', userAuthorization: 'ユーザー権限', noUserAuthorization: '権限を付与しない', authorizedDatabaseCount: '{0} データベースに権限付与済み', @@ -809,19 +818,12 @@ const message = { roleMarkdownDescriptions: { 'AGENTS.md': [ 'エージェントの運用ルールと、メモリをどう使うかの説明です。', - '各セッションの開始時に読み込まれます。', 'ルール、優先順位、振る舞い方の詳細を書くのに適しています。', ], - 'SOUL.md': ['人格、口調、境界線。', '毎セッション読み込まれます。'], - 'USER.md': ['ユーザーが誰で、どう呼びかけるか。', '毎セッション読み込まれます。'], - 'IDENTITY.md': [ - 'エージェントの名前、雰囲気、絵文字。', - 'ブートストラップ儀式の中で作成または更新されます。', - ], - 'TOOLS.md': [ - 'ローカルツールや運用上の約束に関するメモ。', - 'ツールの利用可否を制御するものではなく、あくまでガイドです。', - ], + 'SOUL.md': ['人格、口調、境界線。'], + 'USER.md': ['ユーザーが誰で、どう呼びかけるか。'], + 'IDENTITY.md': ['エージェントの名前、雰囲気、絵文字。'], + 'TOOLS.md': ['ローカルツールや運用上の約束に関するメモ。'], 'HEARTBEAT.md': [ 'heartbeat 実行用の任意の簡易チェックリスト。', 'トークン消費を抑えるため短く保ってください。', @@ -830,11 +832,7 @@ const message = { '内部フック有効時に gateway 再起動で実行される任意の起動チェックリスト。', '短く保ち、外部送信には message ツールを使ってください。', ], - 'BOOTSTRAP.md': [ - '初回起動時だけの儀式です。', - 'まったく新しいワークスペースでのみ作成されます。', - '儀式が完了したら削除してください。', - ], + 'BOOTSTRAP.md': ['初回起動時だけの儀式です。', 'まったく新しいワークスペースでのみ作成されます。'], }, duplicateBinding: 'チャネルとアカウント ID の組み合わせは一意である必要があります', accountIdOptional: 'アカウント ID(任意)', @@ -996,9 +994,6 @@ const message = { failureCount: '失敗回数', lastError: '直近のエラー', modelMap: 'モデルマッピング', - apiKeyKeepEmpty: 'API Key(空欄の場合は変更しません)', - apiKeyOnceHint: 'API Key は作成時に一度だけ表示されます。今すぐコピーして保存してください。', - apiKeyOnceSave: 'API Key は一度だけ表示されます。今すぐ保存してください:', qpsLimit: 'QPS 制限', tokenLimit: 'Token 制限', tokenUsed: '使用済み Token', @@ -1140,23 +1135,23 @@ const message = { modelGroupGuide: 'モデルグループには AI ゲートウェイが公開するリクエストモデル名を設定します。上流モデルはアカウントプールのモデルマッピングで設定してください。auto は仮想モデル名のため、モデルグループには追加しません。', modelGroupModelCount: '{0} モデル', - contentCompliance: 'Content Compliance', - contentAction: 'Action', - actionBlock: 'Block', - actionAuditOnly: 'Audit only', + contentCompliance: 'コンテンツコンプライアンス', + contentAction: '処理', + actionBlock: 'ブロック', + actionAuditOnly: '監査のみ', actionDropHistory: '履歴を削除', - severity: 'Severity', - severityHigh: 'High', - severityMedium: 'Medium', - severityLow: 'Low', - sensitiveWord: 'Sensitive word', - sensitiveGroup: 'Sensitive word group', - sensitiveWordCount: 'Words', - normalizedWord: 'Normalized word', - matchedWords: 'Matched words', - matchedGroups: 'Matched groups', - importResult: 'Imported {0}, duplicated {1}, invalid {2}', - auditLogs: 'Audit Logs', + severity: '重大度', + severityHigh: '高', + severityMedium: '中', + severityLow: '低', + sensitiveWord: '機密語', + sensitiveGroup: '機密語グループ', + sensitiveWordCount: '語数', + normalizedWord: '正規化された語', + matchedWords: '一致した語', + matchedGroups: '一致したグループ', + importResult: 'インポート {0} 件、重複 {1} 件、無効 {2} 件', + auditLogs: '監査ログ', smartRoute: 'スマートルーティング', smartRouteGuideTitle: 'クライアントで model=auto を使用してスマートルーティングに入ります', smartRouteGuideReady: @@ -1222,9 +1217,9 @@ const message = { latencyMs: 'レイテンシ(ms)', smartRouteSettingGuide: '有効化後、model=auto のリクエストだけがスマートルーティングを使用します。簡単モデルグループは低コストタスク、複雑モデルグループはコード分析、設計、障害調査などに使います。', - sampleLabelPlaceholder: 'simple / complex / high', + sampleLabelPlaceholder: '簡単 / 複雑 / 高', sampleImportPlaceholder: '1行に1つのサンプル', - apiKeyCount: '数量', + apiKeyCount: 'API キー数', }, skillsHub: { title: 'Skills Hub', @@ -1476,14 +1471,14 @@ const message = { streamableHttpPathHelper: '例:/mcp、他のサーバーと重複しないように注意してください', npxHelper: 'npx またはバイナリで起動する mcp に適しています', uvxHelper: 'uvx で起動する mcp に適しています', - protocolVersion: 'Protocol Version', + protocolVersion: 'プロトコルバージョン', protocolVersionHelper: - 'Only used by stateless Streamable HTTP to auto-initialize the downstream stdio MCP Server', + 'ステートレス Streamable HTTP で、下流の stdio MCP Server を自動初期化する場合にのみ使用します', gatewayArgsHelper: '引数は supergateway の起動コマンドに追加されます。1Panel が管理する転送方式、ポート、パス、プロトコルの引数は変更できません', - testConnection: 'Test Connection', - connectionSuccess: 'Connection succeeded', - connectionFailed: 'Connection failed', + testConnection: '接続テスト', + connectionSuccess: '接続に成功しました', + connectionFailed: '接続に失敗しました', }, tensorRT: { llm: 'TensorRT LLM', @@ -1556,9 +1551,10 @@ const message = { last4Hour: '最後の4時間', lastHour: '最後の時間', last10Min: '最後の10分', + cleanLogscope: 'クリーンアップ種別', cleanLog: 'クリーンログ', downLogHelper1: 'これにより、Container {0}からすべてのログをダウンロードします。続けたいですか?', - downLogHelper2: 'これにより、コンテナ{0}から最近の{0}ログをダウンロードします。続けたいですか?', + downLogHelper2: 'コンテナ {0} から最新の {1} 行のログをダウンロードします。続行しますか?', cleanLogHelper: 'これには、コンテナを再起動する必要があり、元に戻すことはできません。続けたいですか?', newName: '新しい名前', source: 'リソースの使用', @@ -1601,8 +1597,6 @@ const message = { privileged: '特権', privilegedHelper: 'コンテナがホストに特定の特権操作を実行できるようにします。これにより、コンテナのリスクが増加する可能性があります。注意して使用してください!', - editComposeHelper: - '注意:環境変数は1panel.envファイルに保存され、composeでenv_fileを介して参照する必要があります。\n変数はコンテナ内部でのみ有効であり、composeファイルの${VAR}置換には参加しません。', upgradeHelper: 'リポジトリ名/画像名:画像バージョン', upgradeWarning2: 'アップグレード操作では、コンテナを再構築する必要があります。続けたいですか?', oldImage: '現在の画像', @@ -1683,7 +1677,7 @@ const message = { exportImage: '画像エクスポート', size: 'サイズ', tag: 'タグ', - tagHelper: '1行に1つ。たとえば、 nkey1 = value1 nkey2 = value2', + tagHelper: '1行に1つ入力します。例:\nkey1=value1\nkey2=value2', imageNameHelper: '画像名とタグ、例:nginx:最新', cleanBuildCache: 'クリーンビルドキャッシュ', delBuildCacheHelper: @@ -1719,8 +1713,9 @@ const message = { repoHelper: 'ミラーリポジトリ/組織/プロジェクトが含まれていますか?', auth: '認証が必要です', mirrorHelper: - '複数のミラーがある場合、たとえばnewlinesを表示する必要があります:Nhttp://xxxxxxMDaocloudIo Nhttps://xxxxxxMirrorAliyuncsCom', - registrieHelper: '複数のプライベートリポジトリが存在する場合、たとえばnewlinesを表示する必要があります。', + '複数のミラーがある場合は1行に1つ入力します。例:\nhttp://xxxxxx.m.daocloud.io\nhttps://xxxxxx.mirror.aliyuncs.com', + registrieHelper: + '複数のプライベートレジストリがある場合は1行に1つ入力します。例:\n172.16.10.111:8081\n172.16.10.112:8081', compose: '構成|作曲', composeFile: 'オーケストレーションファイル', fromChangeHelper: 'ソースを切り替えると、現在の編集されたコンテンツがきれいになります。続けたいですか?', @@ -1803,7 +1798,8 @@ const message = { macAddr: 'MACアドレス', exportHelper: '選択したイメージを1つのtarにエクスポートします。', goSetting: '設定へ', - mirrorsHelper: '', + mirrorsHelper: + 'イメージ操作ではレジストリミラー URL を優先して使用します。空欄にするとレジストリミラーを無効にします。', }, cronjob: { importHelper: @@ -1819,7 +1815,6 @@ const message = { stopHelper: 'この操作により現在のタスクの実行が強制停止されます。続行しますか?', log: 'バックアップログ', logHelper: 'バックアップシステムログ', - ogHelper1: '1.1パネルシステムログ', logHelper2: '2。サーバーのSSHログインログ', logHelper3: '3.すべてのサイトログ', containerCheckBox: 'コンテナ内(コンテナコマンドを入力する必要はありません)', @@ -1889,9 +1884,7 @@ const message = { perNHour: 'N時間ごと)', perNMinute: '毎分(s)', perNSecond: '毎秒毎回', - per: '毎', day: '日', - dayUnit: 'd', monday: '月曜日', tuesday: '火曜日', wednesday: '水曜日', @@ -2034,7 +2027,6 @@ const message = { connTestFailed: '接続は利用できません。接続情報を確認してください。', host: 'ホスト|ホスト', createConn: '新しい接続', - manageGroup: 'グループを管理します', noHost: 'ホストはありません', groupChange: 'グループを変更します', expand: 'すべて拡張します', @@ -2112,8 +2104,7 @@ const message = { dnsHelper: 'DNSサーバー', dnsAlert: '注意!/etc/resolv.confファイルの構成を変更すると、システムが再起動した後、ファイルがデフォルト値に復元されます。', - dnsHelper1: - '複数のDNSエントリがある場合は、新しい行に表示する必要があります。例えば、 n114.114.114.114 n8.8.8.8', + dnsHelper1: '複数の DNS を設定する場合は1行に1つ入力します。例:\n114.114.114.114\n8.8.8.8', hostsHelper: 'ホスト名解像度', hosts: 'ドメイン', hostAlert: '隠されたコメントレコード、すべての構成ボタンをクリックして表示または設定してください', @@ -2280,6 +2271,7 @@ const message = { nodes: 'ノード', commands: 'クイックコマンド', opsReport: '運用レポート', + ops_report: '運用レポート', users: 'ユーザー管理', roles: 'ロール', auth: 'ログイン認証', @@ -2300,10 +2292,6 @@ const message = { fileDirNum: '{0} 個のディレクトリ、{1} 個のファイル、', currentDir: '現在のディレクトリ', dir: 'フォルダ', - upload: 'アップロード', - uploadFile: '@:file.upload@.lower:file.file', - uploadDirectory: '@:file.upload@.lower:file.dir', - download: 'ダウンロード', fileName: 'ファイル名', search: '検索', mode: '権限', @@ -2319,7 +2307,6 @@ const message = { role: '権限', info: '属性', linkFile: 'ソフトリンク', - batchoperation: 'バッチ操作', shareList: '共有リスト', fileTools: 'ファイルツール', aiSearchHitLines: '一致した行', @@ -2632,9 +2619,8 @@ const message = { port: 'ポート', portHelper: 'SSHサービスが耳を傾けるポートを特定します。', listenAddress: '住所を聞いてください', - allV4V6: '0.0.0.0: {0 }(IPv4)および::: {0}(IPv6)', - listenHelper: - 'IPv4とIPv6の両方の設定を空白のままにしておくと、「0.0.0.0:0:0:0}」と「::: {0}(IPv6)」で聞きます。', + allV4V6: '0.0.0.0:{0}(IPv4)および :::{0}(IPv6)', + listenHelper: 'IPv4 と IPv6 の両方を空欄にすると、0.0.0.0:{0}(IPv4)および :::{0}(IPv6)で待ち受けます。', addressHelper: 'SSHサービスが耳を傾けるアドレスを指定します。', permitRootLogin: 'ルートユーザーログインを許可します', rootSettingHelper: 'ルートユーザーのデフォルトのログインメソッドは「SSHログインを許可」です。', @@ -2774,7 +2760,7 @@ const message = { apiKey: 'APIキー', apiKeyHelper: 'APIキーは、サードパーティアプリケーションに使用されてAPIにアクセスします。', ipWhiteList: 'IP AllowList', - ipWhiteListEgs: '1行に1つ。たとえば、 n172.161.10.111 n172.161.10.0/24', + ipWhiteListEgs: '1行に1つ入力します。例:\n172.161.10.111\n172.161.10.0/24', ipWhiteListHelper: 'AllowList内のIPSはAPIにアクセスできます、0.0.0.0/0(すべての IPv4)、::/0(すべての IPv6)', apiTrustedProxies: 'API信頼済みプロキシ', apiTrustedProxiesHelper: @@ -2788,7 +2774,6 @@ const message = { systemIPWarning: '現在のノードにはデフォルトアクセスアドレスが設定されていません。パネル設定から設定してください!', systemIPWarning1: '現在のサーバーアドレスは{0}に設定されており、クイックリダイレクトは不可能です!', - defaultNetwork: 'ネットワークカード', syncTime: 'サーバー時間', timeZone: 'タイムゾーン', timeZoneChangeHelper: 'タイムゾーンを変更するには、サービスを再起動する必要があります。続けたいですか?', @@ -2835,7 +2820,7 @@ const message = { codeWarning: '現在の承認コード形式が正しくありません。もう一度確認してください!', code: '認証コード', codeHelper: - '[取得]ボタンをクリックしてから、リダイレクトリンクの「コード」の後にコンテンツをログインしてコピーします。この入力ボックスに貼り付けます。特定の手順については、公式のドキュメントを参照してください。', + '「取得」をクリックし、{0} にログインします。リダイレクト先 URL の「code」以降をコピーしてこの入力欄に貼り付けてください。詳しい手順は公式ドキュメントを参照してください。', googleHelper: 'まずGoogleアプリケーションを作成し、クライアント情報を取得してフォームに記入し、取得ボタンをクリックしてください。具体的な操作は公式ドキュメントを参照してください。', loadCode: '取得する', @@ -3057,7 +3042,7 @@ const message = { editIgnoreRule: '@:commons.button.edit @.lower:setting.ignorerule', ignoreHelper: 'このルールは、スナップショットの作成中に1パネルデータディレクトリを圧縮およびバックアップするために使用されます。デフォルトでは、ソケットファイルは無視されます。', - ignoreHelper1: '1行に1つ。たとえば、 n*.log n/opt/1panel/cache', + ignoreHelper1: '1行に1つ入力します。例:\n*.log\n/opt/1panel/cache', panelInfo: '1パネルの基本情報を書いてください', panelBin: 'バックアップ1パネルシステムファイル', daemonJson: 'バックアップDocker構成ファイル', @@ -3152,7 +3137,6 @@ const message = { upgrading: 'アップグレード中、しばらくお待ちください...', versionHelper: '命名規則: [メジャー].[機能].[バグ修正]。例:', upgradeCheck: '更新を確認', - panelSSLHelper: 'パネルSSL自動更新後、1Panelサービスを手動再起動してください。', }, license: { offLine: 'オフライン版', @@ -3180,12 +3164,11 @@ const message = { authorizedUser: '認定ユーザー', lostHelper: 'ライセンスは、再試行の最大数に達しました。商用版機能が適切に機能していることを確認するには、手動で同期ボタンをクリックしてください。詳細: ', - disableHelper: - 'ライセンスの同期の検証は失敗しました。商用版機能が適切に機能していることを確認するには、手動で同期ボタンをクリックしてください。詳細: ', quickUpdate: 'クイックアップデート', power: '許可', unbindHelper: 'すべての商用版関連設定は、バインディングを解除した後にクリーニングされます。続けたいですか?', importLicense: 'ライセンス', + import: 'インポート', securityWarningTitle: 'クラック版または出所不明のライセンスを使用しないでください。', securityWarningContent: '1Panel はシステム管理者権限を持つユーザーで実行する必要があります。非公式ライセンスや改ざんされたバージョンは、サーバーの制御不能、データ漏えいなどの重大なセキュリティリスクを引き起こす可能性があります。ライセンスとインストールパッケージは FIT2CLOUD 公式チャネルから入手してください。', @@ -3240,6 +3223,7 @@ const message = { '商用版にアップグレードすると、マルチノードのアプリ、Web サイト、データベース、スケジュールタスクを一元管理できます。', fileExchange: '商用版にアップグレードすると、複数サーバー間でファイルをすばやく転送できます。', cluster: '商用版にアップグレードすると、MySQL/Postgres/Redis のプライマリ/レプリカ構成を管理できます。', + vllm: '商用版にアップグレードすると、1Panel で vLLM サービスのデプロイ、設定、ライフサイクル操作、タスク追跡を一元管理できます。', 'model-downloader': '商用版にアップグレードすると、HuggingFace、ModelScope、または互換ミラーからローカルモデルファイルを検索、ダウンロード、管理できます。モデルディレクトリとダウンロードタスクを一元管理できます。', exceptionalHelper: @@ -3294,7 +3278,7 @@ const message = { dockerHelper: 'コンテナ、イメージ、ボリューム、ビルドキャッシュなどのファイル', volumes: 'ボリューム', buildCache: 'コンテナビルドキャッシュ', - appTmpDownload: 'Archivo de descarga temporal de la aplicación', + appTmpDownload: 'アプリ一時ダウンロードファイル', unknownWebsiteLog: '未関連ウェブサイトログバックアップファイル', snapshot: 'システムスナップショット一時ファイル', }, @@ -3456,7 +3440,6 @@ const message = { ftpHelper: 'Webサイトを作成すると、対応するFTPアカウントが作成され、FTPディレクトリがWebサイトディレクトリにリンクされます。', remark: '述べる', - manageGroup: 'グループを管理します', groupSetting: 'グループ管理', createGroup: 'グループを作成します', appNew: '新しいアプリケーション', @@ -3521,7 +3504,6 @@ const message = { nginxPer: 'パフォーマンスチューニング', neverExpire: '一度もない', setDefault: 'デフォルトとして設定します', - default: 'デフォルト', deleteHelper: '関連するアプリケーションステータスは異常です。確認してください', toApp: 'インストールされているリストに移動します', cycle: 'サイクル', @@ -3576,7 +3558,7 @@ const message = { disableHTTPS: 'httpsを無効にします', disableHTTPSHelper: 'HTTPSを無効にすると、証明書関連の構成が削除されますが、続行しますか?', SSLHelper: - '注:違法なWebサイトにSSL証明書を使用しないでください。 nif httpsアクセスを開いた後に使用できません。.', + '注意:違法な Web サイトに SSL 証明書を使用しないでください。\n有効化後に HTTPS でアクセスできない場合は、セキュリティグループでポート 443 が許可されているか確認してください。', SSLConfig: '証明書設定', SSLProConfig: 'プロトコル設定', supportProtocol: 'プロトコルバージョン', @@ -3636,7 +3618,6 @@ const message = { proxyHelper1: 'このディレクトリにアクセスすると、ターゲットURLのコンテンツが返されて表示されます。', proxyPassHelper: 'ターゲットURLは有効でアクセス可能でなければなりません。', proxyHostHelper: 'リクエストヘッダーのドメイン名をプロキシサーバーに渡します。', - replacementHelper: '最大5つの交換を追加できます。交換が不要な場合は、空白のままにしてください。', modifier: '一致するルール', modifierHelper: '例: "="は正確な一致、 "〜"は通常の一致、^〜」はパスの始まりなどと一致します。', replace: 'テキスト置換', @@ -3741,7 +3722,6 @@ const message = { subsite: 'サブサイト', subsiteHelper: 'サブサイトは、既存のPHPまたは静的ウェブサイトのディレクトリをルートディレクトリとして選択できます。', - parentWebsite: '親ウェブサイト', deleteSubsite: '現在のウェブサイトを削除するには、まずサブサイト {0} を削除する必要があります。', loadBalance: 'ロードバランシング', server: 'ノード', @@ -3772,7 +3752,6 @@ const message = { cacheExpire: 'キャッシュ有効期限', shareCacheHelper: '1Mのメモリで約8000個のキャッシュオブジェクトを保存できます。', cacheLimitHelper: '制限を超えると、古いキャッシュが自動的に削除されます。', - cacheExpireHelper: '有効期限内にヒットしないキャッシュは削除されます。', realIP: 'リアルIP', ipFrom: 'IPソース', ipFromHelper: @@ -3834,8 +3813,6 @@ const message = { syncHtmlHelper: 'PHP と静的ウェブサイトに同期', wafValueHelper: '値', parentWbeiste: '親サイト', - shareCahe: 'キャッシュ数メモリサイズ', - shareCaheHelper: 'メモリ1Mあたり約8000件のキャッシュを保存可能', cacheExpireJHelper: '有効期限後に未ヒットならキャッシュを削除', }, php: { @@ -4209,7 +4186,6 @@ const message = { netRecv: '下流', numConnections: '接続', startTime: '開始時間', - state: '州', running: 'ランニング', sleep: '寝る', stop: '停止', @@ -4367,7 +4343,7 @@ const message = { 'ご注意: あなたのEnterprise Editionライセンスは{0}日後に終了し、すべてのEnterprise Edition機能が使用できなくなります。継続的な使用のために速やかに更新してください。', expiresProAlert: 'ご注意: あなたのPro Editionライセンスは{0}日後に終了し、すべてのPro Edition機能が使用できなくなります。継続的な使用のために速やかに更新してください。', - menu: 'Рro', + menu: 'Pro', upage: 'AIウェブサイトビルダー', proAlert: 'この機能を使用するには商用版にアップグレードしてください', opsReport: { @@ -4425,8 +4401,10 @@ const message = { scorePanelHTTPSDisabled: 'パネルHTTPSが無効です', scoreSSHRootLogin: 'SSH Rootログインが許可されています', scoreSSHPasswordAuth: 'SSHパスワード認証が有効で、鍵認証が無効です', + scoreSSLExpired: '{0} 証明書の有効期限が切れています', scoreSSLHigh: '{0} 証明書残り {1} 日', scoreSSLMedium: '{0} 証明書残り {1} 日', + scoreWebsiteExpired: '{0} Web サイトの有効期限が切れています', scoreWebsiteExpire: '{0} Webサイト残り {1} 日で期限切れ', scoreWebsiteHTTP: '{0} HTTPSが有効ではありません', scoreWebsiteStopped: '{0} 状態が異常です', @@ -4472,6 +4450,7 @@ const message = { panelLogin: 'パネルログイン', sshLogin: 'SSHログイン', failedRecord: '失敗記録', + expired: '期限切れ', expiredDays: '{0} 日前に期限切れ', remainingDays: '{0} · 残り {1} 日', enabled: '有効', @@ -4742,9 +4721,9 @@ const message = { abnormalSites: '異常サイト', count5xxSource: '5xxリクエストで集計', wafIntercept: 'WAF遮断', - highRiskHit: '高リスクヒット', websiteMonitorDisabledOrNoData: 'Webサイト監視が無効または監視データがありません', wafDisabledOrNoData: 'WAFが無効または遮断データがありません', + serviceEnabledButAbnormal: '有効ですが、異常な状態です', noWafData: 'WAF遮断データがありません', sourceIP: '送信元IP', hitCount: 'ヒット数', @@ -4805,6 +4784,7 @@ const message = { successRate: '成功率', failedJobs: '失敗タスク', recentRecoveryPoint: '最新復元ポイント', + disabledCronjobTasks: '無効なスケジュールタスク', remoteCoverage: 'リモートカバレッジ', recent7Days: '過去7日間', taskTypeStats: 'タスク種別統計', @@ -4827,6 +4807,7 @@ const message = { cronjobReasonDisabled: '{0} 件のタスクが無効', cronjobReasonLocalOnlyBackup: 'ローカルのみのバックアップ {0} 件', cronjobReasonNormal: 'スケジュールタスクの実行とバックアップ範囲は正常です', + riskLow: '低リスク', viewFailedRecords: '失敗タスクを表示', viewCronjobTasks: 'スケジュールタスクを表示', checkBackupTasks: 'バックアップタスクを確認', @@ -4923,6 +4904,14 @@ const message = { authManage: '認証管理', auth: { providerNavigation: '認証プロバイダー', + defaultNode: 'デフォルトノード', + defaultNodePlaceholder: 'ノードを選択してください', + defaultNodeHelper: '新規ユーザーにのみ使用します。', + defaultNodeRequired: '有効なデフォルトノードを選択してください。', + nodesLoadFailed: 'ノードの読み込みに失敗しました。デフォルトノードを選択する前に再試行してください。', + nodeHandling: 'ノードの処理', + assignDefaultNode: 'デフォルトノードを割り当て: {node}', + keepExistingNode: '既存のノード権限を保持', providers: { ldap: 'AD/LDAP', passkey: 'Passkey', @@ -4950,7 +4939,404 @@ const message = { planned: '計画済み', plannedTitle: '{0} 認証設定', plannedDesc: 'この認証プロバイダーは計画されており、まだ利用できません。', + oidc: { + accessMode: '接続モード', + accessModeDesc: + 'アイデンティティ プロバイダーがサポートする場合は常に標準の Discovery を使用します。', + actionCreate: 'ユーザーの作成', + actionKeepName: '現在のユーザー名を保持', + actionPending: '結果を待機中', + actionReject: 'ログインの拒否', + actionUpdate: 'アイデンティティ情報の更新', + advanced: '詳細設定', + advancedDesc: 'プロバイダーが互換性オプションを必要としない限り、安全なデフォルトを維持します。', + assignDefaultRole: 'デフォルトのロールの割り当て: {role}', + authorizationEndpoint: 'Authorization Endpoint', + authorizationEndpointInvalid: '有効な Authorization Endpoint を入力してください。', + authorizationFlow: '認証フロー', + automatic: '自動', + automaticPolicy: '自動処理ポリシー', + automaticPolicyDesc: 'これらのルールはバックエンドによって適用され、管理者スイッチではありません。', + basic: '基本設定', + basicDesc: 'プロバイダー モードを選択し、クライアントとコールバックを設定します。', + browserTest: 'ブラウザーテストログイン', + browserTestConflict: 'ID は確認されましたが、ユーザー名が競合しています。', + browserTestConflictHelper: + 'マッピングされたユーザー名は別の ID に属するため、自動的に関連付けません。', + browserTestExpired: 'ブラウザ テストの有効期限が切れました。', + browserTestExpiredHelper: + '新しいブラウザ テストを開始し、有効期限が切れる前に認証を完了してください。', + browserTestFailed: 'ブラウザ テストに失敗しました', + browserTestFailedHelper: + 'ID プレビューを完了できませんでした。ローカライズされたバックエンド エラーを確認します。', + browserTestIsolation: + '実際の認証ラウンドトリップを実行しますが、ユーザーの作成や更新、ロールの割り当て、認証済みパネルセッションの作成は行いません。', + browserTestPopupBlocked: + 'このサイトのポップアップを許可してから、ブラウザ テストを再度開始してください。', + browserTestPopupClosed: 'テストが完了する前に認証ウィンドウが閉じられました。', + browserTestSuccess: 'プロバイダーの検証に成功しました', + browserTestSuccessHelper: 'ユーザーやセッションを変更せずに ID マッピングがプレビューされました。', + browserTestTitle: 'OIDC ブラウザー テスト ログイン', + browserTestWaiting: 'プロバイダーの認証を待機中', + browserTestWaitingHelper: + '新しいブラウザウィンドウでログインを完了してください。このページは自動的に更新されます。', + callbackCopied: 'OIDC コールバック URL がコピーされました。', + callbackURL: 'コールバック URL', + callbackURLHelper: + 'この URL を ID プロバイダーのクライアントで許可するコールバック URL に追加してください。', + cancelClearSecret: 'クリアをキャンセル', + clearSecret: 'シークレットのクリア', + clearSecretConfirm: 'Client Secret は保存後にのみ削除されます。続行しますか?', + clientAuthMethod: 'クライアント認証方法', + clientAuthMethodHelper: 'ID プロバイダーでこのクライアントに設定した認証方式を選択してください。', + clientAuthMethodRequired: 'クライアント認証方法を選択してください。', + clientID: 'Client ID', + clientIDRequired: 'Client ID を入力します。', + clientSecret: 'Client Secret', + clockSkew: 'トークン時刻の許容差', + clockSkewHelper: + 'ID プロバイダーと 1Panel のわずかな時刻差を許容します。通常は 60 秒のままにしてください。', + clockSkewRequired: 'トークン時刻の許容差を入力してください。', + compatibilityMode: '互換モード', + compatibilityModeHelper: + '不完全な Discovery または書き換えられたエンドポイントにのみ使用します。コア OIDC 検証は有効なままです。', + configurationFailedHelper: + 'テストは失敗しました。このページには、ローカライズされたバックエンド エラーのみが表示されます。', + configurationFailedTag: 'テストに失敗しました', + configurationHighRiskPassed: '設定は合格しましたが、高リスクの互換性オプションが含まれています。', + configurationHighRiskTag: '高リスクの設定は合格しました', + configurationNotTested: '現在の設定はテストされていません。', + configurationNotTestedTag: '未テスト', + configurationPassed: '現在の構成はセキュリティと機能のチェックに合格しました。', + configurationPassedTag: 'テストに合格しました', + configurationStaleHelper: '設定が変更されました。保存する前に再度テストしてください。', + configurationStaleTag: '結果の有効期限が切れました', + configurationTestMeta: + '{time} にテストし、{duration} ミリ秒で完了しました。プロバイダーの未加工レスポンスは保存されません。', + configurationTestResult: '構成テスト結果', + configurationTestResultDesc: + 'これは、Discovery と機能のみをチェックします。認証コードを交換したり、Client Secret を証明したりするものではありません。エンドツーエンドの検証にはブラウザのテスト ログインを使用します。', + configurationTestSuccess: 'OIDC 構成テストは成功しました。', + configurationTesting: '現在の OIDC 構成をテストしています…', + configurationTestingTag: 'テスト中', + configureSecret: 'Client Secret を設定', + conflictExistingRename: 'バインドされた subject が、すでに使用中の新しいユーザー名を返します。', + conflictExistingRenameResult: + '既存の User.Name を保持し、バインドされたユーザーがサインインできるようにします。', + conflictLDAP: 'LDAP ユーザー', + conflictLocal: 'ローカル ユーザー', + conflictNewAvailable: '新しい subject とマッピングされたユーザー名が利用可能', + conflictNewAvailableResult: 'エンタープライズ ユーザーを作成し、デフォルトのロールを割り当てる', + conflictNone: '競合なし', + conflictOIDC: '別の OIDC ID', + conflictOccupied: + 'マッピングされたユーザー名は、ローカルユーザー、LDAP ユーザー、または別の OIDC ID に属します。', + conflictOccupiedResult: '新しいアイデンティティを拒否します。自動的にバインドまたはマージしない', + conflictType: '競合タイプ', + connectionSecurity: '接続セキュリティ', + connectionSecurityDesc: + 'TLS ポリシーは、Discovery、Token、JWKS、および UserInfo リクエストに適用されます。', + connectionTest: '接続と構成のテスト', + connectionTestCompatibilityDesc: + 'カスタムエンドポイントとプロトコルのセキュリティポリシーを検証します。', + connectionTestStandardDesc: 'エンドポイントと機能は、Issuer から自動的に検出されます。', + connectionTestTab: '接続テスト', + customCA: 'カスタム CA', + customCAHelper: 'この認証ソースにのみ適用され、ログには書き込まれません。', + customCARequired: 'カスタム CA 証明書を指定してください。', + defaultRole: 'デフォルトの役割', + defaultRoleHelper: 'ユーザーの初回作成時だけ割り当て、以降のログインではロールを変更しません。', + defaultRolePlaceholder: 'ロールを選択してください。', + defaultRoleRequired: '有効なデフォルトのロールを選択してください。', + disableAfterSave: 'OIDC は保存後に無効になります。', + disableConfirm: + 'OIDC を無効にすると、このソースのユーザーのアクセスが直ちに無効になります。続行しますか?', + disableDiscardConfirm: + 'OIDC の無効化は緊急処置です。ログイン エントリが閉じられるだけで、このソースのユーザーのアクセスは直ちに無効になります。 Client Secret の変更を含む、このページのその他の未保存の変更は破棄されます。続行しますか?', + disableTitle: 'OIDC を無効にする', + disabled: '無効', + discoveryAllowlist: 'Discovery セキュリティ許可リスト', + enable: '有効化', + enableAfterSave: 'OIDC は保存が成功すると有効になります。', + enabled: '有効', + endSessionEndpoint: 'End Session Endpoint', + endSessionEndpointHelper: + '将来の使用のために保存されます。プロバイダー起点のログアウトは、このリリースには含まれていません。', + endSessionEndpointInvalid: '有効な End Session Endpoint を入力してください。', + endpointDiscoveryPlaceholder: '接続テスト後に表示されます', + firstLogin: '初回ログイン', + firstLoginPolicy: + 'ローカル エンタープライズ ユーザーを作成し、設定されたデフォルトのロールを割り当てます。', + fixedAuthorizationCode: 'Authorization Code Flow', + fixedNoTokenPersistence: 'Token、Claims、および verifier は永続化されません。', + fixedSecurityPolicy: '常に適用されます。設定は必要ありません', + fixedStateNonce: 'ワンタイム state および nonce', + fixedTokenValidation: 'ID Token 署名と Claims 検証', + highRiskSaveConfirm: + 'この有効な設定には、高リスクの互換性オプションが含まれています。隔離された環境にそれらが必要であることを確認します。', + highRiskTitle: '高リスク OIDC 構成', + hs256Compatibility: 'HS256 (互換性)', + hs256KeyHelper: 'HS256 は常にこのソースの Client Secret を使用し、別の署名キーを受け入れません。', + hs256Warning: + 'HS256 は ID Token 署名に共有対称シークレットを使用します。プロバイダーが非対称アルゴリズムを使用できない場合にのみ使用してください。', + identityBindingPolicy: + 'ID は AuthSourceID + issuer + subject に固定されます。ユーザー名が一致しても別のアカウントへ自動的に関連付けません。', + identityMissing: 'ID が無効', + issuer: 'Issuer URL', + issuerHelper: 'ID Token の値と Discovery issuer はこの値と正確に一致する必要があります。', + issuerInvalid: + 'クエリまたはフラグメントを含まない有効な HTTP または HTTPS の Issuer URL を入力してください。', + issuerRequired: 'Issuer URL を入力してください。', + jwksRotation: 'JWKS の自動回転', + jwksURI: 'JWKS URI', + jwksURIHelper: '署名キーのソースが JWKS の場合、非対称署名に必要です。', + jwksURIInvalid: '選択した署名キー ソースに有効な JWKS URI を入力します。', + keepExistingRole: '既存のロールとローカル権限を保持します', + localSecurityData: 'ローカル セキュリティ データ', + localSecurityDataPolicy: 'ロール、MFA、API Keys、Passkeys、ローカル権限は上書きしません。', + localCredentialsManaged: + 'ユーザー名とローカルパスワードは OIDC によって管理されており、ここでは編集できません。ロール、権限、MFA、API Keys、Passkeys はローカルのままです。', + localUserFields: 'ローカル ユーザー フィールド', + localUserFieldsDesc: + '最初のリリースでは User.Name のみがマッピングされ、JSON マッピング式は使用されません。', + loginWith: '{provider} でログイン', + manualEndpoints: 'カスタムエンドポイント', + manualEndpointsDesc: + 'Discovery が不完全な場合、またはアップストリーム ゲートウェイがエンドポイントを書き換える場合にのみ使用します。', + mappingResult: 'マッピング結果', + mode: '接続モード', + modeRequired: '接続モードを選択します。', + nameClaim: 'ユーザー名 Claim', + nameClaimHelper: 'ユーザー名を含むフィールド名を入力してください(例:preferred_username)。', + nameClaimRequired: 'ユーザー名 Claim を入力してください。', + nameConflict: '名前の競合ポリシー', + panelURL: '1Panel 公開 URL', + panelURLHTTPWarning: + 'HTTP は認可応答を保護しません。プロバイダーが許可した隔離されたプライベート環境でのみ使用してください。', + panelURLHelper: + 'ユーザーが 1Panel へアクセスするアドレスを入力してください。コールバック URL の生成に使用します。', + panelURLInvalid: 'スキーム、ホスト、およびオプションのポートのみを含むオリジンを入力します。', + panelURLRequired: '1Panel の公開 URL を入力してください。', + pkceDisabled: '無効(互換性のみ)', + pkceDisabledWarning: 'PKCE を無効にすると、認証コードの傍受に対する保護が低下します。', + pkceHelper: 'S256 を優先します。 plain チャレンジ メソッドは決して提供されません。', + pkceS256: 'S256 (推奨)', + plannedHandling: '計画された処理', + privateNetworkIdP: 'プライベート ネットワーク IdP', + privateNetworkIdPHelper: + 'プライベート アドレスを明示的に許可します。メタデータ、ループバック、リンクローカル、リダイレクト、および DNS リバインドはブロックされたままです。', + privateNetworkWarning: 'プライベート ネットワーク アクセスは、この認証ソースに対して有効です。', + protocolCompatibility: 'プロトコルの互換性', + protocolCompatibilityDesc: 'ID Token 署名の検証を無効にすることはできません。', + providerAndClient: 'プロバイダーとクライアント', + providerAndClientDesc: + 'Client Secret は置換またはクリアのみ可能で、ページから返されることはありません。', + providerCapabilities: 'プロバイダーの機能', + recentTestSuccess: '最後のテストは成功しました: {0}', + recommended: '推奨', + rejectPlain: 'plain 拒否されました', + replaceSecret: 'シークレットの置換', + requestAndClaims: 'リクエストと属性', + requestAndClaimsDesc: '認可スコープ、ユーザー情報の補完、リクエストパラメーターを設定します。', + requestTimeout: 'リクエスト タイムアウト', + requestTimeoutRequired: 'リクエスト タイムアウトを入力します。', + restore: '復元', + restored: '最後に保存された OIDC 設定が復元されました。', + result: '結果', + rolesLoadFailed: + 'ロールをロードできませんでした。デフォルトのロールを選択する前に再試行してください。', + roleHandling: 'ロール処理', + scenario: 'シナリオ', + scopes: '認可スコープ', + scopesHelper: 'openid を含める必要があります。複数のスコープはスペースで区切ってください。', + scopesRequired: 'Scopes には openid が含まれている必要があります。', + seconds: '秒', + secretClearHelper: 'クリア後、OIDC を再度有効にする前に、新しい Client Secret が必要です。', + secretConfigured: '設定済み', + secretNotConfigured: '未設定', + secretPlaceholder: '新しいClient Secretを入力してください', + secretReplaceHelper: + '保存すると新しいシークレットで置き換えられます。OIDC Provider 側の Client Secret も更新してください。', + secretRequiredHelper: 'OIDC を有効にする前に、Client Secret を設定してください。', + secretRequiredToEnable: 'OIDC を有効にする前に、Client Secret を設定してください。', + secretSavedHelper: '暗号化して保存されています。空欄にすると現在のシークレットを保持します。', + secretWaiting: '入力待ち', + secretWillClear: 'クリアされます', + secretWillReplace: '置き換えられます', + signingAlgorithm: 'ID Token 署名アルゴリズム', + signingAlgorithmHelper: 'バックエンド セキュリティ ホワイトリスト内のアルゴリズムのみが有効です。', + signingKey: '署名キー', + signingKeyClientSecret: 'Client Secret (HS256 のみ)', + signingKeyJWKS: '自動ローテーション付きの JWKS URI', + signingKeySource: '署名キーのソース', + signingKeySourceHelper: 'JWKS を推奨します。静的公開キーは自動的にローテーションできません。', + signingKeyStatic: '静的 JWK または PEM 公開キー', + standardDiscovery: '標準 OIDC Discovery', + standardDiscoveryDesc: '1Panel はエンドポイントと機能を検出し、生のドキュメントは保存しません。', + standardMode: '標準モード', + standardModeHelper: 'エンドポイント、署名機能、Issuer の PKCE サポートを確認します。', + standardProtocolPolicy: '標準プロトコル ポリシー', + standardProtocolPolicyDesc: + '署名機能は自動的にネゴシエートされます。ここには署名キーは入力されません。', + staticSigningKey: '静的署名公開キー', + staticSigningKeyHelper: + '公開キー素材のみ使用できます。プロバイダーのキーが変更された場合は手動でローテーションしてください。', + staticSigningKeyPlaceholder: 'JWK、JWKS JSON、または PEM 公開キーを貼り付けます。', + staticSigningKeyRequired: '静的署名公開キーを指定します。', + staticSigningKeyWarning: + '静的署名キーは自動的にローテーションできません。プロバイダーがキーをローテーションする前に更新してください。', + settingLoadFailed: 'OIDC 設定を読み込めませんでした。', + settingLoadFailedHelper: + '現在の設定に空のデフォルト設定が保存されないように、フォームはロックされています。接続が回復してから再試行してください。', + subsequentLogin: 'その後のログイン', + subsequentLoginPolicy: + 'subject によるバインディングを検索し、新しいユーザー名が利用可能な場合のみ User.Name を更新します。', + testBeforeBrowserTest: 'ブラウザのログイン テストを開始する前に、現在の設定をテストします。', + testBeforeEnable: '設定変更を保存する前に、現在の設定をテストしてください。', + testConfiguration: '設定をテスト', + testDiscovery: 'Discovery をテスト', + tlsCustomCA: 'HTTPS · カスタム CA 証明書', + tlsPrivateHTTP: 'HTTP · プライベート ネットワークのみ (危険)', + tlsPrivateHTTPWarning: + 'HTTP はトランスポート暗号化を提供せず、明示的に許可されたプライベート ネットワークに制限されます。', + tlsSkipVerify: 'HTTPS · 証明書検証をスキップ (危険)', + tlsSystem: 'HTTPS · システム証明書検証 (推奨)', + tokenEndpoint: 'Token Endpoint', + tokenEndpointInvalid: '有効な Token Endpoint を入力してください。', + transportSecurity: 'トランスポート セキュリティ', + transportSecurityHelper: + 'HTTPS を推奨します。プライベート HTTP を使用するには、プライベートネットワークへのアクセスも明示的に許可する必要があります。', + unsavedChanges: '保存されていない OIDC 設定があります。', + usedClaim: 'Claim を使用', + userInfoEndpoint: 'UserInfo Endpoint', + userInfoEndpointHelper: + 'ユーザー名フィールドがない場合、このエンドポイントから補完します。補完しない場合は空欄にします。', + userInfoEndpointInvalid: '有効な UserInfo Endpoint を入力してください。', + userMapping: 'ユーザー設定', + userMappingDesc: + 'OIDC ユーザー名のマッピングと、初回ログイン時のユーザー作成に使用するデフォルトノードおよびロールを設定します。', + }, + saml2: { + actionCreate: 'ユーザーの作成', + actionPending: '結果を待機中', + actionReject: 'ログインの拒否', + actionReuse: '紐付け済みユーザーを使用', + assignDefaultRole: 'デフォルトのロールの割り当て: {role}', + basic: '基本設定', + basicDesc: '標準的な SAML2 IdP に必要な一般設定を構成します。', + browserTest: 'ログインテスト', + browserTestConflict: 'ID は確認されましたが、ユーザー名が競合しています。', + browserTestConflictHelper: + 'マッピングされたユーザー名は別の ID に属するため、自動的に関連付けません。', + browserTestExpired: 'ブラウザ テストの有効期限が切れました。', + browserTestExpiredHelper: + '新しいブラウザ テストを開始し、有効期限が切れる前に認証を完了してください。', + browserTestFailed: 'ブラウザ テストに失敗しました', + browserTestFailedHelper: + 'ID プレビューを完了できませんでした。ローカライズされたバックエンド エラーを確認します。', + browserTestIsolation: + '実際の認証ラウンドトリップを実行しますが、ユーザーの作成や更新、ロールの割り当て、認証済みパネルセッションの作成は行いません。', + browserTestPopupBlocked: + 'このサイトのポップアップを許可してから、ブラウザ テストを再度開始してください。', + browserTestPopupClosed: 'テストが完了する前に認証ウィンドウが閉じられました。', + browserTestSuccess: 'プロバイダーの検証に成功しました', + browserTestSuccessHelper: 'ユーザーやセッションを変更せずに ID マッピングがプレビューされました。', + browserTestTitle: 'SAML2 ブラウザー テスト ログイン', + browserTestWaiting: 'プロバイダーの認証を待機中', + browserTestWaitingHelper: + '新しいブラウザウィンドウでログインを完了してください。このページは自動的に更新されます。', + certificateFileInvalid: '有効な PEM、CRT、または CER 証明書ファイルを選択してください。', + configured: '設定済み', + configurationFailedHelper: + 'テストは失敗しました。このページには、ローカライズされたバックエンド エラーのみが表示されます。', + configurationNotTested: '現在の設定はテストされていません。', + configurationPassed: '現在の構成はセキュリティと機能のチェックに合格しました。', + configurationStaleHelper: '認証に依存する設定が変更されました。現在のドラフトを再度テストします。', + configurationTestSuccess: 'SAML2 構成テストは成功しました。', + configurationTesting: '現在の SAML2 構成をテストしています…', + conflictLDAP: 'LDAP ユーザー', + conflictLocal: 'ローカル ユーザー', + conflictNone: '競合なし', + conflictOIDC: '別の OIDC ID', + conflictSAML2: '別の SAML2 ID', + conflictType: '競合タイプ', + credentialFileReadFailed: '認証情報ファイルを読み取れませんでした。', + credentialFileTooLarge: '認証情報ファイルは 256 KiB 以下にしてください。', + credentialsRequired: 'SP 秘密鍵と証明書の両方を設定してください。', + defaultRole: '新規ユーザーのロール', + defaultRoleHelper: + '初回作成時のみ割り当てます。以後のログインではローカルのロール、MFA、権限を保持します。', + defaultRolePlaceholder: 'ロールを選択してください。', + defaultRoleRequired: '有効なデフォルトのロールを選択してください。', + disableConfirm: + 'SAML2 を無効にすると、新規ログインが直ちに拒否され、そのユーザーセッションが無効になります。続行しますか?', + disableDiscardConfirm: + 'SAML2 を無効にすると、このページの他の未保存の変更が破棄され、ユーザーセッションが直ちに無効になります。続行しますか?', + disableTitle: 'SAML2 を無効にする', + disabled: '無効', + enable: '有効化', + enabled: '有効', + idpMetadata: 'IdP メタデータ', + idpMetadataDesc: 'URL または XML のいずれかを入力します。両方ある場合は URL が優先されます。', + keepExistingRole: '既存のロールとローカル権限を保持します', + loginWith: '{provider} でログイン', + mappingResult: 'マッピング結果', + metadataRequired: 'IdP Metadata URL または XML を入力してください。', + metadataURLHelper: 'テスト時と保存時に、バックエンドがメタデータを取得して検証します。', + metadataURLInvalid: + '認証情報やフラグメントを含まない有効な HTTPS メタデータ URL を入力してください。', + metadataURLRecommended: 'メタデータ URL(推奨)', + metadataXML: 'メタデータ XML', + metadataXMLHelper: 'IdP が到達可能なメタデータ URL を公開していない場合に使用します。', + metadataXMLInvalid: '有効な EntityDescriptor メタデータ XML を入力してください。', + metadataXMLPlaceholder: '... を貼り付け', + nameAttribute: 'ユーザー名属性', + nameAttributeHelper: + '検証済みの SAML Assertion からこの属性を読み取り、1Panel のユーザー名にマッピングします。', + nameAttributePlaceholder: '例: uid、username、account', + nameAttributeRequired: 'ユーザー名属性を入力してください。', + notConfigured: '未設定', + or: 'または', + pageDesc: 'IdP Metadata を使用して企業 SSO を接続し、一般設定を 1 ページで完了します。', + plannedHandling: '計画された処理', + privateKeyFileInvalid: '有効な PEM 秘密鍵ファイルを選択してください。', + recentTestSuccess: '最後のテストは成功しました: {0}', + restore: '復元', + restored: '最後に保存された SAML2 設定が復元されました。', + roleHandling: 'ロール処理', + rolesLoadFailed: + 'ロールをロードできませんでした。デフォルトのロールを選択する前に再試行してください。', + selectFile: 'ファイルを選択', + serviceStatus: 'サービス状態', + serviceStatusDesc: 'SAML2 を有効にするには、現在の設定がテストに合格する必要があります。', + settingLoadFailed: 'SAML2 設定を読み込めませんでした。', + settingLoadFailedHelper: + '現在の設定に空のデフォルト設定が保存されないように、フォームはロックされています。接続が回復してから再試行してください。', + spCertificate: 'SP 証明書', + spCertificateHelper: + 'IdP がログインおよびログアウト要求を検証できるように、SP メタデータで公開されます。', + spCredentials: 'SP 秘密鍵と証明書', + spCredentialsDesc: + 'ログインおよびログアウトメッセージの署名に使用します。署名と検証のポリシーはバックエンドで固定されています。', + spPrivateKey: 'SP 秘密鍵', + spPrivateKeyHelper: + 'AuthnRequest とログアウトメッセージの署名に使用します。保存時に暗号化され、表示されることはありません。', + syncLogout: '同期ログアウト', + syncLogoutHelper: '1Panel または IdP の一方からログアウトすると、もう一方からもログアウトします。', + testBeforeBrowserTest: 'ブラウザのログイン テストを開始する前に、現在の設定をテストします。', + testBeforeEnable: '機密変更を有効にするか保存する前に、現在の設定をテストしてください。', + testConfiguration: '設定をテスト', + unsavedChanges: '保存されていない SAML2 設定があります。', + usedAttribute: 'ユーザー名マッピング', + usersAndRoles: 'ユーザーとロール', + usersAndRolesDesc: + 'パネルユーザー名のマッピングと、初回ログイン時のユーザー作成に使用するデフォルトノードおよびロールを設定します。', + }, ldap: { + basic: '基本設定', + loginTitle: 'LDAP ログイン', + loginWith: 'LDAP でログイン', + backToLocalLogin: 'パネルログインに戻る', enable: '有効にする', enabled: '有効', disabled: '無効', @@ -5168,6 +5554,7 @@ const message = { deleteConfirm: 'このエクスポート履歴とファイルを削除しますか?', }, waf: { + WAF: 'WAF', name: 'WAF', blackWhite: 'ブラックリストとホワイトリスト', globalSetting: 'グローバル設定', @@ -5779,6 +6166,13 @@ const message = { nodeUpgradePackageCleanHelper: 'すべての低バージョン更新パッケージをクリーンアップします。続行しますか?', nodeUpgradeOfflinePackageHelper: 'オフライン環境では、異なるアーキテクチャのノードは対応する更新パッケージを先にアップロードしてから更新してください。', + healthCheck: 'ヘルスチェック', + healthCheckFrequency: 'チェック頻度', + healthCheckFrequencyHelper: + 'バックエンドノードの状態を定期的にチェックします。チェックを無効にするには 0 を入力してください。', + healthCheckFrequencyLimit: 'チェック頻度は 1 日以内の負でない整数にしてください。', + loadFailedNodeResources: '障害ノードのリソースを読み込む', + loadFailedNodeResourcesHelper: 'ノード一覧を開くときに、障害ノードのリソース情報も読み込みます。', nodeUnhealthy: 'ノード状態異常', deletedNode: '削除済みノード {0} は現在アップグレード操作をサポートしていません!', nodeUnhealthyHelper: 'ノード状態異常を検出しました。[ノード管理]で確認してから再試行してください!', @@ -5793,10 +6187,9 @@ const message = { nodeItem: 'ノード管理', panelItem: 'パネル管理', addPanel: 'パネル追加', - addPanelHelper: - 'Después de agregar el panel exitosamente, puede acceder rápidamente al panel objetivo en [Resumen - Paneles].', - panel: 'Panel 1Panel', - others: 'Otros Paneles', + addPanelHelper: 'パネルを追加すると、[概要 - パネル] から対象のパネルにすばやくアクセスできます。', + panel: '1Panel パネル', + others: 'その他のパネル', addNode: 'ノードを追加', connInfo: '接続情報', nodeInfo: 'ノード情報', @@ -5870,6 +6263,8 @@ const message = { offlineHelper: 'ノードがオフライン環境にある場合に使用', appUpgrade: 'アプリのアップグレード', appUpgradeHelper: 'アップグレードが必要なアプリが {0} 個あります', + dashboardSetting: '概要設定', + keepOneDashboardComponent: '概要セクションを少なくとも 1 つ残してください', }, customApp: { name: 'カスタムアプリリポジトリ', @@ -5985,7 +6380,7 @@ const message = { timeRule: '残り時間が{0}日未満(処理されない場合、翌日再送信)', panelUpdateRule: '新しいパネルバージョンが検出されたときに1回アラートを送信(処理されない場合、翌日再送信)', - avgRule: '指定された時間内の平均{1}使用率が{2}%を超過するとアラートがトリガーされ、1日{3}回送信', + avgRule: '{0} 分以内の平均 {1} 使用率が {2}% を超えるとアラートを発生させ、1日 {3} 回送信します', diskRule: 'マウントディレクトリ{0}のディスク使用率が{1}{2}を超過するとアラートがトリガーされ、1日{3}回送信', allDiskRule: 'ディスク使用率が{0}{1}を超過するとアラートがトリガーされ、1日{2}回送信', cpuName: 'CPU', @@ -6261,35 +6656,36 @@ const message = { cpu: 'CPU', memory: 'メモリ', disk: 'ディスク', - overview: 'Overview', - kvmUnavailable: 'No available KVM hardware virtualization capability was detected.', - kvmCheckCpu: 'Confirm that the host CPU supports Intel VT-x or AMD-V virtualization.', - kvmCheckBios: 'Enable virtualization options in BIOS/UEFI.', - kvmCheckModule: 'Confirm that the kvm, kvm_intel, or kvm_amd kernel module is loaded correctly.', + overview: '概要', + kvmUnavailable: '利用可能な KVM ハードウェア仮想化機能が検出されませんでした。', + kvmCheckCpu: 'ホスト CPU が Intel VT-x または AMD-V をサポートしていることを確認してください。', + kvmCheckBios: 'BIOS/UEFI で仮想化オプションを有効にしてください。', + kvmCheckModule: + 'kvm、kvm_intel、kvm_amd カーネルモジュールが正しく読み込まれていることを確認してください。', kvmCheckDevice: - 'Confirm that /dev/kvm exists and the current environment is not a container or cloud host without KVM support.', - abnormal: 'Abnormal', - resourceOverview: 'Resource Overview', - cpuAllocated: 'CPU Allocated', - memoryAllocated: 'Memory Allocated', - storageUsed: 'Storage Used', - riskReminder: 'Risk Reminders', - noRisk: 'No risks', - runtimeHealth: 'Runtime Health', - runtimeAbnormal: 'VM runtime is abnormal', - noDependency: 'No dependency check data', - storageOverview: 'Storage Overview', - totalAllocated: 'Calculated by total VM configuration', - runningAllocated: 'Running allocation: {0}', - storageAvailable: 'Available: {0}', - inProgress: 'In progress', - needAttention: 'Needs attention', - normal: 'Normal', - environmentRisk: 'The VM runtime is not ready. Fix dependencies or virtualization services.', - storageRisk: 'Storage pool {0} usage has reached {1}%.', - abnormalRisk: '{0} VMs are in an abnormal state.', - pausedRisk: '{0} VMs are paused.', - memoryRisk: 'VM memory allocation has reached {0}%.', + '/dev/kvm が存在し、現在の環境が KVM 非対応のコンテナまたはクラウドホストではないことを確認してください。', + abnormal: '異常', + resourceOverview: 'リソース概要', + cpuAllocated: 'CPU 割り当て', + memoryAllocated: 'メモリ割り当て', + storageUsed: '使用済みストレージ', + riskReminder: 'リスク通知', + noRisk: 'リスクなし', + runtimeHealth: '実行環境の状態', + runtimeAbnormal: 'VM 実行環境に異常があります', + noDependency: '依存関係のチェックデータがありません', + storageOverview: 'ストレージ概要', + totalAllocated: 'VM の合計構成から算出', + runningAllocated: '実行中の割り当て:{0}', + storageAvailable: '利用可能:{0}', + inProgress: '処理中', + needAttention: '要確認', + normal: '正常', + environmentRisk: 'VM 実行環境の準備ができていません。依存関係または仮想化サービスを修正してください。', + storageRisk: 'ストレージプール {0} の使用率が {1}% に達しました。', + abnormalRisk: '{0} 台の VM が異常な状態です。', + pausedRisk: '{0} 台の VM が一時停止中です。', + memoryRisk: 'VM のメモリ割り当て率が {0}% に達しました。', cpuLimitHelper: '現在利用可能な CPU:{0} コア', cpuLimitExceeded: 'CPU が上限を超えています。現在利用可能な最大値:{0} コア。', memoryLimitHelper: '現在割り当て可能なメモリ:{0}(ホストは {1} のメモリを予約する必要があります)', @@ -6298,11 +6694,11 @@ const message = { storageLimitExceeded: 'ディスク容量が上限を超えています。現在利用可能な最大値:{0}。', iso: 'ISO', createFromTemplate: 'テンプレートから作成', - template: 'Template', - templateName: 'Template Name', - convertToTemplate: 'Convert to Template', - sourceVM: 'Source VM', - templateSize: 'Template Size', + template: 'テンプレート', + templateName: 'テンプレート名', + convertToTemplate: 'テンプレートに変換', + sourceVM: '元の VM', + templateSize: 'テンプレートサイズ', deleteTemplateConfirm: 'テンプレート {0} を削除します。この操作は元に戻せません。続行しますか?', orphanClean: '孤立データのクリーンアップ', orphanScan: '再スキャン', @@ -6346,21 +6742,21 @@ const message = { available: '利用可能', vmCount: '関連 VM', usedIPs: '使用済み IP', - monitor: 'Monitor', - monitorNotReady: 'The virtual machine is not running. Monitoring data is unavailable.', - monitorLoadFailed: 'Failed to get VM monitoring data.', - monitorLoadFailedWithReason: 'Failed to get VM monitoring data: {0}', - rename: 'Rename', + monitor: '監視', + monitorNotReady: '仮想マシンが実行されていないため、監視データを利用できません。', + monitorLoadFailed: 'VM の監視データを取得できませんでした。', + monitorLoadFailedWithReason: 'VM の監視データを取得できませんでした:{0}', + rename: '名前変更', newName: '新しい名前', - renameHelper: 'Enter a new VM name. The VM must be shut down before renaming.', - renameConfirm: 'Rename virtual machine [{0}] to [{1}]?', - renameRunningHelper: 'Shut down the virtual machine before renaming it.', - cpuUsage: 'CPU Usage', - memoryUsage: 'Memory Usage', - diskIO: 'Disk IO', - networkIO: 'Network IO', - diskReadWrite: 'Disk Read / Write', - networkRxTx: 'Network RX / TX', + renameHelper: '新しい VM 名を入力してください。名前を変更する前に VM を停止する必要があります。', + renameConfirm: '仮想マシン [{0}] の名前を [{1}] に変更しますか?', + renameRunningHelper: '名前を変更する前に仮想マシンを停止してください。', + cpuUsage: 'CPU 使用率', + memoryUsage: 'メモリ使用率', + diskIO: 'ディスク I/O', + networkIO: 'ネットワーク I/O', + diskReadWrite: 'ディスク読み取り/書き込み', + networkRxTx: 'ネットワーク受信/送信', rx: 'RX', tx: 'TX', console: 'コンソール', @@ -6370,16 +6766,18 @@ const message = { 'VNC コンソールへの接続に失敗しました。コンソールプロキシサービスを確認してください。', consoleCredentialsRequired: 'VNC コンソールには認証情報が必要です。バックエンドプロキシ設定を確認してください。', - snapshot: 'Snapshot', - createSnapshot: 'Create Snapshot', - recoverSnapshot: 'Recover Snapshot', + snapshot: 'スナップショット', + createSnapshot: 'スナップショットを作成', + recoverSnapshot: 'スナップショットを復元', snapshotSize: '使用量', - currentSnapshot: 'Current', - snapshotEmpty: 'No snapshots', + currentSnapshot: '現在', + snapshotEmpty: 'スナップショットがありません', snapshotHelper: - 'A snapshot saves the current VM state as a restore point. Subsequent data changes are recorded in a delta file without changing the original disk. Restoring a snapshot returns the VM to that point in time.', + 'スナップショットは現在の VM 状態を復元ポイントとして保存します。以降のデータ変更は元のディスクを変更せず差分ファイルに記録されます。復元すると VM はその時点の状態に戻ります。', + snapshotOperationHelper: + '現在のスナップショットは削除できません。スナップショットを復元できるのは仮想マシンが停止している場合のみです。', snapshotRecoverConfirm: - 'Recover virtual machine [{1}] to snapshot [{0}]? The VM disk will be restored to the snapshot state.', + '仮想マシン [{1}] をスナップショット [{0}] に復元しますか?VM ディスクはスナップショット時点の状態に戻ります。', interface: 'ネットワークインターフェース', device: 'デバイス', path: 'パス', diff --git a/frontend/src/lang/modules/ko.ts b/frontend/src/lang/modules/ko.ts index 5aed86080..905d0faf4 100644 --- a/frontend/src/lang/modules/ko.ts +++ b/frontend/src/lang/modules/ko.ts @@ -11,6 +11,7 @@ const message = { button: { run: '실행', add: '추가', + select: '선택', save: '저장', set: '설정', sync: '동기화', @@ -29,7 +30,6 @@ const message = { selectAll: '전체 선택', login: '로그인', close: '닫기', - off: '꺼짐', stop: '중지', start: '시작', view: '보기', @@ -91,6 +91,7 @@ const message = { setDefault: '기본값 복원', bind: '연결', tip: '팁', + reconnect: '다시 연결', }, operate: { start: '시작', @@ -119,6 +120,9 @@ const message = { card: '카드', table: '표', status: '상태', + statusSuccess: '성공', + statusFailed: '실패', + statusWaiting: '대기 중...', records: '기록', group: '그룹', createdAt: '생성 시간', @@ -163,6 +167,7 @@ const message = { deleteSuccess: '삭제 완료', loginSuccess: '로그인 성공', operationSuccess: '작업 완료', + operationFailed: '작업에 실패했습니다', copySuccess: '복사 완료', notSupportOperation: '이 작업은 지원되지 않습니다', requestTimeout: '요청이 시간 초과되었습니다. 나중에 다시 시도해 주십시오', @@ -205,6 +210,7 @@ const message = { username: '사용자 이름', password: '비밀번호', passkey: '패스키 로그인', + otherLoginMethods: '다른 로그인 방법', welcome: '다시 오신 것을 환영합니다. 사용자 이름과 비밀번호를 입력하여 로그인하세요!', errorAuthInfo: '입력한 사용자 이름 또는 비밀번호가 잘못되었습니다. 다시 입력해주세요!', errorMfaInfo: '인증 정보가 잘못되었습니다. 다시 시도해주세요!', @@ -283,6 +289,8 @@ const message = { authBasicPassword: '알파벳, 숫자 및 일반 특수 문자 지원, 길이 1-72', length128Err: '길이는 128자를 초과할 수 없습니다', maxLength: '길이는 {0}자를 초과할 수 없습니다', + vmName: '영문, 숫자, ".", "-", "_"를 지원하며 길이는 1-64자이고 영문 또는 숫자로 시작해야 합니다.', + vmNetwork: '영문, 숫자, ".", ":", "-", "_"를 지원하며 길이는 1-64자이고 영문 또는 숫자로 시작해야 합니다.', alias: '영어, 숫자, - 및 _ 지원, 길이 1-128, -_로 시작하거나 끝날 수 없습니다.', }, res: { @@ -302,7 +310,6 @@ const message = { success: '성공', waiting: '대기 중', waitForUpgrade: '업그레이드 대기 중', - waiting1: '대기 중', failed: '실패', stopped: '중지됨', error: '오류', @@ -326,7 +333,6 @@ const message = { deny: '거부됨', accept: '수락됨', used: '사용 중', - unUsed: '사용 안 함', starting: '시작 중', recreating: '재생성 중', creating: '생성 중', @@ -467,7 +473,7 @@ const message = { cpuSteal: 'Steal', cpuTop: 'CPU 사용률 상위 5개 프로세스 정보', memTop: '메모리 사용률 상위 5개 프로세스 정보', - loadAverage: '지난 1분의 평균 부하 | 지난 {n} 분의 평균 부하', + loadAverage: '지난 1분의 평균 부하 | 지난 {0}분의 평균 부하', load: '부하', mount: '마운트 지점', fileSystem: '파일 시스템', @@ -503,6 +509,7 @@ const message = { deleteBackupHelper: '데이터베이스 백업을 동시에 삭제', delete: '삭제 작업은 되돌릴 수 없습니다. 삭제하려면 "', deleteHelper: '"를 입력하세요.', + deleteUserHelper: '"를 입력하여 이 사용자를 삭제하세요.', userBoundDatabases: '다음 데이터베이스에 대한 접근 권한이 있습니다:', noMysql: '데이터베이스 서비스 (MySQL 또는 MariaDB)', noPostgresql: '데이터베이스 서비스 PostgreSQL', @@ -541,6 +548,7 @@ const message = { portHelper: '이 포트는 컨테이너의 노출된 포트입니다. 수정을 별도로 저장하고 컨테이너를 재시작해야 합니다!', loadFromRemote: '동기화', userBind: '사용자 바인딩', + noUserBind: '바인딩 없음', userAuthorization: '사용자 권한', noUserAuthorization: '권한 부여 안 함', authorizedDatabaseCount: '데이터베이스 {0}개 권한 보유', @@ -800,16 +808,12 @@ const message = { roleMarkdownDescriptions: { 'AGENTS.md': [ '에이전트의 운영 지침과 메모리를 어떻게 사용할지에 대한 설명입니다.', - '모든 세션 시작 시 로드됩니다.', '규칙, 우선순위, 동작 방식의 세부 내용을 적기에 좋습니다.', ], - 'SOUL.md': ['페르소나, 말투, 경계.', '매 세션마다 로드됩니다.'], - 'USER.md': ['사용자가 누구인지, 어떻게 호칭할지.', '매 세션마다 로드됩니다.'], - 'IDENTITY.md': ['에이전트의 이름, 분위기, 이모지.', '부트스트랩 절차 중 생성되거나 업데이트됩니다.'], - 'TOOLS.md': [ - '로컬 도구와 사용 규약에 대한 메모입니다.', - '도구 사용 가능 여부를 제어하지 않으며, 안내용 설명입니다.', - ], + 'SOUL.md': ['페르소나, 말투, 경계.'], + 'USER.md': ['사용자가 누구인지, 어떻게 호칭할지.'], + 'IDENTITY.md': ['에이전트의 이름, 분위기, 이모지.'], + 'TOOLS.md': ['로컬 도구와 사용 규약에 대한 메모입니다.'], 'HEARTBEAT.md': ['heartbeat 실행용 선택 체크리스트입니다.', '토큰 낭비를 막기 위해 짧게 유지하세요.'], 'BOOT.md': [ '내부 훅이 켜져 있을 때 gateway 재시작 시 실행되는 선택 시작 체크리스트입니다.', @@ -818,7 +822,6 @@ const message = { 'BOOTSTRAP.md': [ '최초 실행 시 한 번만 수행되는 절차입니다.', '완전히 새로운 작업공간에서만 생성됩니다.', - '절차가 끝나면 삭제하세요.', ], }, duplicateBinding: '채널과 계정 ID 조합은 중복될 수 없습니다', @@ -980,9 +983,6 @@ const message = { failureCount: '실패 횟수', lastError: '최근 오류', modelMap: '모델 매핑', - apiKeyKeepEmpty: 'API Key (비워 두면 변경하지 않음)', - apiKeyOnceHint: 'API Key는 생성 시 한 번만 표시됩니다. 지금 복사하여 저장하세요.', - apiKeyOnceSave: 'API Key는 한 번만 표시됩니다. 지금 저장하세요:', qpsLimit: 'QPS 제한', tokenLimit: 'Token 제한', tokenUsed: '사용한 Token', @@ -1124,23 +1124,23 @@ const message = { modelGroupGuide: '모델 그룹에는 AI 게이트웨이가 노출하는 요청 모델 이름을 설정합니다. 업스트림 모델은 계정 풀의 모델 매핑에서 설정하세요. auto는 가상 모델 이름이므로 모델 그룹에 추가하지 않습니다.', modelGroupModelCount: '{0}개 모델', - contentCompliance: 'Content Compliance', - contentAction: 'Action', - actionBlock: 'Block', - actionAuditOnly: 'Audit only', + contentCompliance: '콘텐츠 규정 준수', + contentAction: '작업', + actionBlock: '차단', + actionAuditOnly: '감사만', actionDropHistory: '기록 삭제', - severity: 'Severity', - severityHigh: 'High', - severityMedium: 'Medium', - severityLow: 'Low', - sensitiveWord: 'Sensitive word', - sensitiveGroup: 'Sensitive word group', - sensitiveWordCount: 'Words', - normalizedWord: 'Normalized word', - matchedWords: 'Matched words', - matchedGroups: 'Matched groups', - importResult: 'Imported {0}, duplicated {1}, invalid {2}', - auditLogs: 'Audit Logs', + severity: '심각도', + severityHigh: '높음', + severityMedium: '중간', + severityLow: '낮음', + sensitiveWord: '민감 단어', + sensitiveGroup: '민감 단어 그룹', + sensitiveWordCount: '단어 수', + normalizedWord: '정규화된 단어', + matchedWords: '일치한 단어', + matchedGroups: '일치한 그룹', + importResult: '가져오기 {0}건, 중복 {1}건, 유효하지 않음 {2}건', + auditLogs: '감사 로그', smartRoute: '스마트 라우팅', smartRouteGuideTitle: '클라이언트에서 model=auto를 사용해 스마트 라우팅에 진입합니다', smartRouteGuideReady: @@ -1206,9 +1206,9 @@ const message = { latencyMs: '지연 시간(ms)', smartRouteSettingGuide: '활성화 후 model=auto 요청만 스마트 라우팅을 사용합니다. 간단 모델 그룹은 저비용 작업, 복잡 모델 그룹은 코드 분석, 아키텍처 설계, 장애 조사 등에 사용됩니다.', - sampleLabelPlaceholder: 'simple / complex / high', + sampleLabelPlaceholder: '단순 / 복잡 / 높음', sampleImportPlaceholder: '한 줄에 샘플 하나', - apiKeyCount: '数量', + apiKeyCount: 'API 키 수', }, skillsHub: { title: 'Skills Hub', @@ -1433,22 +1433,22 @@ const message = { processCount: '프로세스 수', }, mcp: { - server: 'MCP サーバー', - baseUrl: '外部アクセスパス', - baseUrlHelper: '例: http://192.168.1.2:8000', - ssePath: 'SSE パス', - ssePathHelper: '例: /sse, 他のサーバーと重複しないように注意してください', - environment: '環境変数', - envKey: '変数名', - envValue: '変数値', - externalUrl: '外部接続アドレス', - operatorHelper: '{0} に {1} 操作を実行します、続行しますか?', - domain: 'デフォルトアクセスアドレス', - domainHelper: '例: 192.168.1.1 または example.com', - bindDomain: 'ウェブサイトをバインド', + server: 'MCP 서버', + baseUrl: '외부 접근 경로', + baseUrlHelper: '예: http://192.168.1.2:8000', + ssePath: 'SSE 경로', + ssePathHelper: '예: /sse, 다른 서버와 중복되지 않도록 주의하세요', + environment: '환경 변수', + envKey: '변수 이름', + envValue: '변수 값', + externalUrl: '외부 연결 주소', + operatorHelper: '{0}에 {1} 작업을 수행합니다. 계속하시겠습니까?', + domain: '기본 접근 주소', + domainHelper: '예: 192.168.1.1 또는 example.com', + bindDomain: '웹사이트 바인딩', commandPlaceHolder: '현재 npx 및 바이너리 시작 명령만 지원합니다', - importMcpJson: 'MCP サーバー設定をインポート', - importMcpJsonError: 'mcpServers 構造が正しくありません', + importMcpJson: 'MCP 서버 구성 가져오기', + importMcpJsonError: 'mcpServers 구조가 올바르지 않습니다', bindDomainHelper: '웹사이트를 바인딩한 후, 설치된 모든 MCP 서버의 접근 주소를 수정하고 포트의 외부 접근을 닫습니다', outputTransport: '출력 유형', @@ -1456,14 +1456,14 @@ const message = { streamableHttpPathHelper: '예: /mcp, 다른 서버와 중복되지 않도록 주의하세요', npxHelper: 'npx 또는 바이너리로 시작하는 mcp에 적합', uvxHelper: 'uvx로 시작하는 mcp에 적합', - protocolVersion: 'Protocol Version', + protocolVersion: '프로토콜 버전', protocolVersionHelper: - 'Only used by stateless Streamable HTTP to auto-initialize the downstream stdio MCP Server', + '상태 비저장 Streamable HTTP에서 하위 stdio MCP Server를 자동 초기화할 때만 사용합니다', gatewayArgsHelper: '인수는 supergateway 시작 명령에 추가됩니다. 1Panel에서 관리하는 전송, 포트, 경로 및 프로토콜 인수는 변경할 수 없습니다', - testConnection: 'Test Connection', - connectionSuccess: 'Connection succeeded', - connectionFailed: 'Connection failed', + testConnection: '연결 테스트', + connectionSuccess: '연결 성공', + connectionFailed: '연결 실패', }, tensorRT: { llm: 'TensorRT LLM', @@ -1533,9 +1533,10 @@ const message = { last4Hour: '지난 4시간', lastHour: '지난 1시간', last10Min: '지난 10분', + cleanLogscope: '정리 유형', cleanLog: '로그 정리', downLogHelper1: '이 작업은 컨테이너 {0}의 모든 로그를 다운로드합니다. 계속하시겠습니까?', - downLogHelper2: '이 작업은 컨테이너 {0}의 최근 {0}개의 로그를 다운로드합니다. 계속하시겠습니까?', + downLogHelper2: '컨테이너 {0}의 최신 로그 {1}줄을 다운로드합니다. 계속하시겠습니까?', cleanLogHelper: '이 작업은 컨테이너를 재시작해야 하며 취소할 수 없습니다. 계속하시겠습니까?', newName: '새 이름', source: '리소스 사용', @@ -1727,7 +1728,8 @@ const message = { dockerStatus: 'Docker 서비스', daemonJsonPathHelper: '구성 경로가 docker.service 에 지정된 경로와 동일한지 확인하십시오.', mirrors: '레지스트리 미러들', - mirrorsHelper: '', + mirrorsHelper: + '이미지 작업에 레지스트리 미러 URL을 우선 사용합니다. 레지스트리 미러를 비활성화하려면 비워 두세요.', mirrorsHelper2: '자세한 내용은 공식 문서를 참조하십시오.', registries: '불안정한 레지스트리들', ipv6Helper: @@ -1791,7 +1793,6 @@ const message = { stopHelper: '이 작업은 현재 작업 실행을 강제로 중지합니다. 계속하시겠습니까?', log: '백업 로그', logHelper: '시스템 백업 로그', - ogHelper1: '1. 1Panel 시스템 로그', logHelper2: '2. 서버 SSH 로그인 로그', logHelper3: '3. 모든 사이트 로그', containerCheckBox: '컨테이너 내 (컨테이너 명령어 입력 불필요)', @@ -1866,7 +1867,6 @@ const message = { perNMinute: '매 N분', perNSecond: '매 N초', day: '일', - dayUnit: 'd', monday: '월요일', tuesday: '화요일', wednesday: '수요일', @@ -1901,7 +1901,7 @@ const message = { interactive: '대화형 스크립트', interactiveHelper: '실행 중 사용자 입력이 필요하며 예약 작업에서는 사용할 수 없습니다.', library: '스크립트 라이브러리', - remoteLibrary: 'リモートスクリプトライブラリ', + remoteLibrary: '원격 스크립트 라이브러리', create: '스크립트 추가', edit: '스크립트 수정', groupHelper: @@ -1998,7 +1998,6 @@ const message = { connTestFailed: '연결할 수 없습니다. 연결 정보를 확인해주세요.', host: '호스트 | 호스트들', createConn: '새 연결', - manageGroup: '그룹 관리', noHost: '호스트 없음', groupChange: '그룹 변경', expand: '모두 확장', @@ -2235,6 +2234,7 @@ const message = { nodes: '노드', commands: '빠른 명령', opsReport: '운영 보고서', + ops_report: '운영 보고서', users: '사용자 관리', roles: '역할', auth: '로그인 인증', @@ -2255,10 +2255,6 @@ const message = { fileDirNum: '총 {0}개 디렉터리, {1}개 파일,', currentDir: '현재 디렉터리', dir: '폴더', - upload: '업로드', - uploadFile: '@:file.upload @.lower:file.file', - uploadDirectory: '@:file.upload @.lower:file.dir', - download: '다운로드', fileName: '파일 이름', search: '검색', mode: '권한', @@ -2274,7 +2270,6 @@ const message = { role: '권한', info: '속성', linkFile: '소프트 링크', - batchoperation: '일괄 작업', shareList: '공유 목록', fileTools: '파일 도구', aiSearchHitLines: '일치하는 줄', @@ -2608,7 +2603,7 @@ const message = { syncHelper: '동기화 작업으로 유효하지 않은 키를 정리하고 새로운 완전한 키 쌍을 동기화합니다. 계속하시겠습니까?', input: '수동 입력', import: '파일 업로드', - authKeys: 'Kunci Pengesahan', + authKeys: '인증 키', authKeysHelper: '현재 공개 키 정보를 저장하시겠습니까?', pubkey: '키 정보', encryptionMode: '암호화 모드', @@ -2742,7 +2737,6 @@ const message = { restartLater: '나중에 수동으로 재시작', systemIPWarning: '현재 노드에 기본 접근 주소가 설정되지 않았습니다. 패널 설정에서 설정해 주세요!', systemIPWarning1: '현재 서버 주소는 {0}으로 설정되어 있어 빠른 리디렉션이 불가능합니다!', - defaultNetwork: '네트워크 카드', syncTime: '서버 시간', timeZone: '시간대', timeZoneChangeHelper: '시간대를 변경하면 서비스를 재시작해야 합니다. 계속하시겠습니까?', @@ -2787,7 +2781,7 @@ const message = { codeWarning: '현재 인증 코드 형식이 올바르지 않습니다. 다시 확인하십시오!', code: '인증 코드', codeHelper: - '"획득" 버튼을 클릭한 다음 OneDrive 에 로그인하여 리디렉션된 링크에서 "code" 이후의 내용을 복사하십시오. 이 입력 상자에 붙여넣으십시오. 자세한 지침은 공식 문서를 참조하십시오.', + '"획득" 버튼을 클릭한 다음 {0}에 로그인하여 리디렉션된 링크에서 "code" 이후의 내용을 복사하십시오. 이 입력 상자에 붙여넣으십시오. 자세한 지침은 공식 문서를 참조하십시오.', googleHelper: '먼저 Google 애플리케이션을 생성하고 클라이언트 정보를 획득한 후 양식을 작성하고 획득 버튼을 클릭하세요. 구체적인 작업은 공식 문서를 참조하십시오.', loadCode: '획득', @@ -3085,7 +3079,6 @@ const message = { upgrading: '업그레이드 중, 잠시만 기다려 주세요...', versionHelper: '명명 규칙: [메이저].[기능].[버그 수정], 예시:', upgradeCheck: '업데이트 확인', - panelSSLHelper: '패널 SSL 자동 갱신 후 1Panel 서비스를 수동 재시작해야 적용됩니다.', }, license: { offLine: '오프라인 버전', @@ -3112,12 +3105,11 @@ const message = { authorizedUser: '인증된 사용자', lostHelper: '라이센스가 최대 재시도 횟수를 초과했습니다. 상용 버전 기능이 제대로 작동하는지 확인하려면 동기화 버튼을 수동으로 클릭하세요.', - disableHelper: - '라이센스 동기화 검증에 실패했습니다. 상용 버전 기능이 제대로 작동하는지 확인하려면 동기화 버튼을 수동으로 클릭하세요.', quickUpdate: '빠른 업데이트', power: '권한 부여', unbindHelper: '연결 해제 후 모든 상용 버전 관련 설정이 초기화됩니다. 계속하시겠습니까?', importLicense: '라이센스', + import: '가져오기', securityWarningTitle: '크랙 버전 또는 출처를 알 수 없는 라이선스를 사용하지 마세요.', securityWarningContent: '1Panel은 시스템 관리 권한을 가진 사용자로 실행해야 합니다. 비공식 라이선스 또는 변조된 버전은 서버 제어 상실, 데이터 유출 등 심각한 보안 위험을 초래할 수 있습니다. 라이선스와 설치 패키지는 FIT2CLOUD 공식 채널을 통해 받으세요.', @@ -3171,6 +3163,7 @@ const message = { fileExchange: '상용 버전으로 업그레이드하면 여러 서버 간에 파일을 빠르게 전송할 수 있습니다.', app: '상용 버전으로 업그레이드하면 모바일 앱에서 서비스 정보와 이상 모니터링을 확인할 수 있습니다.', cluster: '상용 버전으로 업그레이드하면 MySQL/Postgres/Redis 기본-복제 클러스터를 관리할 수 있습니다.', + vllm: '상용 버전으로 업그레이드하면 1Panel에서 vLLM 서비스의 배포, 구성, 수명 주기 작업 및 작업 추적을 중앙에서 관리할 수 있습니다.', 'model-downloader': '상용 버전으로 업그레이드하면 HuggingFace, ModelScope 또는 호환 미러에서 로컬 모델 파일을 검색, 다운로드 및 관리하고 모델 디렉터리와 다운로드 작업을 통합 관리할 수 있습니다.', exceptionalHelper: @@ -3354,7 +3347,7 @@ const message = { toLink: '이동', customAppHelper: '사용자 정의 앱 스토어 패키지를 설치하기 전에 설치된 앱이 없는지 확인하십시오.', forceUninstall: '강제 제거', - syncCustomApp: 'カスタムアプリを同期', + syncCustomApp: '사용자 정의 앱 동기화', ignoreAll: '후속 모든 버전 무시', ignoreVersion: '지정된 버전 무시', specifyIP: '호스트 IP 바인딩', @@ -3380,7 +3373,6 @@ const message = { ftpPassword: 'FTP 비밀번호', ftpHelper: '웹사이트를 생성하면 해당 FTP 계정이 생성되고 FTP 디렉터리는 웹사이트 디렉터리와 연결됩니다.', remark: '비고', - manageGroup: '그룹 관리', groupSetting: '그룹 설정', createGroup: '그룹 생성', appNew: '새로운 애플리케이션', @@ -3444,7 +3436,6 @@ const message = { nginxPer: '성능 튜닝', neverExpire: '만료 없음', setDefault: '기본값으로 설정', - default: '기본값', deleteHelper: '관련 애플리케이션 상태가 비정상입니다. 확인해 주세요.', toApp: '설치된 목록으로 이동', cycle: '주기', @@ -3556,7 +3547,6 @@ const message = { proxyHelper1: '이 디렉터리에 접근할 때 대상 URL 의 내용이 반환되고 표시됩니다.', proxyPassHelper: '대상 URL 은 유효하고 접근 가능해야 합니다.', proxyHostHelper: '요청 헤더에 있는 도메인 이름을 프록시 서버로 전달합니다.', - replacementHelper: '최대 5개의 교체를 추가할 수 있으며, 교체가 필요하지 않은 경우 비워두세요.', modifier: '매칭 규칙', modifierHelper: '예: = 는 정확히 일치, ~ 는 정규식 일치, ^~ 는 경로 시작 부분 일치 등을 나타냅니다.', replace: '텍스트 교체', @@ -3660,7 +3650,6 @@ const message = { global: '글로벌', subsite: '하위 사이트', subsiteHelper: '하위 사이트는 기존 PHP 또는 정적 웹사이트의 디렉토리를 루트 디렉토리로 선택할 수 있습니다.', - parentWebsite: '상위 웹사이트', deleteSubsite: '현재 웹사이트를 삭제하려면 먼저 하위 사이트 {0}를 삭제해야 합니다.', loadBalance: '로드 밸런싱', server: '노드', @@ -3691,7 +3680,6 @@ const message = { cacheExpire: '캐시 만료 시간', shareCacheHelper: '1M 메모리로 약 8000개의 캐시 객체를 저장할 수 있습니다.', cacheLimitHelper: '제한을 초과하면 이전 캐시가 자동으로 삭제됩니다.', - cacheExpireHelper: '만료 시간 내에 히트되지 않은 캐시는 삭제됩니다.', realIP: '실제 IP', ipFrom: 'IP 소스', ipFromHelper: @@ -3753,8 +3741,6 @@ const message = { syncHtmlHelper: 'PHP 및 정적 웹사이트에 동기화', wafValueHelper: '값', parentWbeiste: '상위 웹사이트', - shareCahe: '캐시 수 메모리 크기', - shareCaheHelper: '메모리 1M당 약 8000개의 캐시 객체를 저장할 수 있습니다', cacheExpireJHelper: '만료 후 미적중 시 캐시가 삭제됩니다', }, php: { @@ -4121,7 +4107,6 @@ const message = { netRecv: '다운스트림', numConnections: '연결', startTime: '시작 시간', - state: '상태', running: '실행 중', sleep: '대기 중', stop: '중지', @@ -4335,8 +4320,10 @@ const message = { scorePanelHTTPSDisabled: '패널 HTTPS 미활성화', scoreSSHRootLogin: 'SSH Root 로그인 허용됨', scoreSSHPasswordAuth: 'SSH 비밀번호 인증 활성화, 키 인증 미활성화', + scoreSSLExpired: '{0} 인증서가 만료되었습니다', scoreSSLHigh: '{0} 인증서 만료까지 {1}일 남음', scoreSSLMedium: '{0} 인증서 만료까지 {1}일 남음', + scoreWebsiteExpired: '{0} 웹사이트가 만료되었습니다', scoreWebsiteExpire: '{0} 웹사이트 만료까지 {1}일 남음', scoreWebsiteHTTP: '{0} HTTPS 미사용', scoreWebsiteStopped: '{0} 상태 비정상', @@ -4383,6 +4370,7 @@ const message = { panelLogin: '패널 로그인', sshLogin: 'SSH 로그인', failedRecord: '실패 기록', + expired: '만료됨', expiredDays: '{0}일 전 만료', remainingDays: '{0} · {1}일 남음', enabled: '활성화', @@ -4648,9 +4636,9 @@ const message = { abnormalSites: '비정상 사이트', count5xxSource: '5xx 요청 기준 집계', wafIntercept: 'WAF 차단', - highRiskHit: '고위험 매칭', websiteMonitorDisabledOrNoData: '웹사이트 모니터링이 미활성화되었거나 모니터 데이터가 없습니다', wafDisabledOrNoData: 'WAF가 미활성화되었거나 차단 데이터가 없습니다', + serviceEnabledButAbnormal: '활성화되었지만 비정상 상태입니다', noWafData: 'WAF 차단 데이터가 없습니다', sourceIP: '출처 IP', hitCount: '매칭 횟수', @@ -4711,6 +4699,7 @@ const message = { successRate: '성공률', failedJobs: '실패 작업', recentRecoveryPoint: '최근 복구 지점', + disabledCronjobTasks: '비활성화된 예약 작업', remoteCoverage: '원격 포함', recent7Days: '최근 7일', taskTypeStats: '작업 유형 통계', @@ -4732,6 +4721,7 @@ const message = { cronjobReasonDisabled: '{0}개 작업 비활성화', cronjobReasonLocalOnlyBackup: '로컬 전용 백업 {0}개', cronjobReasonNormal: '예약 작업 실행과 백업 범위가 정상입니다', + riskLow: '낮은 위험', viewFailedRecords: '실패 작업 보기', viewCronjobTasks: '예약 작업 보기', checkBackupTasks: '백업 작업 확인', @@ -4828,6 +4818,14 @@ const message = { authManage: '인증 관리', auth: { providerNavigation: '인증 공급자', + defaultNode: '기본 노드', + defaultNodePlaceholder: '노드를 선택하세요', + defaultNodeHelper: '새 사용자에게만 사용됩니다.', + defaultNodeRequired: '유효한 기본 노드를 선택하세요.', + nodesLoadFailed: '노드를 불러오지 못했습니다. 기본 노드를 선택하기 전에 다시 시도하세요.', + nodeHandling: '노드 처리', + assignDefaultNode: '기본 노드 할당: {node}', + keepExistingNode: '기존 노드 권한 유지', providers: { ldap: 'AD/LDAP', passkey: 'Passkey', @@ -4855,7 +4853,381 @@ const message = { planned: '예정', plannedTitle: '{0} 인증 설정', plannedDesc: '이 인증 공급자는 계획되어 있으며 아직 사용할 수 없습니다.', + oidc: { + accessMode: '연결 모드', + accessModeDesc: 'ID 공급자가 지원할 때마다 표준 Discovery를 사용하세요.', + actionCreate: '사용자 만들기', + actionKeepName: '현재 이름 유지', + actionPending: '결과를 기다리는 중', + actionReject: '로그인 거부', + actionUpdate: '신원 정보 업데이트', + advanced: '고급 설정', + advancedDesc: '공급자가 호환성 옵션을 요구하지 않는 한 안전한 기본값을 유지하세요.', + assignDefaultRole: '기본 역할 할당: {role}', + authorizationEndpoint: 'Authorization Endpoint', + authorizationEndpointInvalid: '유효한 Authorization Endpoint를 입력하세요.', + authorizationFlow: '인가 흐름', + automatic: '자동', + automaticPolicy: '자동 처리 정책', + automaticPolicyDesc: '이 규칙은 백엔드에 의해 시행되며 관리자 스위치가 아닙니다.', + basic: '기본 설정', + basicDesc: '공급자 모드를 선택한 다음 클라이언트와 콜백을 구성합니다.', + browserTest: '브라우저 테스트 로그인', + browserTestConflict: '신원은 확인되었지만 사용자 이름이 충돌합니다', + browserTestConflictHelper: '매핑된 사용자 이름은 다른 신원에 속하므로 자동으로 연결하지 않습니다.', + browserTestExpired: '브라우저 테스트가 만료되었습니다.', + browserTestExpiredHelper: '만료되기 전에 새 브라우저 테스트를 시작하고 인증을 완료하세요.', + browserTestFailed: '브라우저 테스트 실패', + browserTestFailedHelper: '신원 미리보기를 완료할 수 없습니다. 현지화된 백엔드 오류를 검토하세요.', + browserTestIsolation: + '실제 인증 왕복을 수행하지만 사용자를 생성하거나 업데이트하지 않고, 역할을 할당하거나 인증된 패널 세션을 생성하지 않습니다.', + browserTestPopupBlocked: '이 사이트에 대한 팝업을 허용한 다음 브라우저 테스트를 다시 시작하세요.', + browserTestPopupClosed: '테스트가 완료되기 전에 인증 창이 닫혔습니다.', + browserTestSuccess: '공급자 확인 성공', + browserTestSuccessHelper: '사용자 또는 세션을 변경하지 않고 ID 매핑을 미리 보았습니다.', + browserTestTitle: 'OIDC 브라우저 테스트 로그인', + browserTestWaiting: '공급자 인증 대기 중', + browserTestWaitingHelper: + '새 브라우저 창에서 로그인을 완료하세요. 이 페이지는 자동으로 업데이트됩니다.', + callbackCopied: 'OIDC 콜백 URL이 복사되었습니다.', + callbackURL: '콜백 URL', + callbackURLHelper: '이 URL을 ID 공급자 클라이언트의 허용된 콜백 URL에 추가하세요.', + cancelClearSecret: '삭제 취소', + clearSecret: 'Client Secret 지우기', + clearSecretConfirm: 'Client Secret은 저장한 후에만 제거됩니다. 계속하시겠습니까?', + clientAuthMethod: '클라이언트 인증 방법', + clientAuthMethodHelper: 'ID 공급자에서 이 클라이언트에 설정한 인증 방식을 선택하세요.', + clientAuthMethodRequired: '클라이언트 인증 방법을 선택하세요.', + clientID: 'Client ID', + clientIDRequired: 'Client ID를 입력하세요.', + clientSecret: 'Client Secret', + clockSkew: '토큰 시간 오차 허용', + clockSkewHelper: + 'ID 공급자와 1Panel 사이의 약간의 시간 차이를 허용합니다. 기본값인 60초를 유지하세요.', + clockSkewRequired: '토큰 시간 오차 허용 값을 입력하세요.', + compatibilityMode: '호환 모드', + compatibilityModeHelper: + '불완전한 Discovery 또는 다시 작성된 엔드포인트에만 사용하세요. 코어 OIDC 검증은 활성화된 상태로 유지됩니다.', + configurationFailedHelper: '테스트에 실패했습니다. 페이지에 현지화된 백엔드 오류만 표시됩니다.', + configurationFailedTag: '테스트 실패', + configurationHighRiskPassed: '구성이 통과되었지만 고위험 호환성 옵션이 포함되어 있습니다.', + configurationHighRiskTag: '고위험 구성이 통과되었습니다.', + configurationNotTested: '현재 구성은 테스트되지 않았습니다.', + configurationNotTestedTag: '테스트되지 않음', + configurationPassed: '현재 구성이 보안 및 기능 검사를 통과했습니다.', + configurationPassedTag: '테스트 통과', + configurationStaleHelper: '구성이 변경되었습니다. 저장하기 전에 다시 테스트하세요.', + configurationStaleTag: '결과가 만료되었습니다.', + configurationTestMeta: + '{time}에 테스트했으며 {duration}ms 만에 완료했습니다. 공급자의 원시 응답은 저장하지 않습니다.', + configurationTestResult: '구성 테스트 결과', + configurationTestResultDesc: + '이것은 Discovery 및 기능만 확인합니다. 인증 코드를 교환하거나 Client Secret를 증명하지 않습니다. 엔드투엔드 확인을 위해 브라우저 테스트 로그인을 사용하세요.', + configurationTestSuccess: 'OIDC 구성 테스트에 성공했습니다.', + configurationTesting: '현재 OIDC 구성 테스트 중...', + configurationTestingTag: '테스트 중', + configureSecret: 'Client Secret 설정', + conflictExistingRename: '바인딩된 subject가 이미 사용 중인 새 사용자 이름을 반환합니다', + conflictExistingRenameResult: '기존 User.Name를 유지하고 바인딩된 사용자가 로그인하도록 허용', + conflictLDAP: 'LDAP 사용자', + conflictLocal: '로컬 사용자', + conflictNewAvailable: '새 subject와 매핑된 사용자 이름을 사용할 수 있습니다', + conflictNewAvailableResult: '엔터프라이즈 사용자를 생성하고 기본 역할 할당', + conflictNone: '충돌 없음', + conflictOIDC: '다른 OIDC ID', + conflictOccupied: '매핑된 사용자 이름은 로컬 사용자, LDAP 사용자 또는 다른 OIDC 신원에 속합니다.', + conflictOccupiedResult: '새 ID를 거부합니다. 자동으로 바인딩하거나 병합하지 않음', + conflictType: '충돌 유형', + connectionSecurity: '연결 보안', + connectionSecurityDesc: 'TLS 정책은 Discovery, Token, JWKS 및 UserInfo 요청에 적용됩니다.', + connectionTest: '연결 및 구성 테스트', + connectionTestCompatibilityDesc: '사용자 지정 엔드포인트 및 프로토콜 보안 정책을 검증합니다.', + connectionTestStandardDesc: '엔드포인트와 기능은 Issuer에서 자동으로 검색됩니다.', + connectionTestTab: '연결 테스트', + customCA: '사용자 지정 CA', + customCAHelper: '이 인증 소스에만 적용되고 로그에는 기록되지 않습니다.', + customCARequired: '사용자 지정 CA 인증서를 입력하세요.', + defaultRole: '기본 역할', + defaultRoleHelper: + '사용자를 처음 생성할 때만 할당하며, 이후 로그인에서는 역할을 변경하지 않습니다.', + defaultRolePlaceholder: '역할 선택', + defaultRoleRequired: '유효한 기본 역할을 선택하세요.', + disableAfterSave: 'OIDC는 저장 후 비활성화됩니다.', + disableConfirm: + 'OIDC를 비활성화하면 이 인증 소스 사용자의 접근 권한이 즉시 무효화됩니다. 계속하시겠습니까?', + disableDiscardConfirm: + 'OIDC를 비활성화하는 것은 긴급 조치입니다. 로그인 항목만 닫히고 이 소스 사용자의 액세스가 즉시 무효화됩니다. Client Secret 변경사항을 포함하여 이 페이지에서 저장되지 않은 다른 변경사항은 삭제됩니다. 계속하시겠습니까?', + disableTitle: 'OIDC 비활성화', + disabled: '비활성화됨', + discoveryAllowlist: 'Discovery 보안 허용 목록', + enable: '활성화', + enableAfterSave: 'OIDC는 성공적으로 저장되면 활성화됩니다.', + enabled: '활성화됨', + endSessionEndpoint: 'End Session Endpoint', + endSessionEndpointHelper: + '향후 사용을 위해 저장합니다. 공급자 시작 로그아웃은 이번 버전에 포함되지 않습니다.', + endSessionEndpointInvalid: '유효한 End Session Endpoint를 입력하세요.', + endpointDiscoveryPlaceholder: '연결 테스트 후 표시됩니다', + firstLogin: '첫 번째 로그인', + firstLoginPolicy: '로컬 기업 사용자를 생성하고 구성된 기본 역할을 할당하세요.', + fixedAuthorizationCode: 'Authorization Code Flow', + fixedNoTokenPersistence: 'Token, Claims 및 verifier를 저장하지 않음', + fixedSecurityPolicy: '항상 시행됩니다. 구성 필요 없음', + fixedStateNonce: '일회성 state 및 nonce', + fixedTokenValidation: 'ID Token 서명 및 Claims 검증', + highRiskSaveConfirm: + '이 활성화된 구성에는 고위험 호환성 옵션이 포함되어 있습니다. 격리된 환경에 필요한지 확인하세요.', + highRiskTitle: '고위험 OIDC 구성', + hs256Compatibility: 'HS256(호환성)', + hs256KeyHelper: + 'HS256은 항상 이 인증 소스의 Client Secret을 사용하며 별도의 서명 키를 허용하지 않습니다.', + hs256Warning: + 'HS256은 ID Token 서명에 공유 대칭 비밀을 사용합니다. 공급자가 비대칭 알고리즘을 사용할 수 없는 경우에만 사용하세요.', + identityBindingPolicy: + '신원은 AuthSourceID + issuer + subject로 고정됩니다. 사용자 이름이 같더라도 다른 계정을 자동으로 연결하지 않습니다.', + identityMissing: 'ID 비활성', + issuer: 'Issuer URL', + issuerHelper: 'ID Token iss 값과 Discovery issuer는 이 값과 정확히 일치해야 합니다.', + issuerInvalid: '쿼리나 프래그먼트가 없는 유효한 HTTP 또는 HTTPS Issuer URL을 입력하세요.', + issuerRequired: 'Issuer URL을 입력하세요.', + jwksRotation: '자동 JWKS 회전', + jwksURI: 'JWKS URI', + jwksURIHelper: '키 소스가 JWKS인 경우 비대칭 서명에 필요합니다.', + jwksURIInvalid: '선택한 서명 키 소스에 유효한 JWKS URI를 입력하세요.', + keepExistingRole: '기존 역할 및 로컬 권한 유지', + localSecurityData: '로컬 보안 데이터', + localSecurityDataPolicy: '역할, MFA, API Keys, Passkeys 또는 로컬 권한을 덮어쓰지 마십시오.', + localCredentialsManaged: + '사용자 이름과 로컬 비밀번호는 OIDC에서 관리하므로 여기에서 편집할 수 없습니다. 역할, 권한, MFA, API Keys 및 Passkeys는 로컬에 유지됩니다.', + localUserFields: '로컬 사용자 필드', + localUserFieldsDesc: + '첫 번째 릴리스에서는 User.Name만 매핑하고 JSON 매핑 표현식을 사용하지 않습니다.', + loginWith: '{provider}(으)로 로그인', + manualEndpoints: '사용자 지정 엔드포인트', + manualEndpointsDesc: + 'Discovery가 불완전하거나 업스트림 게이트웨이가 엔드포인트를 다시 쓰는 경우에만 사용하십시오.', + mappingResult: '매핑 결과', + mode: '연결 모드', + modeRequired: '연결 모드를 선택하세요.', + nameClaim: '사용자 이름 Claim', + nameClaimHelper: '사용자 이름이 포함된 필드 이름을 입력하세요. 예: preferred_username', + nameClaimRequired: '사용자 이름 Claim을 입력하세요.', + nameConflict: '이름 충돌 정책', + panelURL: '1Panel 공개 URL', + panelURLHTTPWarning: + 'HTTP는 인가 응답을 보호하지 않습니다. 공급자가 허용한 격리된 사설 환경에서만 사용하세요.', + panelURLHelper: '사용자가 1Panel에 접속하는 주소를 입력하세요. 콜백 URL 생성에 사용됩니다.', + panelURLInvalid: '구성표, 호스트 및 선택적 포트만 포함하는 원본을 입력하세요.', + panelURLRequired: '1Panel 공개 URL을 입력하세요.', + pkceDisabled: '비활성화됨(호환성만 해당)', + pkceDisabledWarning: 'PKCE를 비활성화하면 인증 코드 가로채기에 대한 보호가 줄어듭니다.', + pkceHelper: 'S256를 선호하세요. plain 챌린지 방법은 절대 제공되지 않습니다.', + pkceS256: 'S256(권장)', + plannedHandling: '계획된 처리', + privateNetworkIdP: '개인 네트워크 IdP', + privateNetworkIdPHelper: + '개인 주소를 명시적으로 허용합니다. 메타데이터, 루프백, 링크-로컬, 리디렉션 및 DNS 리바인딩은 차단된 상태로 유지됩니다.', + privateNetworkWarning: '이 인증 소스에 대해 개인 네트워크 액세스가 활성화되어 있습니다.', + protocolCompatibility: '프로토콜 호환성', + protocolCompatibilityDesc: 'ID Token 서명 검증은 비활성화할 수 없습니다.', + providerAndClient: '공급자 및 클라이언트', + providerAndClientDesc: + 'Client Secret은 교체하거나 지울 수만 있으며 페이지에서 다시 표시하지 않습니다.', + providerCapabilities: '공급자 기능', + recentTestSuccess: '마지막 테스트 성공: {0}', + recommended: '권장', + rejectPlain: 'plain 거부됨', + replaceSecret: 'Client Secret 교체', + requestAndClaims: '요청 및 속성', + requestAndClaimsDesc: '권한 부여 범위, 사용자 정보 보완 및 요청 매개변수를 구성합니다.', + requestTimeout: '요청 시간 초과', + requestTimeoutRequired: '요청 시간 제한을 입력하세요.', + restore: '복원', + restored: '마지막으로 저장한 OIDC 설정을 복원했습니다.', + result: '결과', + rolesLoadFailed: '역할을 로드할 수 없습니다. 기본 역할을 선택하기 전에 다시 시도하세요.', + roleHandling: '역할 처리', + scenario: '시나리오', + scopes: '권한 부여 범위', + scopesHelper: 'openid를 포함해야 합니다. 여러 범위는 공백으로 구분하세요.', + scopesRequired: 'Scopes에는 openid가 포함되어야 합니다.', + seconds: '초', + secretClearHelper: '지운 후 OIDC를 다시 활성화하려면 새 Client Secret이 필요합니다.', + secretConfigured: '구성됨', + secretNotConfigured: '구성되지 않음', + secretPlaceholder: '새 Client Secret을 입력하세요', + secretReplaceHelper: + '저장하면 새 비밀 값으로 교체됩니다. OIDC Provider의 Client Secret도 함께 업데이트하세요.', + secretRequiredHelper: 'OIDC를 활성화하기 전에 Client Secret를 구성하세요.', + secretRequiredToEnable: 'OIDC를 활성화하기 전에 Client Secret를 구성하세요.', + secretSavedHelper: '암호화되어 저장됩니다. 비워 두면 현재 시크릿을 유지합니다.', + secretWaiting: '입력 대기 중', + secretWillClear: '삭제됩니다', + secretWillReplace: '대체됩니다', + signingAlgorithm: 'ID Token 서명 알고리즘', + signingAlgorithmHelper: '백엔드 보안 허용 목록에 있는 알고리즘만 사용할 수 있습니다.', + signingKey: '서명 키', + signingKeyClientSecret: 'Client Secret(HS256 전용)', + signingKeyJWKS: '자동 회전이 포함된 JWKS URI', + signingKeySource: '서명 키 소스', + signingKeySourceHelper: 'JWKS를 선호합니다. 정적 공개 키는 자동으로 순환될 수 없습니다.', + signingKeyStatic: '정적 JWK 또는 PEM 공개 키', + standardDiscovery: '표준 OIDC Discovery', + standardDiscoveryDesc: '1Panel은 엔드포인트와 기능을 검색하지만 원시 문서는 저장하지 않습니다.', + standardMode: '표준 모드', + standardModeHelper: 'Issuer의 엔드포인트, 서명 기능 및 PKCE 지원을 알아보세요.', + standardProtocolPolicy: '표준 프로토콜 정책', + standardProtocolPolicyDesc: + '서명 기능은 자동으로 협상됩니다. 여기에는 서명 키가 입력되지 않습니다.', + staticSigningKey: '정적 서명 공개 키', + staticSigningKeyHelper: '공개 키 자료만 허용됩니다. 공급자 키가 변경되면 수동으로 교체하세요.', + staticSigningKeyPlaceholder: 'JWK, JWKS JSON 또는 PEM 공개 키를 붙여넣으세요.', + staticSigningKeyRequired: '정적 서명 공개 키를 제공하세요.', + staticSigningKeyWarning: + '정적 서명 키는 자동으로 회전할 수 없습니다. 공급자가 키를 회전하기 전에 업데이트하세요.', + settingLoadFailed: 'OIDC 설정을 로드할 수 없습니다', + settingLoadFailedHelper: + '현재 설정 위에 빈 기본 구성이 저장되지 않도록 양식이 잠겨 있습니다. 연결이 복구된 후 다시 시도하세요.', + subsequentLogin: '다음 로그인', + subsequentLoginPolicy: + 'subject로 바인딩을 찾고 새 사용자 이름을 사용할 수 있는 경우에만 User.Name을 업데이트합니다.', + testBeforeBrowserTest: '브라우저 테스트 로그인을 시작하기 전에 현재 구성을 테스트하세요.', + testBeforeEnable: '구성 변경 사항을 저장하기 전에 현재 구성을 테스트하세요.', + testConfiguration: '구성 테스트', + testDiscovery: 'Discovery 테스트', + tlsCustomCA: 'HTTPS · 사용자 지정 CA 인증서', + tlsPrivateHTTP: 'HTTP · 개인 네트워크만 해당(위험)', + tlsPrivateHTTPWarning: + 'HTTP는 전송 암호화를 제공하지 않으며 명시적으로 허용된 개인 대상으로 제한됩니다.', + tlsSkipVerify: 'HTTPS · 인증서 확인 건너뛰기(위험)', + tlsSystem: 'HTTPS · 시스템 인증서 확인(권장)', + tokenEndpoint: 'Token Endpoint', + tokenEndpointInvalid: '유효한 Token Endpoint를 입력하세요.', + transportSecurity: '전송 보안', + transportSecurityHelper: + 'HTTPS 사용을 권장합니다. 사설 HTTP를 사용하려면 사설 네트워크 접근도 명시적으로 허용해야 합니다.', + unsavedChanges: '저장되지 않은 OIDC 설정이 있습니다.', + usedClaim: 'Claim 사용됨', + userInfoEndpoint: 'UserInfo Endpoint', + userInfoEndpointHelper: + '사용자 이름 필드가 없으면 이 엔드포인트에서 보완합니다. 보완하지 않으려면 비워 두세요.', + userInfoEndpointInvalid: '유효한 UserInfo Endpoint를 입력하세요.', + userMapping: '사용자 설정', + userMappingDesc: + 'OIDC 사용자 이름 매핑과 첫 로그인 시 사용자 생성에 사용할 기본 노드 및 역할을 설정합니다.', + }, + saml2: { + actionCreate: '사용자 만들기', + actionPending: '결과를 기다리는 중', + actionReject: '로그인 거부', + actionReuse: '연결된 사용자 사용', + assignDefaultRole: '기본 역할 할당: {role}', + basic: '기본 설정', + basicDesc: '대부분의 표준 SAML2 IdP에 필요한 일반 설정을 구성합니다.', + browserTest: '로그인 테스트', + browserTestConflict: '신원은 확인되었지만 사용자 이름이 충돌합니다', + browserTestConflictHelper: '매핑된 사용자 이름은 다른 신원에 속하므로 자동으로 연결하지 않습니다.', + browserTestExpired: '브라우저 테스트가 만료되었습니다.', + browserTestExpiredHelper: '만료되기 전에 새 브라우저 테스트를 시작하고 인증을 완료하세요.', + browserTestFailed: '브라우저 테스트 실패', + browserTestFailedHelper: '신원 미리보기를 완료할 수 없습니다. 현지화된 백엔드 오류를 검토하세요.', + browserTestIsolation: + '실제 인증 왕복을 수행하지만 사용자를 생성하거나 업데이트하지 않고, 역할을 할당하거나 인증된 패널 세션을 생성하지 않습니다.', + browserTestPopupBlocked: '이 사이트에 대한 팝업을 허용한 다음 브라우저 테스트를 다시 시작하세요.', + browserTestPopupClosed: '테스트가 완료되기 전에 인증 창이 닫혔습니다.', + browserTestSuccess: '공급자 확인 성공', + browserTestSuccessHelper: '사용자 또는 세션을 변경하지 않고 ID 매핑을 미리 보았습니다.', + browserTestTitle: 'SAML2 브라우저 테스트 로그인', + browserTestWaiting: '공급자 인증 대기 중', + browserTestWaitingHelper: + '새 브라우저 창에서 로그인을 완료하세요. 이 페이지는 자동으로 업데이트됩니다.', + certificateFileInvalid: '유효한 PEM, CRT 또는 CER 인증서 파일을 선택하세요.', + configured: '구성됨', + configurationFailedHelper: '테스트에 실패했습니다. 페이지에 현지화된 백엔드 오류만 표시됩니다.', + configurationNotTested: '현재 구성은 테스트되지 않았습니다.', + configurationPassed: '현재 구성이 보안 및 기능 검사를 통과했습니다.', + configurationStaleHelper: '인증에 민감한 설정이 변경되었습니다. 현재 초안을 다시 테스트하세요.', + configurationTestSuccess: 'SAML2 구성 테스트에 성공했습니다.', + configurationTesting: '현재 SAML2 구성 테스트 중...', + conflictLDAP: 'LDAP 사용자', + conflictLocal: '로컬 사용자', + conflictNone: '충돌 없음', + conflictOIDC: '다른 OIDC ID', + conflictSAML2: '다른 SAML2 ID', + conflictType: '충돌 유형', + credentialFileReadFailed: '자격 증명 파일을 읽을 수 없습니다.', + credentialFileTooLarge: '자격 증명 파일은 256 KiB를 초과할 수 없습니다.', + credentialsRequired: 'SP 개인 키와 인증서를 모두 구성하세요.', + defaultRole: '새 사용자 역할', + defaultRoleHelper: + '최초 생성 시에만 지정하며 이후 로그인에서는 로컬 역할, MFA 및 권한을 유지합니다.', + defaultRolePlaceholder: '역할 선택', + defaultRoleRequired: '유효한 기본 역할을 선택하세요.', + disableConfirm: + 'SAML2를 비활성화하면 새 로그인이 즉시 거부되고 해당 사용자 세션이 무효화됩니다. 계속하시겠습니까?', + disableDiscardConfirm: + 'SAML2를 비활성화하면 이 페이지의 저장되지 않은 다른 변경사항이 삭제되고 사용자 세션이 즉시 무효화됩니다. 계속하시겠습니까?', + disableTitle: 'SAML2 비활성화', + disabled: '비활성화', + enable: '활성화', + enabled: '활성화됨', + idpMetadata: 'IdP 메타데이터', + idpMetadataDesc: 'URL 또는 XML 중 하나를 입력합니다. 둘 다 있으면 URL이 우선합니다.', + keepExistingRole: '기존 역할 및 로컬 권한 유지', + loginWith: '{provider}(으)로 로그인', + mappingResult: '매핑 결과', + metadataRequired: 'IdP Metadata URL 또는 XML을 입력하세요.', + metadataURLHelper: '백엔드는 테스트 및 저장 중에 메타데이터를 다운로드하고 검증합니다.', + metadataURLInvalid: '자격 증명이나 프래그먼트가 없는 유효한 HTTPS 메타데이터 URL을 입력하세요.', + metadataURLRecommended: '메타데이터 URL(권장)', + metadataXML: '메타데이터 XML', + metadataXMLHelper: 'IdP가 접근 가능한 메타데이터 URL을 제공하지 않을 때 사용하세요.', + metadataXMLInvalid: '유효한 EntityDescriptor 메타데이터 XML을 입력하세요.', + metadataXMLPlaceholder: '... 붙여넣기', + nameAttribute: '사용자 이름 속성', + nameAttributeHelper: '검증된 SAML Assertion에서 이 속성을 읽어 1Panel 사용자 이름에 매핑합니다.', + nameAttributePlaceholder: '예: uid, username 또는 account', + nameAttributeRequired: '사용자 이름 속성을 입력하세요.', + notConfigured: '구성되지 않음', + or: '또는', + pageDesc: 'IdP Metadata로 기업 SSO를 연결하고 일반 설정을 한 페이지에서 완료합니다.', + plannedHandling: '계획된 처리', + privateKeyFileInvalid: '유효한 PEM 개인 키 파일을 선택하세요.', + recentTestSuccess: '마지막 테스트 성공: {0}', + restore: '복원', + restored: '마지막으로 저장한 SAML2 설정을 복원했습니다.', + roleHandling: '역할 처리', + rolesLoadFailed: '역할을 로드할 수 없습니다. 기본 역할을 선택하기 전에 다시 시도하세요.', + selectFile: '파일 선택', + serviceStatus: '서비스 상태', + serviceStatusDesc: 'SAML2를 활성화하려면 현재 구성이 테스트를 통과해야 합니다.', + settingLoadFailed: 'SAML2 설정을 로드할 수 없습니다', + settingLoadFailedHelper: + '현재 설정 위에 빈 기본 구성이 저장되지 않도록 양식이 잠겨 있습니다. 연결이 복구된 후 다시 시도하세요.', + spCertificate: 'SP 인증서', + spCertificateHelper: 'IdP가 로그인 및 로그아웃 요청을 검증할 수 있도록 SP 메타데이터에 게시됩니다.', + spCredentials: 'SP 개인 키 및 인증서', + spCredentialsDesc: + '로그인 및 로그아웃 메시지 서명에 사용됩니다. 서명 및 검증 정책은 백엔드에서 고정됩니다.', + spPrivateKey: 'SP 개인 키', + spPrivateKeyHelper: + 'AuthnRequest 및 로그아웃 메시지 서명에 사용됩니다. 저장 시 암호화되며 표시되지 않습니다.', + syncLogout: '동기화 로그아웃', + syncLogoutHelper: '1Panel 또는 IdP에서 로그아웃하면 다른 쪽에서도 함께 로그아웃됩니다.', + testBeforeBrowserTest: '브라우저 테스트 로그인을 시작하기 전에 현재 구성을 테스트하세요.', + testBeforeEnable: '민감한 변경 사항을 활성화하거나 저장하기 전에 현재 구성을 테스트하세요.', + testConfiguration: '구성 테스트', + unsavedChanges: '저장되지 않은 SAML2 설정이 있습니다.', + usedAttribute: '사용자 이름 매핑', + usersAndRoles: '사용자 및 역할', + usersAndRolesDesc: + '패널 사용자 이름 매핑과 첫 로그인 시 사용자 생성에 사용할 기본 노드 및 역할을 설정합니다.', + }, ldap: { + basic: '기본 설정', + loginTitle: 'LDAP 로그인', + loginWith: 'LDAP로 로그인', + backToLocalLogin: '패널 로그인으로 돌아가기', enable: '활성화', enabled: '활성화됨', disabled: '비활성화됨', @@ -5663,6 +6035,13 @@ const message = { nodeUpgradePackageCleanHelper: '모든 낮은 버전의 업데이트 패키지를 정리합니다. 계속하시겠습니까?', nodeUpgradeOfflinePackageHelper: '오프라인 환경에서는 다른 아키텍처의 노드를 업데이트하기 전에 해당 업데이트 패키지를 먼저 업로드해야 합니다.', + healthCheck: '상태 확인', + healthCheckFrequency: '확인 주기', + healthCheckFrequencyHelper: + '백엔드 노드 상태를 주기적으로 확인합니다. 확인을 비활성화하려면 0을 입력하세요.', + healthCheckFrequencyLimit: '확인 주기는 하루를 초과할 수 없으며 음수가 아닌 정수여야 합니다.', + loadFailedNodeResources: '오류 노드 리소스 불러오기', + loadFailedNodeResourcesHelper: '노드 목록을 열 때 오류 노드의 리소스 정보도 함께 불러옵니다.', nodeUnhealthy: '노드 상태 이상', deletedNode: '삭제된 노드 {0}은(는) 현재 업그레이드 작업을 지원하지 않습니다!', nodeUnhealthyHelper: '노드 상태 이상이 감지되었습니다. [노드 관리]에서 확인 후 다시 시도하세요!', @@ -5677,9 +6056,9 @@ const message = { nodeItem: '노드 관리', panelItem: '패널 관리', addPanel: '패널 추가', - addPanelHelper: 'パネルの追加に成功後、[概要 - パネル]で対象パネルに迅速にアクセスできます。', - panel: '1Panel パネル', - others: 'その他のパネル', + addPanelHelper: '패널을 추가한 후 [개요 - 패널]에서 대상 패널에 빠르게 접근할 수 있습니다.', + panel: '1Panel 패널', + others: '기타 패널', addNode: '노드 추가', connInfo: '연결 정보', nodeInfo: '노드 정보', @@ -5754,6 +6133,8 @@ const message = { offlineHelper: '노드가 오프라인 환경일 때 사용', appUpgrade: '앱 업그레이드', appUpgradeHelper: '업그레이드가 필요한 앱이 {0}개 있습니다', + dashboardSetting: '개요 설정', + keepOneDashboardComponent: '개요 섹션을 하나 이상 유지하세요', }, customApp: { name: '사용자 정의 앱 저장소', @@ -6140,35 +6521,35 @@ const message = { cpu: 'CPU', memory: '메모리', disk: '디스크', - overview: 'Overview', - kvmUnavailable: 'No available KVM hardware virtualization capability was detected.', - kvmCheckCpu: 'Confirm that the host CPU supports Intel VT-x or AMD-V virtualization.', - kvmCheckBios: 'Enable virtualization options in BIOS/UEFI.', - kvmCheckModule: 'Confirm that the kvm, kvm_intel, or kvm_amd kernel module is loaded correctly.', + overview: '개요', + kvmUnavailable: '사용 가능한 KVM 하드웨어 가상화 기능을 찾지 못했습니다.', + kvmCheckCpu: '호스트 CPU가 Intel VT-x 또는 AMD-V 가상화를 지원하는지 확인하세요.', + kvmCheckBios: 'BIOS/UEFI에서 가상화 옵션을 활성화하세요.', + kvmCheckModule: 'kvm, kvm_intel 또는 kvm_amd 커널 모듈이 올바르게 로드되었는지 확인하세요.', kvmCheckDevice: - 'Confirm that /dev/kvm exists and the current environment is not a container or cloud host without KVM support.', - abnormal: 'Abnormal', - resourceOverview: 'Resource Overview', - cpuAllocated: 'CPU Allocated', - memoryAllocated: 'Memory Allocated', - storageUsed: 'Storage Used', - riskReminder: 'Risk Reminders', - noRisk: 'No risks', - runtimeHealth: 'Runtime Health', - runtimeAbnormal: 'VM runtime is abnormal', - noDependency: 'No dependency check data', - storageOverview: 'Storage Overview', - totalAllocated: 'Calculated by total VM configuration', - runningAllocated: 'Running allocation: {0}', - storageAvailable: 'Available: {0}', - inProgress: 'In progress', - needAttention: 'Needs attention', - normal: 'Normal', - environmentRisk: 'The VM runtime is not ready. Fix dependencies or virtualization services.', - storageRisk: 'Storage pool {0} usage has reached {1}%.', - abnormalRisk: '{0} VMs are in an abnormal state.', - pausedRisk: '{0} VMs are paused.', - memoryRisk: 'VM memory allocation has reached {0}%.', + '/dev/kvm이 존재하며 현재 환경이 KVM을 지원하지 않는 컨테이너 또는 클라우드 호스트가 아닌지 확인하세요.', + abnormal: '비정상', + resourceOverview: '리소스 개요', + cpuAllocated: '할당된 CPU', + memoryAllocated: '할당된 메모리', + storageUsed: '사용한 스토리지', + riskReminder: '위험 알림', + noRisk: '위험 없음', + runtimeHealth: '실행 환경 상태', + runtimeAbnormal: 'VM 실행 환경이 비정상입니다', + noDependency: '종속성 검사 데이터가 없습니다', + storageOverview: '스토리지 개요', + totalAllocated: '전체 VM 구성 기준으로 계산', + runningAllocated: '실행 중 할당량: {0}', + storageAvailable: '사용 가능: {0}', + inProgress: '진행 중', + needAttention: '확인 필요', + normal: '정상', + environmentRisk: 'VM 실행 환경이 준비되지 않았습니다. 종속성 또는 가상화 서비스를 수정하세요.', + storageRisk: '스토리지 풀 {0} 사용률이 {1}%에 도달했습니다.', + abnormalRisk: '{0}개의 VM이 비정상 상태입니다.', + pausedRisk: '{0}개의 VM이 일시 중지되었습니다.', + memoryRisk: 'VM 메모리 할당률이 {0}%에 도달했습니다.', cpuLimitHelper: '현재 사용 가능한 CPU: {0} 코어', cpuLimitExceeded: 'CPU가 제한을 초과했습니다. 현재 최대 사용 가능: {0} 코어.', memoryLimitHelper: '현재 할당 가능한 메모리: {0} (호스트는 {1} 메모리를 예약해야 함)', @@ -6177,11 +6558,11 @@ const message = { storageLimitExceeded: '디스크 용량이 제한을 초과했습니다. 현재 최대 사용 가능: {0}.', iso: 'ISO', createFromTemplate: '템플릿에서 생성', - template: 'Template', - templateName: 'Template Name', - convertToTemplate: 'Convert to Template', - sourceVM: 'Source VM', - templateSize: 'Template Size', + template: '템플릿', + templateName: '템플릿 이름', + convertToTemplate: '템플릿으로 변환', + sourceVM: '원본 VM', + templateSize: '템플릿 크기', deleteTemplateConfirm: '템플릿 {0}을(를) 삭제합니다. 이 작업은 되돌릴 수 없습니다. 계속하시겠습니까?', orphanClean: '고아 데이터 정리', orphanScan: '다시 검색', @@ -6225,21 +6606,21 @@ const message = { available: '사용 가능', vmCount: '연결된 VM', usedIPs: '사용된 IP', - monitor: 'Monitor', - monitorNotReady: 'The virtual machine is not running. Monitoring data is unavailable.', - monitorLoadFailed: 'Failed to get VM monitoring data.', - monitorLoadFailedWithReason: 'Failed to get VM monitoring data: {0}', - rename: 'Rename', + monitor: '모니터링', + monitorNotReady: '가상 머신이 실행 중이 아니어서 모니터링 데이터를 사용할 수 없습니다.', + monitorLoadFailed: 'VM 모니터링 데이터를 가져오지 못했습니다.', + monitorLoadFailedWithReason: 'VM 모니터링 데이터를 가져오지 못했습니다: {0}', + rename: '이름 변경', newName: '새 이름', - renameHelper: 'Enter a new VM name. The VM must be shut down before renaming.', - renameConfirm: 'Rename virtual machine [{0}] to [{1}]?', - renameRunningHelper: 'Shut down the virtual machine before renaming it.', - cpuUsage: 'CPU Usage', - memoryUsage: 'Memory Usage', - diskIO: 'Disk IO', - networkIO: 'Network IO', - diskReadWrite: 'Disk Read / Write', - networkRxTx: 'Network RX / TX', + renameHelper: '새 VM 이름을 입력하세요. 이름을 변경하기 전에 VM을 종료해야 합니다.', + renameConfirm: '가상 머신 [{0}]의 이름을 [{1}](으)로 변경하시겠습니까?', + renameRunningHelper: '이름을 변경하기 전에 가상 머신을 종료하세요.', + cpuUsage: 'CPU 사용률', + memoryUsage: '메모리 사용률', + diskIO: '디스크 I/O', + networkIO: '네트워크 I/O', + diskReadWrite: '디스크 읽기/쓰기', + networkRxTx: '네트워크 수신/송신', rx: 'RX', tx: 'TX', console: '콘솔', @@ -6247,16 +6628,18 @@ const message = { consoleDisconnected: 'VNC 콘솔 연결이 끊어졌습니다.', consoleConnectFailed: 'VNC 콘솔 연결에 실패했습니다. 콘솔 프록시 서비스를 확인하세요.', consoleCredentialsRequired: 'VNC 콘솔에 인증 정보가 필요합니다. 백엔드 프록시 구성을 확인하세요.', - snapshot: 'Snapshot', - createSnapshot: 'Create Snapshot', - recoverSnapshot: 'Recover Snapshot', + snapshot: '스냅샷', + createSnapshot: '스냅샷 생성', + recoverSnapshot: '스냅샷 복구', snapshotSize: '사용량', - currentSnapshot: 'Current', - snapshotEmpty: 'No snapshots', + currentSnapshot: '현재', + snapshotEmpty: '스냅샷 없음', snapshotHelper: - 'A snapshot saves the current VM state as a restore point. Subsequent data changes are recorded in a delta file without changing the original disk. Restoring a snapshot returns the VM to that point in time.', + '스냅샷은 현재 VM 상태를 복원 지점으로 저장합니다. 이후 데이터 변경은 원본 디스크를 변경하지 않고 델타 파일에 기록됩니다. 스냅샷을 복구하면 VM이 해당 시점의 상태로 돌아갑니다.', + snapshotOperationHelper: + '현재 스냅샷은 삭제할 수 없습니다. 가상 머신이 종료된 경우에만 스냅샷을 복구할 수 있습니다.', snapshotRecoverConfirm: - 'Recover virtual machine [{1}] to snapshot [{0}]? The VM disk will be restored to the snapshot state.', + '가상 머신 [{1}]을(를) 스냅샷 [{0}](으)로 복구하시겠습니까? VM 디스크가 스냅샷 시점의 상태로 복원됩니다.', interface: '네트워크 인터페이스', device: '장치', path: '경로', diff --git a/frontend/src/lang/modules/lo.ts b/frontend/src/lang/modules/lo.ts index b34aa0cbc..24f15ebef 100644 --- a/frontend/src/lang/modules/lo.ts +++ b/frontend/src/lang/modules/lo.ts @@ -167,6 +167,7 @@ const message = { deleteSuccess: 'ລຶບສຳເລັດແລ້ວ', loginSuccess: 'ເຂົ້າສູ່ລະບົບສຳເລັດແລ້ວ', operationSuccess: 'ດຳເນີນການສຳເລັດແລ້ວ', + operationFailed: 'ດຳເນີນການລົ້ມເຫຼວ', copySuccess: 'ຄັດລອກສຳເລັດແລ້ວ', notSupportOperation: 'ບໍ່ຮອງຮັບການດຳເນີນການນີ້', requestTimeout: 'ການຮ້ອງຂໍໝົດເວລາ, ກະລຸນາລອງໃໝ່ພາຍຫຼັງ', @@ -209,6 +210,7 @@ const message = { username: 'ຊື່ຜູ້ໃຊ້', password: 'ລະຫັດຜ່ານ', passkey: 'ເຂົ້າສູ່ລະບົບດ້ວຍ Passkey', + otherLoginMethods: 'ວິທີເຂົ້າລະບົບອື່ນ', welcome: 'ຍິນດີຕ້ອນຮັບກັບຄືນ. ເຂົ້າສູ່ລະບົບດ້ວຍຊື່ຜູ້ໃຊ້ ແລະ ລະຫັດຜ່ານຂອງທ່ານ.', errorAuthInfo: 'ຊື່ຜູ້ໃຊ້ ຫຼື ລະຫັດຜ່ານບໍ່ຖືກຕ້ອງ, ກະລຸນາລອງໃໝ່.', errorMfaInfo: 'ຂໍ້ມູນການຢືນຢັນຕົວຕົນບໍ່ຖືກຕ້ອງ, ກະລຸນາລອງໃໝ່.', @@ -475,7 +477,7 @@ const message = { cpuSteal: 'Steal', cpuTop: '5 ອັນດັບໂປຣເຊສທີ່ໃຊ້ CPU ສູງສຸດ', memTop: '5 ອັນດັບໂປຣເຊສທີ່ໃຊ້ໜ່ວຍຄວາມຈຳສູງສຸດ', - loadAverage: 'ພາລະສະເລ່ຍໃນ 1 ນາທີຜ່ານມາ | ພາລະສະເລ່ຍໃນ {n} ນາທີຜ່ານມາ', + loadAverage: 'ພາລະສະເລ່ຍໃນ 1 ນາທີຜ່ານມາ | ພາລະສະເລ່ຍໃນ {0} ນາທີຜ່ານມາ', load: 'ພາລະ', mount: 'ຈຸດເຊື່ອມຕໍ່ (Mount point)', fileSystem: 'ລະບົບໄຟລ໌', @@ -584,8 +586,8 @@ const message = { mongodbPermissionUserAdmin: 'ຜູ້ຈັດການຜູ້ໃຊ້', pgUserHelper: 'ໃຊ້ບັນຊີຊຸບເປີຢູເຊີຂອງຖານຂໍ້ມູນ.', ssl: 'ໃຊ້ SSL', - clientKey: 'Client private key', - clientCert: 'Client certificate', + clientKey: 'ກະແຈສ່ວນຕົວຂອງ Client', + clientCert: 'ໃບຢັ້ງຢືນຂອງ Client', caCert: 'CA certificate', hasCA: 'ມີໃບຢັ້ງຢືນ CA', skipVerify: 'ຂ້າມການກວດສອບໃບຢັ້ງຢືນ', @@ -611,11 +613,11 @@ const message = { threadCacheHitHelper: 'ຫາກຕ່ຳເກີນໄປ, ໃຫ້ເພີ່ມ "thread_cache_size".', indexHit: 'Index hit', indexHitHelper: 'ຫາກຕ່ຳເກີນໄປ, ໃຫ້ເພີ່ມ "key_buffer_size".', - innodbIndexHit: 'Innodb index hit rate', + innodbIndexHit: 'ອັດຕາການຈັບຄູ່ດັດຊະນີ Innodb', innodbIndexHitHelper: 'ຫາກຕ່ຳເກີນໄປ, ໃຫ້ເພີ່ມ "innodb_buffer_pool_size".', - cacheHit: 'Query cache hit rate', + cacheHit: 'ອັດຕາການຈັບຄູ່ Query cache', cacheHitHelper: 'ຫາກຕ່ຳເກີນໄປ, ໃຫ້ເພີ່ມ "query_cache_size".', - tmpTableToDB: 'Temporary table to disk', + tmpTableToDB: 'ຕາຕະລາງຊົ່ວຄາວໄປຍັງດິສກ໌', tmpTableToDBHelper: 'ຫາກໃຫຍ່ເກີນໄປ, ໃຫ້ເພີ່ມ "tmp_table_size".', openTables: 'Open tables', openTablesHelper: 'ຄ່າການຕັ້ງຄ່າຂອງ "table_open_cache" ຕ້ອງຫຼາຍກວ່າ ຫຼື ເທົ່າກັບຄ່ານີ້.', @@ -722,8 +724,6 @@ const message = { appVersion: 'ເວີຊັນແອັບ', webuiPort: 'ພອດ WebUI', tokenOrAuth: 'Token/ຊື່ຜູ້ໃຊ້ ແລະ ລະຫັດຜ່ານ', - dashboardUsername: 'ຊື່ຜູ້ໃຊ້ Dashboard', - dashboardPassword: 'ລະຫັດຜ່ານ Dashboard', allowedOrigins: 'ທີ່ຢູ່ການເຂົ້າເຖິງ', allowedOriginsRequired: 'ປ້ອນທີ່ຢູ່ການເຂົ້າເຖິງຢ່າງໜ້ອຍໜຶ່ງບ່ອນ', allowedOriginsInvalid: 'ໃຊ້ຮູບແບບ http(s)://host-or-ip[:port]', @@ -798,7 +798,7 @@ const message = { versionUnsupportedHelper: 'ກະລຸນາອັບເກຣດ OpenClaw ເປັນເວີຊັນ {0} ຫຼື ສູງກວ່າ.', skillsGroupBuiltIn: 'ມາພ້ອມກັບລະບົບ', skillsGroupExternal: 'ພາຍນອກ', - skillsGroupWorkspace: 'Workspace', + skillsGroupWorkspace: 'ພື້ນທີ່ເຮັດວຽກ', switchModelSuccess: 'ປ່ຽນໂມເດວສຳເລັດແລ້ວ', channelsTab: 'ຊ່ອງທາງ', agentRoleTab: 'ຕົວແທນ', @@ -808,16 +808,12 @@ const message = { roleMarkdownDescriptions: { 'AGENTS.md': [ 'ຄຳແນະນຳການເຮັດວຽກຂອງຕົວແທນ ແລະ ວິທີການໃຊ້ໜ່ວຍຄວາມຈຳ.', - 'ໂຫຼດເມື່ອເລີ່ມທຸກເຊດຊັນ.', 'ບ່ອນທີ່ດີສຳລັບກົດເກນ, ລຳດັບຄວາມສຳຄັນ ແລະ ລາຍລະອຽດ "ວິທີການສະແດງອອກ".', ], - 'SOUL.md': ['ຕົວຕົນ, ນ້ຳສຽງ ແລະ ຂອບເຂດ.', 'ໂຫຼດໃນທຸກເຊດຊັນ.'], - 'USER.md': ['ຜູ້ໃຊ້ແມ່ນໃຜ ແລະ ຄວນເອີ້ນພວກເຂົາແນວໃດ.', 'ໂຫຼດໃນທຸກເຊດຊັນ.'], - 'IDENTITY.md': ['ຊື່ຂອງຕົວແທນ, ບຸກຄະລິກ ແລະ ອີໂມຈິ.', 'ສ້າງ ຫຼື ອັບເດດໃນລະຫວ່າງຂັ້ນຕອນ bootstrap.'], - 'TOOLS.md': [ - 'ໝາຍເຫດກ່ຽວກັບເຄື່ອງມືທ້ອງຖິ່ນ ແລະ ຂໍ້ຕົກລົງຕ່າງໆ.', - 'ບໍ່ໄດ້ຄວບຄຸມການມີຢູ່ຂອງເຄື່ອງມື; ເປັນພຽງຄຳແນະນຳເທົ່ານັ້ນ.', - ], + 'SOUL.md': ['ຕົວຕົນ, ນ້ຳສຽງ ແລະ ຂອບເຂດ.'], + 'USER.md': ['ຜູ້ໃຊ້ແມ່ນໃຜ ແລະ ຄວນເອີ້ນພວກເຂົາແນວໃດ.'], + 'IDENTITY.md': ['ຊື່ຂອງຕົວແທນ, ບຸກຄະລິກ ແລະ ອີໂມຈິ.'], + 'TOOLS.md': ['ໝາຍເຫດກ່ຽວກັບເຄື່ອງມືທ້ອງຖິ່ນ ແລະ ຂໍ້ຕົກລົງຕ່າງໆ.'], 'HEARTBEAT.md': [ 'ລາຍການກວດສອບສຳລັບການເຮັດວຽກແບບ heartbeat (ເລືອກໄດ້).', 'ຄວນຂຽນໃຫ້ສັ້ນເພື່ອປະຢັດ token.', @@ -826,11 +822,7 @@ const message = { 'ລາຍການກວດສອບຕອນເລີ່ມຕົ້ນລະບົບ ເມື່ອ gateway ຣີສະຕາດ (ເລືອກໄດ້).', 'ຄວນຂຽນໃຫ້ສັ້ນ; ໃຊ້ເຄື່ອງມືຂໍ້ຄວາມສຳລັບການສົ່ງອອກ.', ], - 'BOOTSTRAP.md': [ - 'ຂັ້ນຕອນການເລີ່ມຕົ້ນຄັ້ງທຳອິດ.', - 'ສ້າງສະເພາະ workspace ໃໝ່ເທົ່ານັ້ນ.', - 'ລຶບອອກຫຼັງຈາກຂັ້ນຕອນສຳເລັດ.', - ], + 'BOOTSTRAP.md': ['ຂັ້ນຕອນການເລີ່ມຕົ້ນຄັ້ງທຳອິດ.', 'ສ້າງສະເພາະ workspace ໃໝ່ເທົ່ານັ້ນ.'], }, duplicateBinding: 'ການລວມກັນຂອງຊ່ອງທາງ ແລະ ID ບັນຊີ ຕ້ອງບໍ່ຊ້ຳກັນ', accountIdOptional: 'ID ບັນຊີ (ເລືອກໄດ້)', @@ -862,7 +854,7 @@ const message = { feishu: 'Feishu', pluginNotInstalled: 'ຍັງບໍ່ໄດ້ຕິດຕັ້ງປລັກອິນ. ກະລຸນາຕິດຕັ້ງກ່ອນ.', dmPolicy: 'ນະໂຍບາຍ DM', - threadSession: 'Thread Session', + threadSession: 'ເຊດຊັນເທຣດ', replyMode: 'ໂໝດການຕອບກັບ', requireMention: 'ຕ້ອງມີການກ່າວເຖິງ (Mention)', requireMentionTrue: "ຕ້ອງ {'@'}", @@ -880,11 +872,11 @@ const message = { botDuplicateField: '{field} ມີຢູ່ແລ້ວ', botRequired: 'ເພີ່ມຢ່າງໜ້ອຍໜຶ່ງບັອດ', botId: 'ID ບັອດ', - allowFrom: 'DM Allowlist', + allowFrom: 'ລາຍຊື່ອະນຸຍາດ DM', allowFromPlaceholder: 'ໜຶ່ງ ID ຜູ້ສົ່ງຕໍ່ແຖວ', allowlistPolicyHelper: '{0}. ໃຊ້ສະເພາະເມື່ອ {1} ເປັນ Allowlist.', - systemPrompt: 'System Prompt', - groupAllowFrom: 'Group Allowlist', + systemPrompt: 'ຄຳສັ່ງລະບົບ', + groupAllowFrom: 'ລາຍຊື່ອະນຸຍາດກຸ່ມ', groupAllowFromPlaceholder: 'ໜຶ່ງ ID ກຸ່ມຕໍ່ແຖວ', separateSessionByConversation: 'ແຍກເຊດຊັນຕາມການສົນທະນາ', groupSessionScope: 'ຂອບເຂດເຊດຊັນກຸ່ມ', @@ -894,7 +886,7 @@ const message = { asyncMode: 'ໂໝດ Async', ackText: 'ຂໍ້ຄວາມຮັບຊາບ (Ack Text)', ackTextDefault: 'ໄດ້ຮັບໜ້າວຽກແລ້ວ, ກຳລັງດຳເນີນການ...', - streaming: 'Streaming', + streaming: 'ການສົ່ງແບບສະຕຣີມ', streamingOff: 'ປິດ', streamingPartial: 'ບາງສ່ວນ', streamingBlock: 'ຂັດຂວາງ (Blocking)', @@ -913,7 +905,6 @@ const message = { dashboardAuthAutoRebuildHelper: 'ການບັນທຶກຊື່ຜູ້ໃຊ້ ຫຼື ລະຫັດຜ່ານ Dashboard ຈະສ້າງຄອນເທນເນີໃໝ່ອັດຕະໂນມັດເພື່ອໃຫ້ການປ່ຽນແປງມີຜົນ.', channelDeleteConfirm: 'ລຶບການຕັ້ງຄ່າຊ່ອງທາງ {0}?', - customProviderHelper: 'ຜູ້ໃຫ້ບໍລິການແບບກຳນົດເອງຈະບໍ່ກວດສອບວ່າບັນຊີສາມາດໃຊ້ງານໄດ້ຫຼືບໍ່.', apiTypeBaseURLHelper: 'ປະເພດນີ້ຈະສົ່ງການຮ້ອງຂໍໄປທີ່ {0}. Base URL ທີ່ແນະນຳ: {1}', customImageURLHelper: 'ສຳລັບບັນຊີ Custom ໃຫ້ປ້ອນ URL ຂອງ endpoint ສ້າງຮູບທີ່ຄົບຖ້ວນ. ລະບົບຈະບໍ່ເພີ່ມ path ອັດຕະໂນມັດ. ຕົວຢ່າງ: {0}', @@ -942,7 +933,7 @@ const message = { modelDir: 'ໄດເຣັກທໍຣີໂມເດວ', manualDownload: 'ດາວໂຫຼດດ້ວຍຕົນເອງ', modelSource: 'ແຫຼ່ງທີ່ມາໂມເດວ', - repoID: 'Repository ID', + repoID: 'ID ຄັງເກັບ', endpointLabel: 'ຈຸດເຊື່ອມຕໍ່ (Endpoint) {0}', acceleratedEndpointLabel: 'ຈຸດເຊື່ອມຕໍ່ເລັ່ງຄວາມໄວ {0}', tokenOptionalLabel: '{0} Token (ເລືອກໄດ້)', @@ -1025,7 +1016,7 @@ const message = { 'ການປ່ຽນໂປຣໂຕຄອນບໍ່ຮັບປະກັນວ່າຈະບໍ່ສູນເສຍຂໍ້ມູນ. ຟິວສະເພາະ, ການເອີ້ນໃຊ້ເຄື່ອງມື, ການໃຫ້ເຫດຜົນ ຫຼືເນື້ອຫາຫຼາຍຮູບແບບອາດຖືກຫຼຸດຄຸນນະພາບ ຫຼືສູນເສຍ. ກະລຸນາພິຈາລະນາຄວາມສ່ຽງກ່ອນນຳໃຊ້.', lbPolicyRoundRobin: 'Round Robin', lbPolicyRoundRobinDesc: 'ເລືອກບັນຊີໂມເດວຕາມລຳດັບ. ໃຊ້ເມື່ອລະບົບຫຼັງບ້ານມີຄວາມສາມາດໃກ້ຄຽງກັນ.', - lbPolicyWeightedRoundRobin: 'Weighted Round Robin', + lbPolicyWeightedRoundRobin: 'Round Robin ແບບຖ່ວງນ້ຳໜັກ', lbPolicyWeightedRoundRobinDesc: 'ກະຈາຍການຮ້ອງຂໍຕາມນ້ຳໜັກຂອງບັນຊີໂມເດວ. ນ້ຳໜັກສູງກວ່າຈະໄດ້ຮັບ traffic ຫຼາຍກວ່າ.', lbPolicyFailover: 'Failover', @@ -1051,10 +1042,11 @@ const message = { requestBodyLogIndexPrefix: 'ຄຳນຳໜ້າ Index', requestBodyLogRetentionDays: 'ໄລຍະການເກັບຮັກສາລັອກ Request Body (ມື້)', requestBodyLogMaxBodyKb: 'ຂະໜາດ Request Body ສູງສຸດ (KB)', - requestBody: 'Request Body', + requestBody: 'ເນື້ອຫາຄຳຮ້ອງຂໍ', requestBodySize: 'ຂະໜາດ Request Body', requestBodyTruncated: 'ຖືກຕັດບາງສ່ວນ', - responseBody: 'Response Body', + requestBodyHash: 'Hash ຂອງ Request Body', + responseBody: 'ເນື້ອຫາຄຳຕອບ', responseBodySize: 'ຂະໜາດ Response Body', responseBodyTruncated: 'Response Body ຖືກຕັດບາງສ່ວນ', readableContent: 'ເນື້ອໃນທີ່ອ່ານໄດ້', @@ -1067,7 +1059,7 @@ const message = { statusMessage: 'ຂໍ້ຄວາມສະຖານະ', esLogDropped: 'ລັອກ ES ທີ່ຖືກຖິ້ມ', esLogLastSuccessAt: 'ການຂຽນ ES ລ່າສຸດ', - esLogCircuitOpen: 'Circuit Open', + esLogCircuitOpen: 'ຕົວຕັດວົງຈອນເປີດ', esLogCircuitUntil: 'ES Circuit ຈົນເຖິງ', serviceOperateConfirm: 'ຢືນຢັນທີ່ຈະ {0} ບໍລິການ AI Gateway?', deleteTargetConfirm: 'ລຶບ {0} {1}?', @@ -1090,10 +1082,10 @@ const message = { percent: 'ເປີເຊັນ', ranking: 'ການຈັດອັນດັບ', rank: 'ອັນດັບ', - promptToken: 'Prompt Tokens', - completionToken: 'Completion Tokens', + promptToken: 'Token ຂອງ Prompt', + completionToken: 'Token ຂອງ Completion', totalToken: 'Token ທັງໝົດ', - cachedToken: 'Cached Tokens', + cachedToken: 'Token ທີ່ແຄດໄວ້', cacheHitRate: 'ອັດຕາການພົບ Cache', activeUsers: 'ຜູ້ໃຊ້ທີ່ເຄື່ອນໄຫວ', activeModels: 'ໂມເດວທີ່ເຄື່ອນໄຫວ', @@ -1117,8 +1109,6 @@ const message = { healthUnknown: 'ບໍ່ຮູ້ຈັກ', validationModelMapEmpty: 'ຊື່ການຈັບຄູ່ໂມເດວບໍ່ສາມາດຫວ່າງໄດ້', validationModelMapDuplicate: 'ໂມເດວທີ່ຮ້ອງຂໍ {0} ຊ້ຳກັນ', - validateAvailability: 'ກວດສອບການພ້ອມໃຊ້ງານຂອງບັນຊີ', - validateAvailabilityHelper: 'ສົ່ງຂໍ້ຄວາມຂະໜາດນ້ອຍກ່ອນບັນທຶກເພື່ອຢືນຢັນການໃຊ້ງານ API', modelGroup: 'ກຸ່ມໂມເດວ', modelCapability: 'ຄວາມສາມາດຂອງໂມເດວ', textGeneration: 'ການສ້າງຂໍ້ຄວາມ', @@ -1152,7 +1142,7 @@ const message = { matchedGroups: 'ກຸ່ມທີ່ກົງກັນ', importResult: 'ນຳເຂົ້າແລ້ວ {0}, ຊ້ຳກັນ {1}, ບໍ່ຖືກຕ້ອງ {2}', auditLogs: 'ບັນທຶກການກວດສອບ', - smartRoute: 'Smart Route', + smartRoute: 'ການຈັດເສັ້ນທາງອັດສະລິຍະ', smartRouteGuideTitle: 'ໃຊ້ model=auto ຢູ່ Client ເພື່ອເຂົ້າ Smart Route', smartRouteGuideReady: 'model=auto ຈະເລືອກຈາກກຸ່ມໂມເດວແບບງ່າຍ ຫຼື ຊັບຊ້ອນຕາມຄວາມຊັບຊ້ອນຂອງຄຳຮ້ອງຂໍ. ໂມເດວອື່ນຈະຖືກສົ່ງຕໍ່ຕາມປົກກະຕິ.', @@ -1215,7 +1205,7 @@ const message = { latencyMs: 'ຄວາມຫຼ້າຊ້າ (ms)', smartRouteSettingGuide: 'ຫຼັງຈາກເປີດໃຊ້ ມີພຽງຄຳຮ້ອງຂໍທີ່ໃຊ້ model=auto ເທົ່ານັ້ນທີ່ຈະເປີດ Smart Route. ກຸ່ມແບບງ່າຍໃຊ້ສຳລັບວຽກຕົ້ນທຶນຕ່ຳ; ກຸ່ມແບບຊັບຊ້ອນໃຊ້ສຳລັບວິເຄາະໂຄດ, ອອກແບບສະຖາປັດຕະຍະກຳ, ແກ້ໄຂບັນຫາ ແລະ ວຽກຄ້າຍຄືກັນ.', - sampleLabelPlaceholder: 'simple / complex / high', + sampleLabelPlaceholder: 'ງ່າຍ / ຊັບຊ້ອນ / ສູງ', sampleImportPlaceholder: 'ໜຶ່ງຕົວຢ່າງຕໍ່ແຖວ', }, skillsHub: { @@ -1361,9 +1351,9 @@ const message = { resultMetrics: 'ຕົວຊີ້ວັດຜົນລັບ', contextTokens: 'ຄວາມຍາວ Context', contextTokensHelper: 'ຂີດຈຳກັດ input token ບວກກັບ output token ສຳລັບການທົດສອບນີ້.', - outputThroughput: 'Output Throughput', + outputThroughput: 'ອັດຕາການສົ່ງອອກ', outputThroughputHelper: 'ຈຳນວນ output tokens ທີ່ສ້າງໄດ້ຕໍ່ວິນາທີ. ຍິ່ງສູງຍິ່ງໄວ.', - totalThroughput: 'Total Throughput', + totalThroughput: 'ອັດຕາການປະມວນຜົນລວມ', totalThroughputHelper: 'ຈຳນວນ input ແລະ output tokens ທີ່ປະມວນຜົນຕໍ່ວິນາທີ. ໃຊ້ວັດແທກຄວາມສາມາດໂດຍລວມ.', firstTokenLatency: 'ຄວາມໜ່ວງຂອງ Token ທຳອິດ', firstTokenLatencyHelper: 'ເວລາຕັ້ງແຕ່ສົ່ງຄຳຂໍຈົນເຖິງການໄດ້ຮັບ token ທຳອິດ. ຍິ່ງຕ່ຳຍິ່ງຕອບສະໜອງໄວ.', @@ -1375,7 +1365,7 @@ const message = { requestRateCustom: 'ກຳນົດ QPS ເອງ', requestRateCustomPlaceholder: 'ຄຳຂໍຕໍ່ວິນາທີ, ເຊັ່ນ: 2.5', successfulRequests: 'ຄຳຂໍທີ່ສຳເລັດ', - requestThroughput: 'Request Throughput', + requestThroughput: 'ອັດຕາຄຳຮ້ອງຂໍ', mean: 'ຄ່າສະເລ່ຍ', median: 'ຄ່າມັດທະຍະຖານ', timeout: 'ໝົດເວລາ (ວິນາທີ)', @@ -1389,11 +1379,11 @@ const message = { process: 'ຂໍ້ມູນໂປຣເຊສ', processCount: 'ຈຳນວນໂປຣເຊສ', type: 'ປະເພດ', - typeG: 'Graphics', - typeC: 'Compute', - typeCG: 'Compute+Graphics', + typeG: 'ກຣາຟິກ', + typeC: 'ການຄຳນວນ', + typeCG: 'ການຄຳນວນ + ກຣາຟິກ', processName: 'ຊື່ໂປຣເຊສ', - shr: 'Shared Memory', + shr: 'ໜ່ວຍຄວາມຈຳຮ່ວມ', temperatureHelper: 'ອຸນຫະພູມ GPU ທີ່ສູງເກີນໄປອາດເຮັດໃຫ້ປະສິດທິພາບຫຼຸດລົງ', gpuUtil: 'ການໃຊ້ງານ GPU', temperature: 'ອຸນຫະພູມ', @@ -1413,24 +1403,24 @@ const message = { cudaVersion: 'ເວີຊັນ CUDA', processMemoryUsage: 'ການໃຊ້ໜ່ວຍຄວາມຈຳ', performanceStateHelper: 'ຈາກ P0 (ປະສິດທິພາບສູງສຸດ) ເຖິງ P12 (ຕ່ຳສຸດ)', - busID: 'Bus Address', - persistenceMode: 'Persistence Mode', + busID: 'ທີ່ຢູ່ Bus', + persistenceMode: 'ໂໝດຄົງສະພາບ', enabled: 'ເປີດໃຊ້ງານ', disabled: 'ປິດໃຊ້ງານ', - persistenceModeHelper: 'Persistence mode ຊ່ວຍໃຫ້ຕອບສະໜອງງານໄດ້ໄວຂຶ້ນ ແຕ່ຈະກິນໄຟໃນໂໝດ Standby ຫຼາຍຂຶ້ນ', - displayActive: 'GPU Initialization', + persistenceModeHelper: 'ໂໝດຄົງສະພາບຊ່ວຍໃຫ້ຕອບສະໜອງວຽກໄດ້ໄວຂຶ້ນ ແຕ່ຈະໃຊ້ໄຟໃນໂໝດສະແຕນບາຍຫຼາຍຂຶ້ນ', + displayActive: 'ການເລີ່ມຕົ້ນ GPU', displayActiveT: 'ແມ່ນ', displayActiveF: 'ບໍ່', ecc: 'ເຕັກໂນໂລຊີ ECC', computeMode: 'ໂໝດການຄຳນວນ', default: 'ເລີ່ມຕົ້ນ', - exclusiveProcess: 'Exclusive Process', - exclusiveThread: 'Exclusive Thread', + exclusiveProcess: 'ໂປຣເຊສສະເພາະ', + exclusiveThread: 'ເທຣດສະເພາະ', prohibited: 'ຖືກຫ້າມ', - defaultHelper: 'Default: ໂປຣເຊສສາມາດລັນພ້ອມກັນໄດ້', - exclusiveProcessHelper: 'Exclusive Process: ມີພຽງ context ດຽວທີ່ໃຊ້ GPU ໄດ້ ແຕ່ແບ່ງປັນໃຫ້ຫຼາຍ thread ໄດ້', - exclusiveThreadHelper: 'Exclusive Thread: ມີພຽງ thread ດຽວໃນ context ທີ່ໃຊ້ GPU ໄດ້', - prohibitedHelper: 'Prohibited: ບໍ່ອະນຸຍາດໃຫ້ລັນໂປຣເຊສພ້ອມກັນ', + defaultHelper: 'ຄ່າເລີ່ມຕົ້ນ: ໂປຣເຊສສາມາດລັນພ້ອມກັນໄດ້', + exclusiveProcessHelper: 'ໂປຣເຊສສະເພາະ: ມີພຽງ context ດຽວທີ່ໃຊ້ GPU ໄດ້ ແຕ່ແບ່ງປັນໃຫ້ຫຼາຍ thread ໄດ້', + exclusiveThreadHelper: 'ເທຣດສະເພາະ: ມີພຽງ thread ດຽວໃນ context ທີ່ໃຊ້ GPU ໄດ້', + prohibitedHelper: 'ຫ້າມ: ບໍ່ອະນຸຍາດໃຫ້ລັນໂປຣເຊສພ້ອມກັນ', migModeHelper: 'ໃຊ້ສຳລັບສ້າງ MIG instances ເພື່ອແຍກສ່ວນ GPU ທາງກາຍະພາບ.', migModeNA: 'ບໍ່ຮອງຮັບ', current: 'ຕິດຕາມແບບ Real-time', @@ -1645,7 +1635,7 @@ const message = { imagePush: 'ສົ່ງ Image (Push)', imagePushHelper: 'ກວດພົບວ່າ Image ນີ້ມີຫຼາຍແທັກ. ກະລຸນາຢືນຢັນຊື່ Image ທີ່ຈະສົ່ງ: {0}', imageDelete: 'ລຶບ Image', - repoName: 'Container registry', + repoName: 'Registry ຂອງ Container', imageName: 'ຊື່ Image', pull: 'ດຶງຂໍ້ມູນ (Pull)', path: 'ເສັ້ນທາງ', @@ -1730,9 +1720,9 @@ const message = { dockerStatus: 'ບໍລິການ Docker', daemonJsonPathHelper: 'ຢືນຢັນວ່າເສັ້ນທາງກຳນົດຄ່າກົງກັບທີ່ລະບຸໃນ docker.service.', mirrors: 'Registry mirrors', - mirrorsHelper: '', + mirrorsHelper: 'ໃຊ້ URL ຂອງ registry mirror ກ່ອນສຳລັບການດຳເນີນງານ image. ປ່ອຍຫວ່າງເພື່ອປິດ registry mirror.', mirrorsHelper2: 'ສຳລັບລາຍລະອຽດ, ເບິ່ງເອກະສານທາງການ.', - registries: 'Insecure registries', + registries: 'Registry ທີ່ບໍ່ປອດໄພ', ipv6Helper: 'ເມື່ອເປີດໃຊ້ IPv6, ທ່ານຕ້ອງເພີ່ມ IPv6 network ໃຫ້ຄອນເທນເນີ. ອີງຕາມເອກະສານທາງການສຳລັບຂັ້ນຕອນການຕັ້ງຄ່າ.', ipv6CidrHelper: 'ຊ່ວງ IPv6 address pool ສຳລັບຄອນເທນເນີ', @@ -3668,9 +3658,9 @@ const message = { staticChangePHPHelper: 'ປະຈຸບັນເປັນເວັບໄຊ Static, ທ່ານສາມາດປ່ຽນເປັນເວັບໄຊ PHP ໄດ້', proxyCache: 'ແຄຊ Reverse Proxy', cacheLimit: 'ຂີດຈຳກັດພື້ນທີ່ແຄຊ', - shareCahe: 'ຂະໜາດໜ່ວຍຄວາມຈຳຂອງຈຳນວນແຄຊ', + shareCache: 'ຂະໜາດໜ່ວຍຄວາມຈຳຂອງຈຳນວນແຄຊ', cacheExpire: 'ເວລາໝົດອາຍຸຂອງແຄຊ', - shareCaheHelper: 'ສາມາດເກັບວັດຖຸແຄຊໄດ້ປະມານ 8000 ອັນຕໍ່ 1MB ຂອງໜ່ວຍຄວາມຈຳ', + shareCacheHelper: 'ສາມາດເກັບວັດຖຸແຄຊໄດ້ປະມານ 8000 ອັນຕໍ່ 1MB ຂອງໜ່ວຍຄວາມຈຳ', cacheLimitHelper: 'ແຄຊເກົ່າຈະຖືກລຶບໂດຍອັດຕະໂນມັດເມື່ອພື້ນທີ່ເກີນກຳນົດ', cacheExpireJHelper: 'ແຄຊຈະຖືກລຶບຖ້າບໍ່ມີການເຂົ້າເຖິງຫຼັງຈາກເວລາໝົດອາຍຸ', realIP: 'IP ທີ່ແທ້ຈິງ', @@ -4004,6 +3994,7 @@ const message = { }, runtime: { runtime: 'ຣັນທາມ (Runtime)', + default: 'ຄ່າເລີ່ມຕົ້ນ', workDir: 'ໂຟນເດີທີ່ເຮັດວຽກ', localHelper: 'ສຳລັບບັນຫາການຕິດຕັ້ງໃນເຄື່ອງ ຫຼື ການໃຊ້ງານແບບອອຟລາຍ, ເບິ່ງ ', versionHelper: 'ເວີຊັນ PHP ຕົວຢ່າງ: v8.0', @@ -4792,6 +4783,14 @@ const message = { authManage: 'ການຢືນຢັນ', auth: { providerNavigation: 'ຜູ້ໃຫ້ບໍລິການຢັ້ງຢືນ', + defaultNode: 'ໂນດເລີ່ມຕົ້ນ', + defaultNodePlaceholder: 'ເລືອກໂນດ', + defaultNodeHelper: 'ໃຊ້ສຳລັບຜູ້ໃຊ້ໃໝ່ເທົ່ານັ້ນ.', + defaultNodeRequired: 'ເລືອກໂນດເລີ່ມຕົ້ນທີ່ຖືກຕ້ອງ.', + nodesLoadFailed: 'ໂຫຼດໂນດບໍ່ສຳເລັດ. ລອງໃໝ່ກ່ອນເລືອກໂນດເລີ່ມຕົ້ນ.', + nodeHandling: 'ການຈັດການໂນດ', + assignDefaultNode: 'ກຳນົດໂນດເລີ່ມຕົ້ນ: {node}', + keepExistingNode: 'ຮັກສາສິດໂນດເດີມ', providers: { ldap: 'AD/LDAP', passkey: 'Passkey', @@ -4819,7 +4818,388 @@ const message = { planned: 'ວາງແຜນ', plannedTitle: 'ການຕັ້ງຄ່າການພິສູດຢືນຢັນ {0}', plannedDesc: 'ຜູ້ໃຫ້ບໍລິການການພິສູດຢືນຢັນນີ້ຖືກວາງແຜນໄວ້ ແລະຍັງບໍ່ສາມາດໃຊ້ໄດ້ເທື່ອ.', + oidc: { + accessMode: 'ໂໝດການເຊື່ອມຕໍ່', + accessModeDesc: 'ໃຊ້ມາດຕະຖານ Discovery ທຸກຄັ້ງທີ່ຜູ້ໃຫ້ບໍລິການຕົວຕົນສະຫນັບສະຫນູນມັນ.', + actionCreate: 'ສ້າງຜູ້ໃຊ້', + actionKeepName: 'ຮັກສາຊື່ຜູ້ໃຊ້ປັດຈຸບັນ', + actionPending: 'ລໍຖ້າຜົນໄດ້ຮັບ', + actionReject: 'ປະຕິເສດການເຂົ້າສູ່ລະບົບ', + actionUpdate: 'ອັບເດດຂໍ້ມູນຕົວຕົນ', + advanced: 'ການຕັ້ງຄ່າຂັ້ນສູງ', + advancedDesc: 'ຮັກສາຄ່າເລີ່ມຕົ້ນທີ່ປອດໄພເວັ້ນເສຍແຕ່ວ່າຜູ້ໃຫ້ບໍລິການຕ້ອງການທາງເລືອກທີ່ເຂົ້າກັນໄດ້.', + assignDefaultRole: 'ກຳນົດບົດບາດເລີ່ມຕົ້ນ: {role}', + authorizationEndpoint: 'Authorization Endpoint', + authorizationEndpointInvalid: 'ໃສ່ Authorization Endpoint ທີ່ຖືກຕ້ອງ.', + authorizationFlow: 'ກະແສການອະນຸຍາດ', + automatic: 'ອັດຕະໂນມັດ', + automaticPolicy: 'ນະໂຍບາຍການຈັດການອັດຕະໂນມັດ', + automaticPolicyDesc: 'ກົດລະບຽບເຫຼົ່ານີ້ຖືກບັງຄັບໃຊ້ໂດຍ backend ແລະບໍ່ແມ່ນສະຫຼັບຜູ້ບໍລິຫານ.', + basic: 'ການຕັ້ງຄ່າພື້ນຖານ', + basicDesc: 'ເລືອກຮູບແບບຜູ້ໃຫ້ບໍລິການ, ຈາກນັ້ນກຳນົດຄ່າລູກຄ້າ ແລະໂທກັບ.', + browserTest: 'ທົດສອບເຂົ້າລະບົບຜ່ານບຣາວເຊີ', + browserTestConflict: 'ຢັ້ງຢືນຕົວຕົນແລ້ວ ແຕ່ຊື່ຜູ້ໃຊ້ຂັດກັນ', + browserTestConflictHelper: + 'ຊື່ຜູ້ໃຊ້ທີ່ຈັບຄູ່ໄວ້ເປັນຂອງຕົວຕົນອື່ນ ແລະ ຈະບໍ່ຖືກເຊື່ອມຕໍ່ອັດຕະໂນມັດ.', + browserTestExpired: 'ການທົດສອບໂປຣແກຣມທ່ອງເວັບໝົດອາຍຸແລ້ວ', + browserTestExpiredHelper: 'ເລີ່ມການທົດສອບຕົວທ່ອງເວັບໃຫມ່ແລະສໍາເລັດການອະນຸຍາດກ່ອນທີ່ມັນຈະຫມົດອາຍຸ.', + browserTestFailed: 'ການທົດສອບຕົວທ່ອງເວັບລົ້ມເຫລວ', + browserTestFailedHelper: + 'ບໍ່ສາມາດສະແດງຕົວຢ່າງຂໍ້ມູນຕົວຕົນໄດ້. ກວດສອບຂໍ້ຜິດພາດທີ່ backend ສົ່ງກັບມາໃນພາສາປະຈຸບັນ.', + browserTestIsolation: + 'ດຳເນີນການອະນຸຍາດແບບໄປ-ກັບຈິງ ແຕ່ຈະບໍ່ສ້າງ ຫຼື ອັບເດດຜູ້ໃຊ້, ມອບໝາຍບົດບາດ ຫຼື ສ້າງເຊດຊັນເຂົ້າລະບົບຈິງ.', + browserTestPopupBlocked: + 'ອະນຸຍາດໃຫ້ປັອບອັບສໍາລັບເວັບໄຊທ໌ນີ້, ຈາກນັ້ນເລີ່ມການທົດສອບຕົວທ່ອງເວັບອີກຄັ້ງ.', + browserTestPopupClosed: 'ປ່ອງຢ້ຽມການອະນຸຍາດຖືກປິດກ່ອນການທົດສອບສໍາເລັດ.', + browserTestSuccess: 'ຢັ້ງຢືນຜູ້ໃຫ້ບໍລິການສຳເລັດແລ້ວ', + browserTestSuccessHelper: 'ແຜນທີ່ການລະບຸຕົວຕົນໄດ້ຖືກສະແດງຕົວຢ່າງໂດຍບໍ່ມີການປ່ຽນຜູ້ໃຊ້ ຫຼືເຊດຊັນ.', + browserTestTitle: 'OIDC ທົດສອບການເຂົ້າສູ່ລະບົບຂອງຕົວທ່ອງເວັບ', + browserTestWaiting: 'ກຳລັງລໍຖ້າການອະນຸຍາດຈາກຜູ້ໃຫ້ບໍລິການ', + browserTestWaitingHelper: + 'ສຳເລັດການເຂົ້າສູ່ລະບົບໃນໜ້າຈໍໂປຣແກຣມທ່ອງເວັບໃໝ່. ໜ້ານີ້ຈະອັບເດດໂດຍອັດຕະໂນມັດ.', + callbackCopied: 'ສຳເນົາ OIDC ໂທກັບ URL ແລ້ວ.', + callbackURL: 'ໂທກັບ URL', + callbackURLHelper: 'ເພີ່ມທີ່ຢູ່ນີ້ໃສ່ລາຍການທີ່ຢູ່ຮຽກກັບທີ່ອະນຸຍາດຂອງໄຄລເອັນໃນຜູ້ໃຫ້ບໍລິການຕົວຕົນ.', + cancelClearSecret: 'ຍົກເລີກການລຶບລ້າງ', + clearSecret: 'ລ້າງ Client Secret', + clearSecretConfirm: 'Client Secret ຈະຖືກລຶບອອກຫຼັງຈາກທີ່ທ່ານບັນທຶກເທົ່ານັ້ນ. ສືບຕໍ່?', + clientAuthMethod: 'ວິທີການກວດສອບລູກຄ້າ', + clientAuthMethodHelper: 'ເລືອກວິທີຢືນຢັນຕົວຕົນທີ່ກຳນົດໄວ້ສຳລັບໄຄລເອັນນີ້ໃນຜູ້ໃຫ້ບໍລິການຕົວຕົນ.', + clientAuthMethodRequired: 'ເລືອກວິທີການກວດສອບລູກຄ້າ.', + clientID: 'Client ID', + clientIDRequired: 'ໃສ່ Client ID.', + clientSecret: 'Client Secret', + clockSkew: 'ຄ່າຍອມຮັບຄວາມຄາດເຄື່ອນເວລາຂອງໂທເຄັນ', + clockSkewHelper: + 'ອະນຸຍາດໃຫ້ເວລາຂອງຜູ້ໃຫ້ບໍລິການຕົວຕົນ ແລະ 1Panel ແຕກຕ່າງກັນເລັກນ້ອຍ. ແນະນຳໃຫ້ຄົງຄ່າເລີ່ມຕົ້ນ 60 ວິນາທີ.', + clockSkewRequired: 'ໃສ່ຄ່າຍອມຮັບຄວາມຄາດເຄື່ອນເວລາຂອງໂທເຄັນ.', + compatibilityMode: 'ໂໝດຄວາມເຂົ້າກັນໄດ້', + compatibilityModeHelper: + 'ໃຊ້ພຽງແຕ່ສໍາລັບ Discovery ທີ່ບໍ່ຄົບຖ້ວນຫຼືຈຸດສິ້ນສຸດທີ່ຂຽນໃຫມ່. ການກວດສອບ Core OIDC ຍັງຄົງເປີດໃຊ້ຢູ່.', + configurationFailedHelper: + 'ການທົດສອບລົ້ມເຫຼວ. ໜ້ານີ້ສະແດງສະເພາະຂໍ້ຜິດພາດທີ່ backend ສົ່ງກັບມາໃນພາສາປະຈຸບັນ.', + configurationFailedTag: 'ການທົດສອບລົ້ມເຫລວ', + configurationHighRiskPassed: 'ການຕັ້ງຄ່າຜ່ານໄປ, ແຕ່ມີທາງເລືອກທີ່ເຂົ້າກັນໄດ້ທີ່ມີຄວາມສ່ຽງສູງ.', + configurationHighRiskTag: 'ຜ່ານການຕັ້ງຄ່າຄວາມສ່ຽງສູງ', + configurationNotTested: 'ການຕັ້ງຄ່າປັດຈຸບັນຍັງບໍ່ໄດ້ຖືກທົດສອບ.', + configurationNotTestedTag: 'ບໍ່ໄດ້ທົດສອບ', + configurationPassed: 'ການຕັ້ງຄ່າປັດຈຸບັນຜ່ານການກວດສອບຄວາມປອດໄພ ແລະຄວາມສາມາດ.', + configurationPassedTag: 'ການທົດສອບຜ່ານ', + configurationStaleHelper: 'ການຕັ້ງຄ່າຖືກປ່ຽນແປງແລ້ວ. ກະລຸນາທົດສອບອີກຄັ້ງກ່ອນບັນທຶກ.', + configurationStaleTag: 'ຜົນໄດ້ຮັບໝົດອາຍຸ', + configurationTestMeta: + 'ທົດສອບຢູ່ {time}; ສໍາເລັດໃນ {duration} ms. ການຕອບ Provider ດິບບໍ່ໄດ້ຖືກເກັບຮັກສາໄວ້.', + configurationTestResult: 'ຜົນ​ການ​ທົດ​ສອບ​ການ​ຕັ້ງ​ຄ່າ​', + configurationTestResultDesc: + 'ນີ້ກວດເບິ່ງ Discovery ແລະຄວາມສາມາດເທົ່ານັ້ນ; ມັນບໍ່ແລກປ່ຽນລະຫັດການອະນຸຍາດ ຫຼືພິສູດ Client Secret. ໃຊ້ການເຂົ້າສູ່ລະບົບການທົດສອບຂອງຕົວທ່ອງເວັບສໍາລັບການຢັ້ງຢືນໃນຕອນທ້າຍ.', + configurationTestSuccess: 'ການທົດສອບການຕັ້ງຄ່າ OIDC ສຳເລັດແລ້ວ.', + configurationTesting: 'ກຳລັງທົດສອບການຕັ້ງຄ່າ OIDC ໃນປັດຈຸບັນ...', + configurationTestingTag: 'ການທົດສອບ', + configureSecret: 'ຕັ້ງຄ່າລັບ', + conflictExistingRename: 'subject ທີ່ຜູກໄວ້ສົ່ງຄືນຊື່ຜູ້ໃຊ້ໃໝ່ທີ່ຖືກໃຊ້ແລ້ວ', + conflictExistingRenameResult: + 'ຮັກສາ User.Name ທີ່ມີຢູ່ແລ້ວແລະອະນຸຍາດໃຫ້ຜູ້ໃຊ້ທີ່ຖືກຜູກມັດເຂົ້າສູ່ລະບົບ', + conflictLDAP: 'ຜູ້ໃຊ້ LDAP', + conflictLocal: 'ຜູ້ໃຊ້ທ້ອງຖິ່ນ', + conflictNewAvailable: 'subject ໃໝ່ ແລະ ຊື່ຜູ້ໃຊ້ທີ່ຈັບຄູ່ໄວ້ສາມາດໃຊ້ໄດ້', + conflictNewAvailableResult: 'ສ້າງຜູ້ໃຊ້ວິສາຫະກິດແລະມອບຫມາຍບົດບາດເລີ່ມຕົ້ນ', + conflictNone: 'ບໍ່ມີຂໍ້ຂັດແຍ່ງ', + conflictOIDC: 'ຕົວຕົນ OIDC ອື່ນ', + conflictOccupied: 'ຊື່ຜູ້ໃຊ້ທີ່ຈັບຄູ່ໄວ້ເປັນຂອງຜູ້ໃຊ້ທ້ອງຖິ່ນ, LDAP ຫຼື ຕົວຕົນ OIDC ອື່ນ.', + conflictOccupiedResult: 'ປະຕິເສດຕົວຕົນໃຫມ່; ບໍ່ເຄີຍຜູກມັດ ຫຼືລວມອັດຕະໂນມັດ', + conflictType: 'ປະເພດການຂັດແຍ້ງ', + connectionSecurity: 'ຄວາມ​ປອດ​ໄພ​ການ​ເຊື່ອມ​ຕໍ່​', + connectionSecurityDesc: 'ນະໂຍບາຍ TLS ນຳໃຊ້ກັບຄຳຮ້ອງຂໍ Discovery, Token, JWKS, ແລະ UserInfo.', + connectionTest: 'ການ​ເຊື່ອມ​ຕໍ່​ແລະ​ການ​ທົດ​ສອບ​ການ​ຕັ້ງ​ຄ່າ​', + connectionTestCompatibilityDesc: 'ກວດສອບຈຸດສິ້ນສຸດແບບກຳນົດເອງ ແລະນະໂຍບາຍຄວາມປອດໄພຂອງໂປຣໂຕຄໍ.', + connectionTestStandardDesc: 'ຈຸດສິ້ນສຸດ ແລະຄວາມສາມາດຖືກຄົ້ນພົບໂດຍອັດຕະໂນມັດຈາກ Issuer.', + connectionTestTab: 'ທົດສອບການເຊື່ອມຕໍ່', + customCA: 'CA ແບບກຳນົດເອງ', + customCAHelper: 'ນຳໃຊ້ກັບແຫຼ່ງການພິສູດຢືນຢັນນີ້ເທົ່ານັ້ນ ແລະບໍ່ເຄີຍຂຽນໃສ່ບັນທຶກ.', + customCARequired: 'ສະໜອງໃບຢັ້ງຢືນ CA ແບບກຳນົດເອງ.', + defaultRole: 'ບົດບາດເລີ່ມຕົ້ນ', + defaultRoleHelper: 'ມອບໃຫ້ສະເພາະເມື່ອສ້າງຜູ້ໃຊ້ຄັ້ງທຳອິດ; ການເຂົ້າລະບົບຄັ້ງຕໍ່ໄປຈະບໍ່ປ່ຽນບົດບາດ.', + defaultRolePlaceholder: 'ເລືອກບົດບາດ', + defaultRoleRequired: 'ເລືອກບົດບາດເລີ່ມຕົ້ນທີ່ຖືກຕ້ອງ.', + disableAfterSave: 'OIDC ຈະຖືກປິດໃຊ້ງານຫຼັງຈາກບັນທຶກ.', + disableConfirm: 'ການປິດໃຊ້ງານ OIDC ທັນທີເຮັດໃຫ້ການເຂົ້າເຖິງຜູ້ໃຊ້ຂອງແຫຼ່ງນີ້ບໍ່ຖືກຕ້ອງ. ສືບຕໍ່?', + disableDiscardConfirm: + 'ການປິດການນຳໃຊ້ OIDC ເປັນການກະທຳສຸກເສີນ: ມັນພຽງແຕ່ປິດການເຂົ້າລະບົບ ແລະເຮັດໃຫ້ການເຂົ້າເຖິງບໍ່ຖືກຕ້ອງສຳລັບຜູ້ໃຊ້ແຫຼ່ງທີ່ມານີ້ໃນທັນທີ. ການປ່ຽນແປງອື່ນໆທີ່ຍັງບໍ່ໄດ້ບັນທຶກໄວ້ໃນໜ້ານີ້, ລວມທັງການປ່ຽນແປງ Client Secret, ຈະຖືກຍົກເລີກ. ສືບຕໍ່?', + disableTitle: 'ປິດໃຊ້ງານ OIDC', + disabled: 'ປິດໃຊ້', + discoveryAllowlist: 'ບັນຊີອະນຸຍາດຄວາມປອດໄພສຳລັບ Discovery', + enable: 'ເປີດໃຊ້', + enableAfterSave: 'OIDC ຈະຖືກເປີດໃຊ້ຫຼັງຈາກບັນທຶກສຳເລັດ.', + enabled: 'ເປີດໃຊ້ແລ້ວ', + endSessionEndpoint: 'End Session Endpoint', + endSessionEndpointHelper: + 'ບັນທຶກສໍາລັບການນໍາໃຊ້ໃນອະນາຄົດ; ການອອກຈາກລະບົບທີ່ລິເລີ່ມ Provider ບໍ່ໄດ້ລວມຢູ່ໃນລຸ້ນນີ້.', + endSessionEndpointInvalid: 'ໃສ່ End Session Endpoint ທີ່ຖືກຕ້ອງ.', + endpointDiscoveryPlaceholder: 'ສະແດງຫຼັງຈາກທົດສອບການເຊື່ອມຕໍ່', + firstLogin: 'ເຂົ້າ​ສູ່​ລະ​ບົບ​ຄັ້ງ​ທໍາ​ອິດ​', + firstLoginPolicy: 'ສ້າງຜູ້ໃຊ້ວິສາຫະກິດໃນທ້ອງຖິ່ນແລະມອບຫມາຍບົດບາດເລີ່ມຕົ້ນທີ່ໄດ້ກໍານົດໄວ້.', + fixedAuthorizationCode: 'Authorization Code Flow', + fixedNoTokenPersistence: 'Tokens, Claims, ແລະ verifier ບໍ່ເຄີຍຄົງຢູ່', + fixedSecurityPolicy: 'ບັງຄັບໃຊ້ສະເໝີ; ບໍ່​ມີ​ການ​ຕັ້ງ​ຄ່າ​ທີ່​ຕ້ອງ​ການ​', + fixedStateNonce: 'state ແລະ nonce ຄັ້ງດຽວ', + fixedTokenValidation: 'ລາຍເຊັນ ID Token ແລະການກວດສອບຄວາມຖືກຕ້ອງຂອງ Claims', + highRiskSaveConfirm: + 'ການຕັ້ງຄ່າທີ່ເປີດໃຊ້ງານນີ້ມີທາງເລືອກຄວາມເຂົ້າກັນໄດ້ທີ່ມີຄວາມສ່ຽງສູງ. ຢືນຢັນວ່າສະພາບແວດລ້ອມທີ່ໂດດດ່ຽວຮຽກຮ້ອງໃຫ້ມີພວກມັນ.', + highRiskTitle: 'ການຕັ້ງຄ່າ OIDC ມີຄວາມສ່ຽງສູງ', + hs256Compatibility: 'HS256 (ເຂົ້າກັນໄດ້)', + hs256KeyHelper: 'HS256 ໃຊ້ Client Secret ຂອງແຫຼ່ງນີ້ສະເໝີ ແລະ ບໍ່ຍອມຮັບລະຫັດການເຊັນແຍກຕ່າງຫາກ.', + hs256Warning: + 'HS256 ໃຊ້ຄວາມລັບ symmetric ຮ່ວມກັນສໍາລັບລາຍເຊັນ ID Token. ໃຊ້ມັນພຽງແຕ່ເມື່ອ Provider ບໍ່ສາມາດໃຊ້ສູດການຄິດໄລ່ທີ່ບໍ່ສົມມາດ.', + identityBindingPolicy: + 'ການລະບຸຕົວຕົນຖືກແກ້ໄຂເປັນ AuthSourceID + issuer + subject. ຜູ້ໃຊ້ທີ່ກົງກັນ name ບໍ່ເຄີຍອ້າງສິດບັນຊີອື່ນ.', + identityMissing: 'ຕົວຕົນບໍ່ມີຜົນ', + issuer: 'Issuer URL', + issuerHelper: 'ID Token iss ຄ່າ ແລະ Discovery issuer ຕ້ອງກົງກັບຄ່ານີ້ແນ່ນອນ.', + issuerInvalid: 'ປ້ອນ HTTP ຫຼື HTTPS Issuer URL ທີ່ຖືກຕ້ອງໂດຍບໍ່ມີການສອບຖາມ ຫຼື fragment.', + issuerRequired: 'ໃສ່ Issuer URL.', + jwksRotation: 'ການຫມຸນ JWKS ອັດຕະໂນມັດ', + jwksURI: 'JWKS URI', + jwksURIHelper: 'ຕ້ອງການສໍາລັບການເຊັນຊື່ທີ່ບໍ່ສົມມາດວັດແທກເມື່ອແຫຼ່ງທີ່ສໍາຄັນແມ່ນ JWKS.', + jwksURIInvalid: 'ໃສ່ JWKS URI ທີ່ຖືກຕ້ອງສໍາລັບແຫຼ່ງລະຫັດການລົງນາມທີ່ເລືອກ.', + keepExistingRole: 'ຮັກສາບົດບາດທີ່ມີຢູ່ແລ້ວແລະການອະນຸຍາດທ້ອງຖິ່ນ', + localSecurityData: 'ຂໍ້ມູນຄວາມປອດໄພໃນທ້ອງຖິ່ນ', + localSecurityDataPolicy: 'ຢ່າຂຽນທັບບົດບາດ, MFA, API Keys, Passkeys, ຫຼືການອະນຸຍາດທ້ອງຖິ່ນ.', + localCredentialsManaged: + 'ຊື່ຜູ້ໃຊ້ ແລະ ລະຫັດຜ່ານທ້ອງຖິ່ນຖືກຈັດການໂດຍ OIDC ແລະ ບໍ່ສາມາດແກ້ໄຂຢູ່ບ່ອນນີ້. ບົດບາດ, ສິດອະນຸຍາດ, MFA, API Keys ແລະ Passkeys ຍັງຄົງເປັນຂໍ້ມູນທ້ອງຖິ່ນ.', + localUserFields: 'ຊ່ອງຂໍ້ມູນຜູ້ໃຊ້ໃນທ້ອງຖິ່ນ', + localUserFieldsDesc: 'ການປ່ອຍຕົວທໍາອິດເຮັດແຜນທີ່ພຽງແຕ່ User.Name ແລະບໍ່ໃຊ້ການສະແດງແຜນທີ່ JSON.', + loginWith: 'ເຂົ້າລະບົບດ້ວຍ {provider}', + manualEndpoints: 'ຈຸດສິ້ນສຸດແບບກຳນົດເອງ', + manualEndpointsDesc: 'ໃຊ້ພຽງແຕ່ເມື່ອ Discovery ບໍ່ສົມບູນ ຫຼືປະຕູທາງເທິງຂຽນຈຸດສິ້ນສຸດຄືນໃໝ່.', + mappingResult: 'ຜົນແຜນທີ່', + mode: 'ໂໝດການເຊື່ອມຕໍ່', + modeRequired: 'ເລືອກຮູບແບບການເຊື່ອມຕໍ່.', + nameClaim: 'Claim ຊື່ຜູ້ໃຊ້', + nameClaimHelper: 'ໃສ່ຊ່ອງຂໍ້ມູນທີ່ມີຊື່ຜູ້ໃຊ້ ເຊັ່ນ preferred_username.', + nameClaimRequired: 'ປ້ອນ Claim ຊື່ຜູ້ໃຊ້.', + nameConflict: 'ນະໂຍບາຍການຂັດແຍ້ງກ່ຽວກັບຊື່', + panelURL: '1Panel ສາທາລະນະ URL', + panelURLHTTPWarning: + 'HTTP ບໍ່ປົກປ້ອງການຕອບຮັບການອະນຸຍາດ. ໃຊ້ມັນຢູ່ໃນສະພາບແວດລ້ອມສ່ວນຕົວທີ່ໂດດດ່ຽວທີ່ຍອມຮັບໂດຍ Provider.', + panelURLHelper: 'ໃສ່ທີ່ຢູ່ທີ່ຜູ້ໃຊ້ໃຊ້ເຂົ້າເຖິງ 1Panel. ລະບົບໃຊ້ທີ່ຢູ່ນີ້ເພື່ອສ້າງທີ່ຢູ່ຮຽກກັບ.', + panelURLInvalid: 'ປ້ອນຕົ້ນກຳເນີດທີ່ປະກອບມີພຽງແຕ່ໂຄງການ, ໂຮສ, ແລະພອດທາງເລືອກ.', + panelURLRequired: 'ປ້ອນ 1Panel ສາທາລະນະ URL.', + pkceDisabled: 'ປິດໃຊ້ງານ (ຄວາມເຂົ້າກັນໄດ້ເທົ່ານັ້ນ)', + pkceDisabledWarning: 'ການປິດໃຊ້ງານ PKCE ຫຼຸດຜ່ອນການປ້ອງກັນການຂັດຂວາງລະຫັດການອະນຸຍາດ.', + pkceHelper: 'ຕ້ອງການ S256. ວິທີການທ້າທາຍ plain ແມ່ນບໍ່ເຄີຍສະເຫນີ.', + pkceS256: 'S256 (ແນະນໍາ)', + plannedHandling: 'ການຈັດການແຜນການ', + privateNetworkIdP: 'IDP ເຄືອຂ່າຍສ່ວນຕົວ', + privateNetworkIdPHelper: + 'ອະນຸຍາດໃຫ້ທີ່ຢູ່ສ່ວນຕົວຢ່າງຊັດເຈນ; metadata, loopback, link-local, redirects, ແລະການ rebinding DNS ຍັງຄົງຖືກບລັອກ.', + privateNetworkWarning: + 'ການ​ເຂົ້າ​ເຖິງ​ເຄືອ​ຂ່າຍ​ສ່ວນ​ຕົວ​ແມ່ນ​ເປີດ​ໃຊ້​ງານ​ສໍາ​ລັບ​ແຫຼ່ງ​ການ​ກວດ​ສອບ​ນີ້​.', + protocolCompatibility: 'ຄວາມເຂົ້າກັນໄດ້ຂອງພິທີການ', + protocolCompatibilityDesc: 'ການກວດສອບລາຍເຊັນ ID Token ບໍ່ສາມາດປິດການໃຊ້ງານໄດ້.', + providerAndClient: 'ຜູ້ໃຫ້ບໍລິການ ແລະ Client', + providerAndClientDesc: 'Client Secret ພຽງແຕ່ສາມາດຖືກແທນທີ່ຫຼືລ້າງແລະບໍ່ເຄີຍຖືກສົ່ງຄືນໂດຍຫນ້າ.', + providerCapabilities: 'ຄວາມສາມາດຂອງຜູ້ໃຫ້ບໍລິການ', + recentTestSuccess: 'ການທົດສອບຄັ້ງສຸດທ້າຍປະສົບຜົນສໍາເລັດ: {0}', + recommended: 'ແນະນຳ', + rejectPlain: 'plain ປະຕິເສດ', + replaceSecret: 'ທົດແທນຄວາມລັບ', + requestAndClaims: 'ການຮ້ອງຂໍແລະຄຸນລັກສະນະ', + requestAndClaimsDesc: 'ກຳນົດຂອບເຂດການອະນຸຍາດ, ການເຕີມຂໍ້ມູນຜູ້ໃຊ້ ແລະພາລາມິເຕີຄຳຮ້ອງຂໍ.', + requestTimeout: 'ການຮ້ອງຂໍໝົດເວລາ', + requestTimeoutRequired: 'ປ້ອນການໝົດເວລາການຮ້ອງຂໍ.', + restore: 'ກູ້ຄືນ', + restored: 'ການຕັ້ງຄ່າ OIDC ທີ່ບັນທຶກໄວ້ຫຼ້າສຸດໄດ້ຖືກຟື້ນຟູຄືນມາ.', + result: 'ຜົນໄດ້ຮັບ', + rolesLoadFailed: 'ບໍ່ສາມາດໂຫຼດບົດບາດໄດ້. ລອງອີກຄັ້ງກ່ອນທີ່ຈະເລືອກບົດບາດເລີ່ມຕົ້ນ.', + roleHandling: 'ການຈັດການພາລະບົດບາດ', + scenario: 'ສະຖານະການ', + scopes: 'ຂອບເຂດການອະນຸຍາດ', + scopesHelper: 'ຕ້ອງມີ openid. ໃຊ້ຊ່ອງຫວ່າງແຍກຫຼາຍຂອບເຂດ.', + scopesRequired: 'Scopes ຕ້ອງມີ openid.', + seconds: 'ວິນາທີ', + secretClearHelper: 'ຫຼັງຈາກການລຶບລ້າງ, ຕ້ອງການ Client Secret ໃໝ່ ກ່ອນທີ່ຈະເປີດ OIDC ອີກຄັ້ງ.', + secretConfigured: 'ຕັ້ງຄ່າແລ້ວ', + secretNotConfigured: 'ບໍ່ໄດ້ຕັ້ງຄ່າ', + secretPlaceholder: 'ໃສ່ Client Secret ໃຫມ່', + secretReplaceHelper: + 'Client Secret ໃໝ່ຈະແທນຄ່າເກົ່າເມື່ອບັນທຶກ. ກະລຸນາອັບເດດ Client Secret ໃນ OIDC Provider ພ້ອມກັນ.', + secretRequiredHelper: 'ຕັ້ງຄ່າ Client Secret ກ່ອນທີ່ຈະເປີດໃຊ້ OIDC.', + secretRequiredToEnable: 'ຕັ້ງຄ່າ Client Secret ກ່ອນທີ່ຈະເປີດໃຊ້ OIDC.', + secretSavedHelper: 'ຈັດເກັບແບບເຂົ້າລະຫັດ. ປ່ອຍຫວ່າງເພື່ອຮັກສາ Client Secret ປັດຈຸບັນ.', + secretWaiting: 'ລໍຖ້າການປ້ອນຂໍ້ມູນ', + secretWillClear: 'ຈະຖືກລຶບລ້າງ', + secretWillReplace: 'ຈະຖືກປ່ຽນແທນ', + signingAlgorithm: 'ອັນກໍຣິທຶມການເຊັນ ID Token', + signingAlgorithmHelper: 'ເລືອກໄດ້ສະເພາະອັນກໍຣິທຶມທີ່ຢູ່ໃນລາຍຊື່ອະນຸຍາດດ້ານຄວາມປອດໄພຂອງ backend.', + signingKey: 'ກະແຈລາຍເຊັນ', + signingKeyClientSecret: 'Client Secret (HS256 ເທົ່ານັ້ນ)', + signingKeyJWKS: 'JWKS URI ພ້ອມການໝູນວຽນອັດຕະໂນມັດ', + signingKeySource: 'ແຫຼ່ງກະແຈລາຍເຊັນ', + signingKeySourceHelper: 'ແນະນຳໃຫ້ໃຊ້ JWKS. ກະແຈສາທາລະນະແບບຄົງທີ່ບໍ່ສາມາດໝູນວຽນອັດຕະໂນມັດໄດ້.', + signingKeyStatic: 'ກະແຈສາທາລະນະ JWK ຫຼື PEM ແບບຄົງທີ່', + standardDiscovery: 'ມາດຕະຖານ OIDC Discovery', + standardDiscoveryDesc: '1Panel ຄົ້ນພົບຈຸດສິ້ນສຸດ ແລະຄວາມສາມາດ ແລະບໍ່ໄດ້ເກັບຮັກສາເອກະສານດິບ.', + standardMode: 'ໂໝດມາດຕະຖານ', + standardModeHelper: 'ຄົ້ນພົບຈຸດສິ້ນສຸດ, ຄວາມສາມາດໃນການເຊັນ, ແລະການສະຫນັບສະຫນູນ PKCE ຈາກ Issuer.', + standardProtocolPolicy: 'ນະໂຍບາຍໂປໂຕຄອນມາດຕະຖານ', + standardProtocolPolicyDesc: + 'ຄວາມສາມາດໃນການເຊັນຖືກເຈລະຈາອັດຕະໂນມັດ; ບໍ່ຕ້ອງປ້ອນອັນກໍຣິທຶມ ຫຼື ກະແຈລາຍເຊັນຢູ່ບ່ອນນີ້.', + staticSigningKey: 'ກະແຈສາທາລະນະລາຍເຊັນແບບຄົງທີ່', + staticSigningKeyHelper: 'ຮັບສະເພາະຂໍ້ມູນກະແຈສາທາລະນະ. ຕ້ອງອັບເດດເອງເມື່ອ Provider ປ່ຽນກະແຈ.', + staticSigningKeyPlaceholder: 'ວາງກະແຈສາທາລະນະ JWK, JWKS JSON ຫຼື PEM', + staticSigningKeyRequired: 'ກະລຸນາລະບຸກະແຈສາທາລະນະລາຍເຊັນແບບຄົງທີ່.', + staticSigningKeyWarning: + 'ກະແຈລາຍເຊັນແບບຄົງທີ່ບໍ່ສາມາດໝູນວຽນອັດຕະໂນມັດໄດ້; ອັບເດດກ່ອນທີ່ Provider ຈະໝູນວຽນກະແຈ.', + settingLoadFailed: 'ການຕັ້ງຄ່າ OIDC ບໍ່ສາມາດໂຫຼດໄດ້', + settingLoadFailedHelper: + 'ແບບຟອມຖືກລັອກເພື່ອຫຼີກເວັ້ນການບັນທຶກການຕັ້ງຄ່າເລີ່ມຕົ້ນທີ່ຫວ່າງເປົ່າໃສ່ກັບການຕັ້ງຄ່າປັດຈຸບັນ. ລອງໃໝ່ຫຼັງຈາກການເຊື່ອມຕໍ່ຟື້ນຕົວ.', + subsequentLogin: 'ເຂົ້າສູ່ລະບົບຕໍ່ມາ', + subsequentLoginPolicy: + 'ຊອກຫາການຜູກມັດດ້ວຍ subject ແລະ ອັບເດດສະເພາະ User.Name ເມື່ອຊື່ຜູ້ໃຊ້ໃໝ່ສາມາດໃຊ້ໄດ້.', + testBeforeBrowserTest: + 'ທົດສອບການຕັ້ງຄ່າປັດຈຸບັນກ່ອນທີ່ຈະເລີ່ມການທົດສອບການເຂົ້າສູ່ລະບົບຂອງຕົວທ່ອງເວັບ.', + testBeforeEnable: 'ທົດສອບການຕັ້ງຄ່າປັດຈຸບັນກ່ອນບັນທຶກການປ່ຽນແປງການຕັ້ງຄ່າ.', + testConfiguration: 'ທົດສອບການຕັ້ງຄ່າ', + testDiscovery: 'ທົດສອບ Discovery', + tlsCustomCA: 'HTTPS · ໃບຢັ້ງຢືນ CA ແບບກຳນົດເອງ', + tlsPrivateHTTP: 'HTTP · ເຄືອຂ່າຍສ່ວນຕົວເທົ່ານັ້ນ (ອັນຕະລາຍ)', + tlsPrivateHTTPWarning: + 'HTTP ບໍ່ມີການເຂົ້າລະຫັດການຂົນສົ່ງ ແລະຖືກຈຳກັດໃຫ້ເປົ້າໝາຍສ່ວນຕົວທີ່ອະນຸຍາດຢ່າງຈະແຈ້ງ.', + tlsSkipVerify: 'HTTPS · ຂ້າມການຢັ້ງຢືນໃບຢັ້ງຢືນ (ອັນຕະລາຍ)', + tlsSystem: 'HTTPS · ການຢັ້ງຢືນລະບົບ (ແນະນຳ)', + tokenEndpoint: 'Token Endpoint', + tokenEndpointInvalid: 'ໃສ່ Token Endpoint ທີ່ຖືກຕ້ອງ.', + transportSecurity: 'ຄວາມປອດໄພການຂົນສົ່ງ', + transportSecurityHelper: + 'ຕ້ອງການ HTTPS. HTTP ສ່ວນຕົວຍັງຕ້ອງການການເຂົ້າເຖິງ private-network ຢ່າງຊັດເຈນ.', + unsavedChanges: 'ມີການປ່ຽນແປງ OIDC ທີ່ຍັງບໍ່ໄດ້ບັນທຶກ.', + usedClaim: 'Claim ໃຊ້ແລ້ວ', + userInfoEndpoint: 'UserInfo Endpoint', + userInfoEndpointHelper: + 'ເມື່ອບໍ່ມີຟິວຊື່ຜູ້ໃຊ້ ລະບົບຈະເຕີມຈາກ endpoint ນີ້; ປ່ອຍຫວ່າງເພື່ອບໍ່ເຕີມ.', + userInfoEndpointInvalid: 'ໃສ່ UserInfo Endpoint ທີ່ຖືກຕ້ອງ.', + userMapping: 'ການຕັ້ງຄ່າຜູ້ໃຊ້', + userMappingDesc: + 'ກຳນົດການຈັບຄູ່ຊື່ຜູ້ໃຊ້ OIDC ແລະໂນດກັບບົດບາດເລີ່ມຕົ້ນທີ່ໃຊ້ສ້າງຜູ້ໃຊ້ໃນການເຂົ້າລະບົບຄັ້ງທຳອິດ.', + }, + saml2: { + actionCreate: 'ສ້າງຜູ້ໃຊ້', + actionPending: 'ລໍຖ້າຜົນໄດ້ຮັບ', + actionReject: 'ປະຕິເສດການເຂົ້າສູ່ລະບົບ', + actionReuse: 'ໃຊ້ຜູ້ໃຊ້ທີ່ຜູກມັດແລ້ວ', + assignDefaultRole: 'ກຳນົດບົດບາດເລີ່ມຕົ້ນ: {role}', + basic: 'ການຕັ້ງຄ່າພື້ນຖານ', + basicDesc: 'ຕັ້ງຄ່າຕົວເລືອກທີ່ຈຳເປັນສຳລັບຜູ້ໃຫ້ບໍລິການ SAML2 ມາດຕະຖານ.', + browserTest: 'ທົດສອບເຂົ້າລະບົບ', + browserTestConflict: 'ຢັ້ງຢືນຕົວຕົນແລ້ວ ແຕ່ຊື່ຜູ້ໃຊ້ຂັດກັນ', + browserTestConflictHelper: + 'ຊື່ຜູ້ໃຊ້ທີ່ຈັບຄູ່ໄວ້ເປັນຂອງຕົວຕົນອື່ນ ແລະ ຈະບໍ່ຖືກເຊື່ອມຕໍ່ອັດຕະໂນມັດ.', + browserTestExpired: 'ການທົດສອບໂປຣແກຣມທ່ອງເວັບໝົດອາຍຸແລ້ວ', + browserTestExpiredHelper: 'ເລີ່ມການທົດສອບຕົວທ່ອງເວັບໃຫມ່ແລະສໍາເລັດການອະນຸຍາດກ່ອນທີ່ມັນຈະຫມົດອາຍຸ.', + browserTestFailed: 'ການທົດສອບຕົວທ່ອງເວັບລົ້ມເຫລວ', + browserTestFailedHelper: + 'ບໍ່ສາມາດສະແດງຕົວຢ່າງຂໍ້ມູນຕົວຕົນໄດ້. ກວດສອບຂໍ້ຜິດພາດທີ່ backend ສົ່ງກັບມາໃນພາສາປະຈຸບັນ.', + browserTestIsolation: + 'ດຳເນີນການອະນຸຍາດແບບໄປ-ກັບຈິງ ແຕ່ຈະບໍ່ສ້າງ ຫຼື ອັບເດດຜູ້ໃຊ້, ມອບໝາຍບົດບາດ ຫຼື ສ້າງເຊດຊັນເຂົ້າລະບົບຈິງ.', + browserTestPopupBlocked: + 'ອະນຸຍາດໃຫ້ປັອບອັບສໍາລັບເວັບໄຊທ໌ນີ້, ຈາກນັ້ນເລີ່ມການທົດສອບຕົວທ່ອງເວັບອີກຄັ້ງ.', + browserTestPopupClosed: 'ປ່ອງຢ້ຽມການອະນຸຍາດຖືກປິດກ່ອນການທົດສອບສໍາເລັດ.', + browserTestSuccess: 'ຢັ້ງຢືນຜູ້ໃຫ້ບໍລິການສຳເລັດແລ້ວ', + browserTestSuccessHelper: 'ແຜນທີ່ການລະບຸຕົວຕົນໄດ້ຖືກສະແດງຕົວຢ່າງໂດຍບໍ່ມີການປ່ຽນຜູ້ໃຊ້ ຫຼືເຊດຊັນ.', + browserTestTitle: 'SAML2 ທົດສອບການເຂົ້າສູ່ລະບົບຂອງຕົວທ່ອງເວັບ', + browserTestWaiting: 'ກຳລັງລໍຖ້າການອະນຸຍາດຈາກຜູ້ໃຫ້ບໍລິການ', + browserTestWaitingHelper: + 'ສຳເລັດການເຂົ້າສູ່ລະບົບໃນໜ້າຈໍໂປຣແກຣມທ່ອງເວັບໃໝ່. ໜ້ານີ້ຈະອັບເດດໂດຍອັດຕະໂນມັດ.', + certificateFileInvalid: 'ເລືອກໄຟລ໌ໃບຢັ້ງຢືນ PEM, CRT ຫຼື CER ທີ່ຖືກຕ້ອງ.', + configured: 'ຕັ້ງຄ່າແລ້ວ', + configurationFailedHelper: + 'ການທົດສອບລົ້ມເຫຼວ. ໜ້ານີ້ສະແດງສະເພາະຂໍ້ຜິດພາດທີ່ backend ສົ່ງກັບມາໃນພາສາປະຈຸບັນ.', + configurationNotTested: 'ການຕັ້ງຄ່າປັດຈຸບັນຍັງບໍ່ໄດ້ຖືກທົດສອບ.', + configurationPassed: 'ການຕັ້ງຄ່າປັດຈຸບັນຜ່ານການກວດສອບຄວາມປອດໄພ ແລະຄວາມສາມາດ.', + configurationStaleHelper: + 'ການ​ຕັ້ງ​ຄ່າ​ທີ່​ລະ​ອຽດ​ອ່ອນ​ການ​ກວດ​ສອບ​ໄດ້​ປ່ຽນ​ແປງ​. ທົດສອບສະບັບຮ່າງປະຈຸບັນອີກຄັ້ງ.', + configurationTestSuccess: 'ການທົດສອບການຕັ້ງຄ່າ SAML2 ສຳເລັດແລ້ວ.', + configurationTesting: 'ກຳລັງທົດສອບການຕັ້ງຄ່າ SAML2 ໃນປັດຈຸບັນ...', + conflictLDAP: 'ຜູ້ໃຊ້ LDAP', + conflictLocal: 'ຜູ້ໃຊ້ທ້ອງຖິ່ນ', + conflictNone: 'ບໍ່ມີຂໍ້ຂັດແຍ່ງ', + conflictOIDC: 'ຕົວຕົນ OIDC ອື່ນ', + conflictSAML2: 'ຕົວຕົນ SAML2 ອື່ນ', + conflictType: 'ປະເພດການຂັດແຍ້ງ', + credentialFileReadFailed: 'ບໍ່ສາມາດອ່ານໄຟລ໌ຂໍ້ມູນຢັ້ງຢືນໄດ້.', + credentialFileTooLarge: 'ໄຟລ໌ຂໍ້ມູນຢັ້ງຢືນຕ້ອງມີຂະໜາດບໍ່ເກີນ 256 KiB.', + credentialsRequired: 'ຕັ້ງຄ່າທັງກະແຈສ່ວນຕົວ ແລະໃບຢັ້ງຢືນຂອງ SP.', + defaultRole: 'ບົດບາດຜູ້ໃຊ້ໃໝ່', + defaultRoleHelper: 'ກຳນົດພຽງຄັ້ງທຳອິດ; ການເຂົ້າຄັ້ງຕໍ່ໄປຮັກສາບົດບາດ, MFA ແລະສິດທ້ອງຖິ່ນ.', + defaultRolePlaceholder: 'ເລືອກບົດບາດ', + defaultRoleRequired: 'ເລືອກບົດບາດເລີ່ມຕົ້ນທີ່ຖືກຕ້ອງ.', + disableConfirm: + 'ການປິດໃຊ້ງານ SAML2 ຈະປະຕິເສດການເຂົ້າລະບົບໃໝ່ ແລະເຮັດໃຫ້ເຊດຊັນຜູ້ໃຊ້ໝົດຜົນທັນທີ. ສືບຕໍ່?', + disableDiscardConfirm: + 'ການປິດໃຊ້ງານ SAML2 ຈະຍົກເລີກການປ່ຽນແປງອື່ນທີ່ຍັງບໍ່ໄດ້ບັນທຶກໃນໜ້ານີ້ ແລະເຮັດໃຫ້ເຊດຊັນຜູ້ໃຊ້ໝົດຜົນທັນທີ. ສືບຕໍ່?', + disableTitle: 'ປິດໃຊ້ງານ SAML2', + disabled: 'ປິດໃຊ້ງານ', + enable: 'ເປີດໃຊ້ງານ', + enabled: 'ເປີດໃຊ້ງານແລ້ວ', + idpMetadata: 'ຂໍ້ມູນເມຕາຂອງ IdP', + idpMetadataDesc: 'ໃສ່ URL ຫຼືວາງ XML. ຖ້າມີທັງສອງ URL ຈະຖືກໃຊ້ກ່ອນ.', + keepExistingRole: 'ຮັກສາບົດບາດທີ່ມີຢູ່ແລ້ວແລະການອະນຸຍາດທ້ອງຖິ່ນ', + loginWith: 'ເຂົ້າລະບົບດ້ວຍ {provider}', + mappingResult: 'ຜົນແຜນທີ່', + metadataRequired: 'ໃສ່ URL ຫຼື XML ຂອງ IdP Metadata.', + metadataURLHelper: 'backend ດາວໂຫຼດ ແລະກວດສອບ Metadata ໃນຂະນະທົດສອບ ແລະບັນທຶກ.', + metadataURLInvalid: 'ໃສ່ Metadata URL ແບບ HTTPS ທີ່ຖືກຕ້ອງ ໂດຍບໍ່ມີຂໍ້ມູນຢັ້ງຢືນ ຫຼື fragment.', + metadataURLRecommended: 'Metadata URL (ແນະນຳ)', + metadataXML: 'ຂໍ້ມູນເມຕາ XML', + metadataXMLHelper: 'ໃຊ້ເມື່ອ IdP ບໍ່ມີ Metadata URL ທີ່ສາມາດເຂົ້າເຖິງໄດ້.', + metadataXMLInvalid: 'ໃສ່ XML Metadata ແບບ EntityDescriptor ທີ່ຖືກຕ້ອງ.', + metadataXMLPlaceholder: 'ວາງ ...', + nameAttribute: 'Attribute ຊື່ຜູ້ໃຊ້', + nameAttributeHelper: + 'ອ່ານ Attribute ນີ້ຈາກ SAML Assertion ທີ່ກວດສອບແລ້ວ ແລະຈັບຄູ່ກັບຊື່ຜູ້ໃຊ້ 1Panel.', + nameAttributePlaceholder: 'ຕົວຢ່າງ: uid, username ຫຼື account', + nameAttributeRequired: 'ໃສ່ Attribute ຊື່ຜູ້ໃຊ້.', + notConfigured: 'ຍັງບໍ່ໄດ້ຕັ້ງຄ່າ', + or: 'ຫຼື', + pageDesc: 'ເຊື່ອມຕໍ່ SSO ອົງກອນຜ່ານ IdP Metadata ໃນໜ້າດຽວ.', + plannedHandling: 'ການຈັດການແຜນການ', + privateKeyFileInvalid: 'ເລືອກໄຟລ໌ກະແຈສ່ວນຕົວ PEM ທີ່ຖືກຕ້ອງ.', + recentTestSuccess: 'ການທົດສອບຄັ້ງສຸດທ້າຍປະສົບຜົນສໍາເລັດ: {0}', + restore: 'ກູ້ຄືນ', + restored: 'ການຕັ້ງຄ່າ SAML2 ທີ່ບັນທຶກໄວ້ຫຼ້າສຸດໄດ້ຖືກຟື້ນຟູຄືນມາ.', + roleHandling: 'ການຈັດການພາລະບົດບາດ', + rolesLoadFailed: 'ບໍ່ສາມາດໂຫຼດບົດບາດໄດ້. ລອງອີກຄັ້ງກ່ອນທີ່ຈະເລືອກບົດບາດເລີ່ມຕົ້ນ.', + selectFile: 'ເລືອກໄຟລ໌', + serviceStatus: 'ສະຖານະບໍລິການ', + serviceStatusDesc: 'ການຕັ້ງຄ່າປັດຈຸບັນຕ້ອງຜ່ານການທົດສອບກ່ອນເປີດໃຊ້ SAML2.', + settingLoadFailed: 'ການຕັ້ງຄ່າ SAML2 ບໍ່ສາມາດໂຫຼດໄດ້', + settingLoadFailedHelper: + 'ແບບຟອມຖືກລັອກເພື່ອຫຼີກເວັ້ນການບັນທຶກການຕັ້ງຄ່າເລີ່ມຕົ້ນທີ່ຫວ່າງເປົ່າໃສ່ກັບການຕັ້ງຄ່າປັດຈຸບັນ. ລອງໃໝ່ຫຼັງຈາກການເຊື່ອມຕໍ່ຟື້ນຕົວ.', + spCertificate: 'ໃບຢັ້ງຢືນ SP', + spCertificateHelper: 'ເຜີຍແຜ່ໃນ SP Metadata ເພື່ອໃຫ້ IdP ກວດສອບຄຳຮ້ອງຂໍເຂົ້າ ແລະອອກລະບົບ.', + spCredentials: 'ກະແຈສ່ວນຕົວ ແລະໃບຢັ້ງຢືນ SP', + spCredentialsDesc: + 'ໃຊ້ເພື່ອເຊັນຂໍ້ຄວາມເຂົ້າ ແລະອອກລະບົບ. ນະໂຍບາຍລາຍເຊັນ ແລະການກວດສອບຖືກກຳນົດໂດຍ backend.', + spPrivateKey: 'ກະແຈສ່ວນຕົວ SP', + spPrivateKeyHelper: + 'ໃຊ້ເພື່ອເຊັນ AuthnRequest ແລະຂໍ້ຄວາມອອກລະບົບ. ກະແຈຈະຖືກເຂົ້າລະຫັດເມື່ອຈັດເກັບ ແລະບໍ່ຖືກສະແດງ.', + syncLogout: 'ອອກລະບົບແບບຊິງຄ໌', + syncLogoutHelper: 'ການອອກຈາກ 1Panel ຫຼື IdP ຈະອອກຈາກອີກຝ່າຍດ້ວຍ.', + testBeforeBrowserTest: + 'ທົດສອບການຕັ້ງຄ່າປັດຈຸບັນກ່ອນທີ່ຈະເລີ່ມການທົດສອບການເຂົ້າສູ່ລະບົບຂອງຕົວທ່ອງເວັບ.', + testBeforeEnable: 'ທົດສອບການຕັ້ງຄ່າປັດຈຸບັນກ່ອນທີ່ຈະເປີດ ຫຼືບັນທຶກການປ່ຽນແປງທີ່ລະອຽດອ່ອນ.', + testConfiguration: 'ທົດສອບການຕັ້ງຄ່າ', + unsavedChanges: 'ມີການປ່ຽນແປງ SAML2 ທີ່ຍັງບໍ່ໄດ້ບັນທຶກ.', + usedAttribute: 'ການຈັບຄູ່ຊື່ຜູ້ໃຊ້', + usersAndRoles: 'ຜູ້ໃຊ້ ແລະບົດບາດ', + usersAndRolesDesc: + 'ກຳນົດການຈັບຄູ່ຊື່ຜູ້ໃຊ້ແຜງ ແລະໂນດກັບບົດບາດເລີ່ມຕົ້ນທີ່ໃຊ້ສ້າງຜູ້ໃຊ້ໃນການເຂົ້າລະບົບຄັ້ງທຳອິດ.', + }, ldap: { + basic: 'ການຕັ້ງຄ່າພື້ນຖານ', + loginTitle: 'ເຂົ້າລະບົບ LDAP', + loginWith: 'ເຂົ້າລະບົບດ້ວຍ LDAP', + backToLocalLogin: 'ກັບໄປການເຂົ້າລະບົບແຜງ', enable: 'ເປີດໃຊ້', enabled: 'ເປີດໃຊ້ແລ້ວ', disabled: 'ປິດໃຊ້ງານ', @@ -5025,8 +5405,8 @@ const message = { black: 'ຢູ່ໃນບັນຊີດຳ', notBlack: 'ບໍ່ຢູ່ໃນບັນຊີດຳ', fuzzy: 'ການຈັບຄູ່ແບບຄຸມເຄືອ', - regex: 'Regular Expression', - invalidRegex: 'ປ້ອນ RE2 Regular Expression ທີ່ຖືກຕ້ອງ ແລະ ຍາວບໍ່ເກີນ 256 ຕົວອັກສອນ', + regex: 'ນິພົດປົກກະຕິ', + invalidRegex: 'ປ້ອນນິພົດປົກກະຕິ RE2 ທີ່ຖືກຕ້ອງ ແລະ ຍາວບໍ່ເກີນ 256 ຕົວອັກສອນ', created: 'ສ້າງວຽກສົ່ງອອກແລ້ວ', fileName: 'ຊື່ໄຟລ໌', fileSize: 'ຂະໜາດໄຟລ໌', @@ -5035,6 +5415,7 @@ const message = { deleteConfirm: 'ລຶບບັນທຶກການສົ່ງອອກ ແລະ ໄຟລ໌ນີ້ບໍ?', }, waf: { + WAF: 'WAF', name: 'WAF', blackWhite: 'ລາຍຊື່ດຳ ແລະ ຂາວ', globalSetting: 'ຕັ້ງຄ່າທົ່ວໄປ', @@ -5099,6 +5480,7 @@ const message = { provinceRuleLabel: 'ແຂວງ', openRestyFeatureVersionAlert: 'OpenResty ຕ້ອງໃໝ່ກວ່າ 1.31.1.1-0 ເພື່ອໃຫ້ {0} ມີຜົນ.', ipLocation: 'ທີ່ຕັ້ງ IP', + ipLocationSearchHelper: 'ປ້ອນທີ່ຕັ້ງ IP, ຮອງຮັບການຄົ້ນຫາແບບຄ້າຍຄື', action: 'ການດຳເນີນການ', ruleType: 'ປະເພດການໂຈມຕີ', ipHelper: 'ປ້ອນທີ່ຢູ່ IP', @@ -5136,7 +5518,7 @@ const message = { ruleContent: 'ເນື້ອໃນ', contain: 'ລວມມີ', equal: 'ເທົ່າກັບ', - regex: 'Regular Expression', + regex: 'ນິພົດປົກກະຕິ', notEqual: 'ບໍ່ເທົ່າກັບ', customRuleHelper: 'ດຳເນີນການຕາມເງື່ອນໄຂທີ່ກຳນົດ', actionAllow: 'ອະນຸຍາດ', @@ -5258,7 +5640,7 @@ const message = { attackCountNum: 'ຈຳນວນຄັ້ງ', percent: 'ເປີເຊັນ', addblackUrlHelper: 'ຕ້ອງການເພີ່ມ URL: {0} ເຂົ້າໃນບັນຊີດຳເລີ່ມຕົ້ນບໍ?', - rce: 'Remote Code Execution', + rce: 'ການປະຕິບັດໂຄດຈາກໄລຍະໄກ', software: 'ຊອບແວ', cveHelper: 'ລວມມີຊ່ອງໂຫວ່ຂອງຊອບແວ ແລະ Framework ທີ່ພົບເລື້ອຍ', vulnCheck: 'ກົດເກນເພີ່ມເຕີມ', @@ -5267,7 +5649,7 @@ const message = { ua: 'ການເຂົ້າເຖິງໂດຍບໍ່ໄດ້ຮັບອະນຸຍາດ', id: 'ຂໍ້ມູນຮົ່ວໄຫຼ', aa: 'ການຂ້າມຜ່ານການຢືນຢັນຕົວຕົນ', - dr: 'Directory Traversal', + dr: 'ການຂ້າມໄດເຣັກທໍຣີ', xxe: 'ຊ່ອງໂຫວ່ XXE', suid: 'ຊ່ອງໂຫວ່ Serialization', dos: 'ຊ່ອງໂຫວ່ Denial of Service', @@ -5299,6 +5681,9 @@ const message = { observationModeConfirm: 'ໃນໂໝດສັງເກດການ ການຈັບຄູ່ WAF ທັງໝົດຈະຖືກບັນທຶກໂດຍບໍ່ບລັອກຄຳຮ້ອງຂໍ. ຕ້ອງການຕໍ່ບໍ?', globalStrictRequired: 'ກະລຸນາເປີດໂໝດເຂັ້ມງວດໃນການຕັ້ງຄ່າສ່ວນກາງກ່ອນ', observe: 'ສັງເກດການ', + websiteSearchHelper: 'ປ້ອນໂດເມນ, ນາມແຝງ ຫຼື ໝາຍເຫດຂອງເວັບໄຊ', + configReadFailed: 'ໂຫຼດການຕັ້ງຄ່າບໍ່ສຳເລັດ', + detailSetting: 'ການຕັ້ງຄ່າລະອຽດ', saveLog: 'ບັນທຶກ Log', remoteURLHelper: 'Remote URL ຕ້ອງມີໜຶ່ງ IP ຕໍ່ແຖວ ແລະ ບໍ່ມີຕົວອັກສອນອື່ນ', notFound: 'ບໍ່ພົບ (404)', @@ -6054,7 +6439,7 @@ const message = { dependencyPurpose: 'ຈຸດປະສົງ', dependencyPurposeMap: { libvirt: 'ໃຫ້ບໍລິການຈັດການ VM ສຳລັບຄວບຄຸມວົງຈອນຊີວິດ ແລະ ຈັດສັນຊັບພະຍາກອນ.', - storage: 'ສະໜອງໄດເຣັກທໍຣີ ຫຼື Storage Pool ເລີ່ມຕົ້ນສຳລັບໄຟລ໌ດິສກ໌ຂອງ VM.', + storage: 'ສະໜອງໄດເຣັກທໍຣີ ຫຼື ພູລຈັດເກັບເລີ່ມຕົ້ນສຳລັບໄຟລ໌ດິສກ໌ຂອງ VM.', }, dependencyNotReady: 'ການກວດສອບສິ່ງຂຶ້ນກັບຂອງ VM ລົ້ມເຫຼວ. ກະລຸນາແກ້ໄຂກ່ອນໃຊ້ເຄື່ອງສະເໝືອນ.', helperUnavailable: 'ເລີ່ມຕົ້ນຄວາມສາມາດ VM ລົ້ມເຫຼວ. ກວດສອບ Core Log ຫຼື ອັບເກຣດອີກຄັ້ງກ່ອນໃຊ້ VM.', @@ -6085,7 +6470,7 @@ const message = { needAttention: 'ຕ້ອງເອົາໃຈໃສ່', normal: 'ປົກກະຕິ', environmentRisk: 'ຣັນທາມ VM ຍັງບໍ່ພ້ອມ. ກະລຸນາແກ້ໄຂສິ່ງຂຶ້ນກັບ ຫຼື ບໍລິການ Virtualization.', - storageRisk: 'ການໃຊ້ Storage Pool {0} ຮອດ {1}% ແລ້ວ.', + storageRisk: 'ການໃຊ້ພູລຈັດເກັບ {0} ຮອດ {1}% ແລ້ວ.', abnormalRisk: 'ມີ VM {0} ເຄື່ອງຢູ່ໃນສະຖານະຜິດປົກກະຕິ.', pausedRisk: 'ມີ VM {0} ເຄື່ອງຖືກຢຸດຊົ່ວຄາວ.', memoryRisk: 'ການຈັດສັນໜ່ວຍຄວາມຈຳຂອງ VM ຮອດ {0}% ແລ້ວ.', @@ -6093,7 +6478,7 @@ const message = { cpuLimitExceeded: 'CPU ເກີນຂີດຈຳກັດ. ສູງສຸດທີ່ໃຊ້ໄດ້ໃນປັດຈຸບັນ: {0} Core.', memoryLimitHelper: 'ໜ່ວຍຄວາມຈຳທີ່ຈັດສັນໄດ້ໃນປັດຈຸບັນ: {0} (Host ຕ້ອງສຳຮອງໜ່ວຍຄວາມຈຳ {1})', memoryLimitExceeded: 'ໜ່ວຍຄວາມຈຳເກີນຂີດຈຳກັດ. ສູງສຸດທີ່ຈັດສັນໄດ້ໃນປັດຈຸບັນ: {0}.', - storageLimitHelper: 'ພື້ນທີ່ວ່າງໃນ Storage Pool ເປົ້າໝາຍປັດຈຸບັນ: {0}', + storageLimitHelper: 'ພື້ນທີ່ວ່າງໃນພູລຈັດເກັບເປົ້າໝາຍປັດຈຸບັນ: {0}', storageLimitExceeded: 'ຄວາມຈຸດິສກ໌ເກີນຂີດຈຳກັດ. ສູງສຸດທີ່ໃຊ້ໄດ້ໃນປັດຈຸບັນ: {0}.', iso: 'ISO', createFromTemplate: 'ສ້າງຈາກແມ່ແບບ', @@ -6119,7 +6504,7 @@ const message = { diskSize: 'ຂະໜາດດິສກ໌', diskPath: 'ເສັ້ນທາງດິສກ໌', isoPath: 'ເສັ້ນທາງ ISO', - storagePool: 'Storage Pool', + storagePool: 'ພູລຈັດເກັບ', network: 'ເຄືອຂ່າຍ', bridgeName: 'ຊື່ Bridge', natNetworkHelper: 'VM ສາມາດເຂົ້າເຄືອຂ່າຍຜ່ານ Host, ແຕ່ອຸປະກອນພາຍນອກໂດຍທົ່ວໄປບໍ່ສາມາດເຂົ້າ VM ໂດຍກົງໄດ້.', @@ -6127,9 +6512,9 @@ const message = { 'ເຊື່ອມຕໍ່ VM ກັບ Bridge ທີ່ມີຢູ່ໃນ Host (ເຊັ່ນ br0). ຖ້າ Host ມີ NIC ເພີ່ມເຕີມທີ່ບໍ່ໄດ້ໃຊ້ ໃຫ້ສ້າງ Bridge ສຳລັບມັນແລ້ວນຳມາໃຊ້.', bridgeNameHelper: 'ເລືອກ Linux Bridge ທີ່ມີຢູ່ໃນ Host ເຊັ່ນ br0. NIC ກາຍະພາບບໍ່ແມ່ນ Bridge ແລະ ບໍ່ສາມາດເລືອກ Bridge ທີ່ docker/libvirt ຈັດການໄດ້.', - natCIDRHelper: 'CIDR, Gateway ແລະ ຊ່ວງ DHCP ຈະຖືກໃຊ້ໂດຍເຄືອຂ່າຍສະເໝືອນ NAT ໃໝ່.', + natCIDRHelper: 'CIDR, ປະຕູເຄືອຂ່າຍ ແລະ ຊ່ວງ DHCP ຈະຖືກໃຊ້ໂດຍເຄືອຂ່າຍສະເໝືອນ NAT ໃໝ່.', networkCIDR: 'CIDR ເຄືອຂ່າຍ', - gateway: 'Gateway', + gateway: 'ປະຕູເຄືອຂ່າຍ', dhcpStart: 'DHCP ເລີ່ມຕົ້ນ', dhcpEnd: 'DHCP ສິ້ນສຸດ', bootOrder: 'ລຳດັບການບູດ', @@ -6155,17 +6540,17 @@ const message = { renameRunningHelper: 'ກະລຸນາປິດເຄື່ອງສະເໝືອນກ່ອນປ່ຽນຊື່.', cpuUsage: 'ການໃຊ້ CPU', memoryUsage: 'ການໃຊ້ໜ່ວຍຄວາມຈຳ', - diskIO: 'Disk IO', - networkIO: 'Network IO', + diskIO: 'I/O ດິສກ໌', + networkIO: 'I/O ເຄືອຂ່າຍ', diskReadWrite: 'ອ່ານ / ຂຽນດິສກ໌', - networkRxTx: 'Network RX / TX', + networkRxTx: 'RX / TX ເຄືອຂ່າຍ', rx: 'RX', tx: 'TX', - console: 'Console', - consoleNotReady: 'VNC Console ໃຊ້ງານບໍ່ໄດ້. ກະລຸນາເລີ່ມ VM ແລະ ກວດສອບການຕັ້ງຄ່າກຣາຟິກ VNC.', - consoleDisconnected: 'VNC Console ຖືກຕັດການເຊື່ອມຕໍ່ແລ້ວ.', - consoleConnectFailed: 'ເຊື່ອມຕໍ່ VNC Console ລົ້ມເຫຼວ. ກວດສອບບໍລິການ Console Proxy.', - consoleCredentialsRequired: 'VNC Console ຕ້ອງການຂໍ້ມູນຢືນຢັນ. ກວດສອບການຕັ້ງຄ່າ Backend Proxy.', + console: 'ຄອນໂຊນ', + consoleNotReady: 'ຄອນໂຊນ VNC ໃຊ້ງານບໍ່ໄດ້. ກະລຸນາເລີ່ມ VM ແລະ ກວດສອບການຕັ້ງຄ່າກຣາຟິກ VNC.', + consoleDisconnected: 'ຄອນໂຊນ VNC ຖືກຕັດການເຊື່ອມຕໍ່ແລ້ວ.', + consoleConnectFailed: 'ເຊື່ອມຕໍ່ຄອນໂຊນ VNC ລົ້ມເຫຼວ. ກວດສອບບໍລິການພຣັອກຊີຄອນໂຊນ.', + consoleCredentialsRequired: 'ຄອນໂຊນ VNC ຕ້ອງການຂໍ້ມູນຢືນຢັນ. ກວດສອບການຕັ້ງຄ່າພຣັອກຊີ backend.', snapshot: 'ສະແນັບຊັອດ', createSnapshot: 'ສ້າງສະແນັບຊັອດ', recoverSnapshot: 'ກູ້ຄືນສະແນັບຊັອດ', @@ -6178,7 +6563,7 @@ const message = { 'ບໍ່ສາມາດລຶບສະແນັບຊັອດປັດຈຸບັນໄດ້. ກູ້ຄືນສະແນັບຊັອດໄດ້ສະເພາະເມື່ອປິດເຄື່ອງສະເໝືອນ.', snapshotRecoverConfirm: 'ກູ້ຄືນເຄື່ອງສະເໝືອນ [{1}] ໄປທີ່ສະແນັບຊັອດ [{0}] ບໍ? ດິສກ໌ VM ຈະຖືກກູ້ຄືນເປັນສະຖານະຂອງສະແນັບຊັອດ.', - interface: 'Network Interface', + interface: 'ສ່ວນຕິດຕໍ່ເຄືອຂ່າຍ', device: 'ອຸປະກອນ', path: 'ເສັ້ນທາງ', start: 'ເລີ່ມ', diff --git a/frontend/src/lang/modules/ms.ts b/frontend/src/lang/modules/ms.ts index 5ef00c9e8..a0314bd46 100644 --- a/frontend/src/lang/modules/ms.ts +++ b/frontend/src/lang/modules/ms.ts @@ -11,6 +11,7 @@ const message = { button: { run: 'Jalankan', add: 'Tambah', + select: 'Pilih', save: 'Simpan', set: 'Tetapan', sync: 'Selaras', @@ -29,7 +30,6 @@ const message = { selectAll: 'Pilih semua', login: 'Log masuk', close: 'Tutup', - off: 'Tutup', stop: 'Henti', start: 'Mula', view: 'Lihat', @@ -54,6 +54,7 @@ const message = { power: 'Hantar', search: 'Cari', refresh: 'Segarkan', + reconnect: 'Sambung semula', get: 'Dapatkan', upgrade: 'Tingkatkan', update: 'Kemas Kini', @@ -119,6 +120,9 @@ const message = { card: 'Kad', table: 'Jadual', status: 'Status', + statusSuccess: 'Berjaya', + statusFailed: 'Gagal', + statusWaiting: 'Menunggu...', records: 'Rekod', group: 'Kumpulan', createdAt: 'Waktu dicipta', @@ -163,6 +167,7 @@ const message = { deleteSuccess: 'Berjaya dipadam', loginSuccess: 'Berjaya log masuk', operationSuccess: 'Berjaya dilakukan', + operationFailed: 'Operasi gagal', copySuccess: 'Berjaya disalin', notSupportOperation: 'Operasi ini tidak disokong', requestTimeout: 'Permintaan telah tamat masa, sila cuba lagi nanti', @@ -208,6 +213,7 @@ const message = { username: 'Pengguna', password: 'Kata Laluan', passkey: 'Log masuk Passkey', + otherLoginMethods: 'Kaedah log masuk lain', welcome: 'Selamat datang kembali, sila masukkan nama pengguna dan kata laluan anda untuk log masuk!', errorAuthInfo: 'Nama pengguna atau kata laluan yang anda masukkan tidak betul, sila cuba lagi!', errorMfaInfo: 'Maklumat pengesahan tidak betul, sila cuba lagi!', @@ -293,6 +299,9 @@ const message = { length128Err: 'Panjang tidak boleh melebihi 128 aksara', maxLength: 'Panjang tidak boleh melebihi {0} aksara', alias: 'Menyokong Bahasa Inggeris, nombor, - dan _, panjang 1-128, dan tidak boleh bermula atau berakhir dengan -_.', + vmName: 'Menyokong huruf Inggeris, nombor, ".", "-" dan "_"; panjang: 1-64; mesti bermula dengan huruf atau nombor.', + vmNetwork: + 'Menyokong huruf Inggeris, nombor, ".", ":", "-" dan "_"; panjang: 1-64; mesti bermula dengan huruf atau nombor.', }, res: { paramError: 'Permintaan gagal, sila cuba lagi nanti!', @@ -311,7 +320,6 @@ const message = { success: 'Berjaya', waiting: 'Menunggu', waitForUpgrade: 'Tunggu Naik Taraf', - waiting1: 'Menunggu', failed: 'Gagal', stopped: 'Dihentikan', error: 'Ralat', @@ -335,7 +343,6 @@ const message = { deny: 'Ditolak', accept: 'Diterima', used: 'Digunakan', - unUsed: 'Tidak Digunakan', starting: 'Sedang Memulakan', recreating: 'Sedang Mencipta Semula', creating: 'Sedang Mencipta', @@ -398,16 +405,16 @@ const message = { home: 'Papan Pemuka', apps: 'App Store', website: 'Laman | Laman', - project: 'Project | Projects', - config: 'Configuration | Configurations', - ssh: 'SSH Settings', + project: 'Projek', + config: 'Konfigurasi', + ssh: 'Tetapan SSH', firewall: 'Firewall', - ssl: 'Certificate | Certificates', - database: 'Database | Databases', + ssl: 'Sijil', + database: 'Pangkalan Data', aiTools: 'AI', mcp: 'MCP', - container: 'Container | Containers', - cronjob: 'Cron Job | Cron Jobs', + container: 'Kontena', + cronjob: 'Tugas Berjadual', system: 'System', security: 'Security', files: 'Files', @@ -416,10 +423,10 @@ const message = { settings: 'Tetapan', toolbox: 'Toolbox', logs: 'Log | Logs', - runtime: 'Runtime | Runtimes', - processManage: 'Process | Processes', - process: 'Process | Processes', - network: 'Network | Networks', + runtime: 'Persekitaran Masa Jalan', + processManage: 'Pengurusan Proses', + process: 'Proses', + network: 'Rangkaian', supervisor: 'Supervisor', tamper: 'Bukti Pengubahsuaian', app: 'Aplikasi', @@ -450,11 +457,11 @@ const message = { network: 'Rangkaian', io: 'Disk I/O', ip: 'Local IP', - proxy: 'System proxy', + proxy: 'Proksi sistem', baseInfo: 'Base info', totalSend: 'Jumlah dihantar', totalRecv: 'Jumlah diterima', - rwPerSecond: 'I/O operations', + rwPerSecond: 'Operasi I/O', ioDelay: 'I/O latency', uptime: 'Up since', runningTime: 'Uptime', @@ -477,7 +484,7 @@ const message = { cpuTop: 'Maklumat Proses 5 Teratas Mengikut Penggunaan CPU', memTop: 'Maklumat Proses 5 Teratas Mengikut Penggunaan Memori', logicCore: 'Teras Logik', - loadAverage: 'Purata beban dalam 1 minit terakhir | Purata beban dalam {n} minit terakhir', + loadAverage: 'Purata beban dalam {0} minit terakhir', load: 'Beban', mount: 'Titik Pemasangan', fileSystem: 'Sistem Fail', @@ -513,6 +520,7 @@ const message = { deleteBackupHelper: 'Padam sandaran pangkalan data secara serentak', delete: 'Operasi padam tidak boleh diundurkan, sila masukkan "', deleteHelper: '" untuk memadam pangkalan data ini', + deleteUserHelper: '" untuk memadam pengguna ini', userBoundDatabases: 'mempunyai akses kepada pangkalan data berikut:', noMysql: 'Perkhidmatan pangkalan data (MySQL atau MariaDB)', noPostgresql: 'Perkhidmatan pangkalan data PostgreSQL', @@ -563,6 +571,7 @@ const message = { revokeAuthorizationHelper: 'Tarik balik akses pengguna {0} kepada pangkalan data {1}?', supplementPassword: 'Tambah kata laluan', supplementPasswordHelper: 'Hanya menyimpan kata laluan sedia ada ke 1Panel dan tidak mengubahnya dalam MySQL.', + noUserBind: 'Tiada kaitan', pgBindHelper: 'Operasi ini digunakan untuk mencipta pengguna baharu dan mengaitkannya dengan pangkalan data sasaran. Pada masa ini, memilih pengguna yang sudah wujud dalam pangkalan data tidak disokong.', pgSuperUser: 'Pengguna Super', @@ -941,9 +950,9 @@ const message = { 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', ollama_sync: - 'Sincronizando o modelo Ollama, encontrou que os seguintes modelos não existem, deseja excluí-los?', - from_remote: 'Este modelo não foi baixado via 1Panel, sem logs de pull relacionados.', - no_logs: 'Os logs de pull deste modelo foram excluídos e não podem ser visualizados.', + 'Semasa menyegerakkan model Ollama, model berikut didapati tidak wujud. Adakah anda mahu memadamkannya?', + from_remote: 'Model ini tidak dimuat turun melalui 1Panel; tiada log muat turun berkaitan.', + no_logs: 'Log muat turun model ini telah dipadam dan tidak boleh dilihat.', vllmVersionHelper: 'Untuk pelayan FusionXpark GB 10, sila pilih versi -cu130.', vllmCommandPortHelper: 'Perintah permulaan mesti menggunakan port {0}; jika tidak, perkhidmatan tidak dapat diakses.', @@ -1006,9 +1015,6 @@ const message = { failureCount: 'Bilangan gagal', lastError: 'Ralat terkini', modelMap: 'Pemetaan model', - apiKeyKeepEmpty: 'API Key (biarkan kosong untuk kekal)', - apiKeyOnceHint: 'API Key hanya dipaparkan sekali semasa penciptaan. Salin dan simpan sekarang.', - apiKeyOnceSave: 'API Key hanya dipaparkan sekali. Simpan sekarang:', qpsLimit: 'Had QPS', tokenLimit: 'Had Token', tokenUsed: 'Token digunakan', @@ -1150,23 +1156,23 @@ const message = { modelGroupGuide: 'Kumpulan model mengandungi nama model permintaan yang didedahkan oleh AI Gateway. Konfigurasikan model upstream dalam pemetaan model kumpulan akaun. auto ialah nama model maya dan tidak perlu ditambah pada kumpulan model.', modelGroupModelCount: '{0} model', - contentCompliance: 'Content Compliance', - contentAction: 'Action', - actionBlock: 'Block', - actionAuditOnly: 'Audit only', + contentCompliance: 'Pematuhan Kandungan', + contentAction: 'Tindakan', + actionBlock: 'Sekat', + actionAuditOnly: 'Audit sahaja', actionDropHistory: 'Buang sejarah', - severity: 'Severity', - severityHigh: 'High', - severityMedium: 'Medium', - severityLow: 'Low', - sensitiveWord: 'Sensitive word', - sensitiveGroup: 'Sensitive word group', - sensitiveWordCount: 'Words', - normalizedWord: 'Normalized word', - matchedWords: 'Matched words', - matchedGroups: 'Matched groups', - importResult: 'Imported {0}, duplicated {1}, invalid {2}', - auditLogs: 'Audit Logs', + severity: 'Tahap', + severityHigh: 'Tinggi', + severityMedium: 'Sederhana', + severityLow: 'Rendah', + sensitiveWord: 'Perkataan sensitif', + sensitiveGroup: 'Kumpulan perkataan sensitif', + sensitiveWordCount: 'Perkataan', + normalizedWord: 'Perkataan dinormalkan', + matchedWords: 'Perkataan sepadan', + matchedGroups: 'Kumpulan sepadan', + importResult: 'Diimport {0}, pendua {1}, tidak sah {2}', + auditLogs: 'Log Audit', smartRoute: 'Penghalaan Pintar', smartRouteGuideTitle: 'Gunakan model=auto pada klien untuk memasuki penghalaan pintar', smartRouteGuideReady: @@ -1239,7 +1245,7 @@ const message = { skillsHub: { title: 'Skills Hub', upload: 'Muat naik Skill', - importSkill: 'Import Skill', + importSkill: 'Import Kemahiran', repositoryAddress: 'Alamat repositori', repositoryGithubOnly: 'Hanya alamat repositori GitHub disokong', repositoryRef: 'Cawangan atau Tag', @@ -1488,14 +1494,14 @@ const message = { streamableHttpPathHelper: 'Contoh: /mcp, elakkan daripada bertindan dengan pelayan lain', npxHelper: 'Sesuai untuk mcp yang dimulakan dengan npx atau binari', uvxHelper: 'Sesuai untuk mcp yang dimulakan dengan uvx', - protocolVersion: 'Protocol Version', + protocolVersion: 'Versi Protokol', protocolVersionHelper: - 'Only used by stateless Streamable HTTP to auto-initialize the downstream stdio MCP Server', + 'Hanya digunakan oleh Streamable HTTP tanpa keadaan untuk memulakan MCP Server stdio hiliran secara automatik', gatewayArgsHelper: 'Argumen ditambahkan pada arahan supergateway. Argumen pengangkutan, port, laluan dan protokol yang diurus oleh 1Panel tidak boleh diubah', - testConnection: 'Test Connection', - connectionSuccess: 'Connection succeeded', - connectionFailed: 'Connection failed', + testConnection: 'Uji Sambungan', + connectionSuccess: 'Sambungan berjaya', + connectionFailed: 'Sambungan gagal', }, tensorRT: { llm: 'TensorRT LLM', @@ -1569,8 +1575,9 @@ const message = { lastHour: 'Jam terakhir', last10Min: '10 minit terakhir', cleanLog: 'Bersihkan log', + cleanLogscope: 'Jenis pembersihan', downLogHelper1: 'Ini akan memuat turun semua log dari kontena {0}. Adakah anda mahu meneruskan?', - downLogHelper2: 'Ini akan memuat turun log terkini {0} dari kontena {0}. Adakah anda mahu meneruskan?', + downLogHelper2: 'Ini akan memuat turun {1} log terkini daripada kontena {0}. Adakah anda mahu meneruskan?', cleanLogHelper: 'Ini memerlukan memulakan semula kontena dan tidak boleh diundur. Adakah anda mahu meneruskan?', newName: 'Nama baru', source: 'Penggunaan sumber', @@ -1768,7 +1775,8 @@ const message = { dockerStatus: 'Perkhidmatan Docker', daemonJsonPathHelper: 'Pastikan laluan konfigurasi sama seperti yang dinyatakan dalam docker.service.', mirrors: 'Cermin pendaftaran', - mirrorsHelper: '', + mirrorsHelper: + 'Gunakan URL cermin registri terlebih dahulu untuk operasi imej. Biarkan kosong untuk melumpuhkan cermin registri.', mirrorsHelper2: 'Untuk maklumat lanjut, lihat dokumen rasmi.', registries: 'Pendaftaran tidak selamat', ipv6Helper: @@ -1837,7 +1845,6 @@ const message = { stopHelper: 'Operasi ini akan memaksa menghentikan pelaksanaan tugas semasa. Teruskan?', log: 'Log sandaran', logHelper: 'Log sistem sandaran', - ogHelper1: '1. Log Sistem 1Panel ', logHelper2: '2. Log log masuk SSH pelayan ', logHelper3: '3. Semua log laman web ', containerCheckBox: 'Dalam kontena (tidak perlu masukkan arahan kontena)', @@ -1915,7 +1922,6 @@ const message = { perNMinute: 'Setiap N minit', perNSecond: 'Setiap N saat', day: 'hari', - dayUnit: 'h', monday: 'Isnin', tuesday: 'Selasa', wednesday: 'Rabu', @@ -2056,7 +2062,6 @@ const message = { connTestFailed: 'Sambungan tidak tersedia, sila semak maklumat sambungan.', host: 'Hos | Hos-hos', createConn: 'Sambungan baru', - manageGroup: 'Urus kumpulan', noHost: 'Tiada hos', groupChange: 'Tukar kumpulan', expand: 'Kembangkan semua', @@ -2311,6 +2316,7 @@ const message = { nodes: 'nod', commands: 'Perintah Pantas', opsReport: 'Laporan Operasi', + ops_report: 'Laporan Operasi', users: 'Pengurusan pengguna', roles: 'Peranan', auth: 'Pengesahan log masuk', @@ -2331,10 +2337,6 @@ const message = { fileDirNum: '{0} direktori, {1} fail,', currentDir: 'Direktori Semasa', dir: 'Folder', - upload: 'Muat naik', - uploadFile: 'Muat naik fail', - uploadDirectory: 'Muat naik direktori', - download: 'Muat turun', fileName: 'Nama fail', search: 'Cari', mode: 'Kebenaran', @@ -2350,7 +2352,6 @@ const message = { role: 'Kebenaran', info: 'Atribut', linkFile: 'Pautan lembut', - batchoperation: 'Operasi kelompok', shareList: 'Senarai kongsi', fileTools: 'Alat fail', aiSearchHitLines: 'Baris padanan', @@ -2507,42 +2508,42 @@ const message = { 'dipilih', copyDir: 'Salin', shareFile: 'Kongsi fail', - shareExpire: 'Expires in', - shareExpire1h: '1 hour', - shareExpire6h: '6 hours', - shareExpire24h: '24 hours', - shareExpire3d: '3 days', - shareExpire7d: '7 days', - sharePassword: 'Password', - sharePasswordPlaceholder: 'Leave empty for no password', - shareMaxDownloads: 'Max downloads', - shareMaxDownloadsHint: '0 means unlimited', - shareGenerate: 'Create link', - shareRegenerate: 'Share again', - shareClose: 'Close', + shareExpire: 'Tempoh sah', + shareExpire1h: '1 jam', + shareExpire6h: '6 jam', + shareExpire24h: '24 jam', + shareExpire3d: '3 hari', + shareExpire7d: '7 hari', + sharePassword: 'Kata laluan', + sharePasswordPlaceholder: 'Biarkan kosong jika tanpa kata laluan', + shareMaxDownloads: 'Muat turun maksimum', + shareMaxDownloadsHint: '0 bermakna tanpa had', + shareGenerate: 'Cipta pautan', + shareRegenerate: 'Kongsi semula', + shareClose: 'Tutup', shareCancel: 'Batalkan perkongsian', shareCancelConfirm: 'Adakah anda pasti mahu membatalkan perkongsian fail ini?', - shareDetail: 'Details', - shareCopyLink: 'Copy link', - shareLinkLabel: 'Share link', - shareQrCode: 'QR code', - shareQrDialogTitle: 'Share link QR code', - shareQrDialogHelper: 'Scan this QR code with your mobile device', - shareSaveImage: 'Save image', - shareOpenImage: 'Open image', - shareExtractFile: 'Extract file', - shareDownloadingHint: 'Preparing your file, download will begin shortly.', - shareInvalid: 'Invalid or expired share link', - shareDownloadFailed: 'Download failed, please try again later', - sharePasswordRequired: 'Password', - sharePasswordRequiredInput: 'Please enter the share password', - sharePasswordLengthHint: 'Share password length must be 4-256 characters', - shareDownloadPasswordTip: 'This link is password-protected. Enter the password before downloading.', + shareDetail: 'Butiran', + shareCopyLink: 'Salin pautan', + shareLinkLabel: 'Pautan perkongsian', + shareQrCode: 'Kod QR', + shareQrDialogTitle: 'Kod QR pautan perkongsian', + shareQrDialogHelper: 'Imbas kod QR ini dengan peranti mudah alih anda', + shareSaveImage: 'Simpan imej', + shareOpenImage: 'Buka imej', + shareExtractFile: 'Dapatkan fail', + shareDownloadingHint: 'Fail sedang disediakan. Muat turun akan bermula sebentar lagi.', + shareInvalid: 'Pautan perkongsian tidak sah atau telah tamat tempoh', + shareDownloadFailed: 'Muat turun gagal. Cuba lagi kemudian', + sharePasswordRequired: 'Kata laluan akses', + sharePasswordRequiredInput: 'Masukkan kata laluan perkongsian', + sharePasswordLengthHint: 'Panjang kata laluan perkongsian mestilah 4-256 aksara', + shareDownloadPasswordTip: 'Pautan ini dilindungi kata laluan. Masukkan kata laluan sebelum memuat turun.', shareRiskAlert: - 'Shared links may carry security risks. Only share with trusted people and avoid exposing sensitive information.', + 'Pautan perkongsian mungkin membawa risiko keselamatan. Kongsi hanya dengan orang yang dipercayai dan elakkan pendedahan maklumat sensitif.', sharePasswordSeparate: - 'A password is set. Share it securely. Recipients must add &password=... to the URL or use a client that can pass the password query parameter.', - shareExpiresAt: 'Expires at', + 'Kata laluan telah ditetapkan. Kongsikannya dengan selamat. Penerima mesti menambah &password=... pada URL atau menggunakan klien yang boleh menghantar parameter pertanyaan kata laluan.', + shareExpiresAt: 'Tamat tempoh pada', paste: 'Tampal', changeOwner: 'Ubah suai pengguna dan kumpulan pengguna', containSub: 'Guna perubahan kebenaran secara rekursif', @@ -2663,7 +2664,7 @@ const message = { enable: 'Aktifkan Mula Automatik', disable: 'Nyahaktif Mula Automatik', sshAlert: - 'Data senarai disusun berdasarkan tarikh log masuk. Menukar zon waktu atau melakukan operasi lain boleh menyebabkan penyimpangan dalam tarikh log log masuk.', + 'Data senarai disusun berdasarkan tarikh log masuk. Menukar zon waktu atau melakukan operasi lain boleh menyebabkan penyimpangan dalam tarikh log masuk.', sshAlert2: 'Anda boleh menggunakan "Fail2ban" di "Kotak Alat" untuk menyekat alamat IP yang cuba menyerang secara kasar, dan ini akan meningkatkan keselamatan hos.', sshOperate: 'Operasi "{0}" pada perkhidmatan SSH akan dilaksanakan. Adakah anda mahu meneruskan?', @@ -2841,7 +2842,6 @@ const message = { systemIPWarning: 'Nod semasa belum mempunyai alamat akses lalai yang dikonfigurasi. Sila pergi ke tetapan panel untuk mengkonfigurasinya!', systemIPWarning1: 'Alamat pelayan semasa ditetapkan kepada {0}, dan pengalihan cepat tidak mungkin!', - defaultNetwork: 'Kad rangkaian', syncTime: 'Waktu Pelayan', timeZone: 'Zon Waktu', timeZoneChangeHelper: @@ -2890,7 +2890,7 @@ const message = { codeWarning: 'Format kod kebenaran semasa tidak betul, sila sahkan semula!', code: 'Kod Auth', codeHelper: - 'Sila klik butang "Peroleh", kemudian log masuk ke OneDrive dan salin kandungan selepas "code" dalam pautan yang telah diarahkan semula. Tampalkan kandungan tersebut ke dalam kotak input ini. Untuk arahan spesifik, sila rujuk dokumentasi rasmi.', + 'Klik butang "Peroleh", kemudian log masuk ke {0} dan salin kandungan selepas "code" dalam pautan ubah hala. Tampalkannya ke dalam kotak input ini. Untuk arahan khusus, rujuk dokumentasi rasmi.', googleHelper: 'Sila buat aplikasi Google dan dapatkan maklumat klien terlebih dahulu, isi borang dan klik butang dapatkan. Untuk operasi khusus, sila rujuk dokumentasi rasmi.', loadCode: 'Peroleh', @@ -3124,7 +3124,6 @@ const message = { compress: 'Cipta fail snapshot', upload: 'Muat naik fail snapshot', recoverDetail: 'Butiran pemulihan', - recover: 'Pulihkan', lastRecoverAt: 'Waktu pemulihan terakhir', lastRollbackAt: 'Waktu pemulangan terakhir', reDownload: 'Muat turun semula fail sandaran', @@ -3160,7 +3159,7 @@ const message = { backupCopiesRule: 'Sila simpan sekurang-kurangnya 3 rekod sandaran naik taraf', release: 'Log Kemaskini Versi', releaseHelper: - 'Pengambilan log kemaskini untuk persekitaran semasa mengalami异常. Anda boleh menyemak dokumentasi rasmi secara manual.', + 'Log kemas kini untuk persekitaran semasa gagal diperoleh. Anda boleh menyemak dokumentasi rasmi secara manual.', project: 'GitHub', issue: 'Isu', doc: 'Dokumentasi rasmi', @@ -3207,8 +3206,6 @@ const message = { upgrading: 'Sedang naik taraf, sila tunggu...', versionHelper: 'Peraturan nama: [versi utama].[versi fungsi].[versi pembaikan], seperti contoh berikut:', upgradeCheck: 'Semak kemas kini', - panelSSLHelper: - 'Selepas pembaharuan automatik SSL panel, anda perlu mulakan semula servis 1Panel secara manual.', }, license: { offLine: 'Versi Luar Talian', @@ -3235,9 +3232,8 @@ const message = { authorizedUser: 'Pengguna yang Dibenarkan', lostHelper: 'Lesen telah mencapai had percubaan semula. Jalankan penyegerakan secara manual untuk memastikan ciri Edisi Komersial terus berfungsi dengan baik. butiran: ', - disableHelper: - 'Pengesahan penyegerakan lesen gagal. Jalankan penyegerakan secara manual untuk memastikan ciri Edisi Komersial berfungsi dengan baik. butiran: ', quickUpdate: 'Kemas Kini Pantas', + import: 'Import', power: 'Kebenaran', unbindHelper: 'Semua Tetapan berkaitan Edisi Komersial akan dibersihkan selepas nyahikat. Adakah anda mahu meneruskan?', @@ -3297,6 +3293,7 @@ const message = { fileExchange: 'Naik taraf ke Edisi Komersial untuk memindahkan fail dengan pantas antara pelayan.', app: 'Naik taraf ke Edisi Komersial untuk melihat maklumat perkhidmatan dan pemantauan anomali dalam aplikasi mudah alih.', cluster: 'Naik taraf ke Edisi Komersial untuk mengurus kelompok utama-replika MySQL/Postgres/Redis.', + vllm: 'Naik taraf ke Edisi Komersial untuk mengurus perkhidmatan vLLM secara berpusat dalam 1Panel, termasuk penggunaan, konfigurasi, operasi kitar hayat dan penjejakan tugas.', 'model-downloader': 'Naik taraf kepada edisi komersial untuk mencari, memuat turun dan mengurus fail model tempatan daripada HuggingFace, ModelScope atau cermin serasi, dengan direktori model dan tugasan muat turun berpusat.', exceptionalHelper: @@ -3505,7 +3502,6 @@ const message = { ftpHelper: 'Selepas membuat laman web, akaun FTP akan dibuat dan direktori FTP akan memautkan ke direktori laman web.', remark: 'Catatan', - manageGroup: 'Urus kumpulan', groupSetting: 'Pengurusan Kumpulan', createGroup: 'Cipta kumpulan', appNew: 'Aplikasi Baru', @@ -3569,7 +3565,6 @@ const message = { nginxPer: 'Penalaan Prestasi Nginx', neverExpire: 'Tidak Pernah Luput', setDefault: 'Tetapkan sebagai lalai', - default: 'Lalai', deleteHelper: 'Status aplikasi berkaitan tidak normal, sila semak', toApp: 'Pergi ke senarai dipasang', cycle: 'Kitaran', @@ -3684,7 +3679,6 @@ const message = { proxyHelper1: 'Semasa mengakses direktori ini, kandungan URL sasaran akan dikembalikan dan dipaparkan.', proxyPassHelper: 'URL sasaran mesti sah dan boleh diakses.', proxyHostHelper: 'Hantar nama domain dalam header permintaan ke pelayan proksi.', - replacementHelper: 'Hingga 5 penggantian boleh ditambah, sila kosongkan jika tiada penggantian diperlukan.', modifier: 'Peraturan padanan', modifierHelper: 'Contoh: "=" adalah padanan tepat, "~" adalah padanan biasa, "^~" memadankan permulaan laluan, dan sebagainya.', @@ -3794,7 +3788,6 @@ const message = { subsite: 'Sublaman', subsiteHelper: 'Sublaman boleh memilih direktori laman web PHP atau statik yang sedia ada sebagai direktori akar.', - parentWebsite: 'Laman Web Induk', deleteSubsite: 'Untuk memadam laman web semasa, anda mesti memadam sublaman {0} terlebih dahulu.', loadBalance: 'Pengimbangan Beban', server: 'Nod', @@ -3825,7 +3818,6 @@ const message = { cacheExpire: 'Masa Tamat Cache', shareCacheHelper: '1M memori boleh menyimpan kira-kira 8000 objek cache.', cacheLimitHelper: 'Melebihi had akan menghapus cache lama secara automatik.', - cacheExpireHelper: 'Cache yang tidak dipenuhi dalam masa tamat akan dihapuskan.', realIP: 'IP Sebenar', ipFrom: 'Sumber IP', ipFromHelper: @@ -3888,8 +3880,6 @@ const message = { syncHtmlHelper: 'Segerakkan ke PHP dan laman web statik', wafValueHelper: 'Nilai', parentWbeiste: 'Laman induk', - shareCahe: 'Saiz memori kiraan cache', - shareCaheHelper: 'Kira-kira 8000 objek cache boleh disimpan bagi setiap 1M memori', cacheExpireJHelper: 'Cache akan dipadam jika tiada hit selepas tamat tempoh', }, php: { @@ -3976,8 +3966,8 @@ const message = { 'Skrip yang dilaksanakan sebelum penyusunan, biasanya untuk memuat turun sumber kod modul, memasang kebergantungan, dll.', buildHelper: 'Modul dinamik dimuatkan melalui konfigurasi selepas dibina; modul statik tetap membina semula OpenResty.', - defaultHttps: 'HTTPS Anti-tampering', - defaultHttpsHelper1: 'Mengaktifkan ini dapat menyelesaikan masalah tampering HTTPS.', + defaultHttps: 'Anti-usikan HTTPS', + defaultHttpsHelper1: 'Mengaktifkan pilihan ini boleh menyelesaikan masalah usikan HTTPS.', sslRejectHandshake: 'Tolak jabat tangan SSL lalai', sslRejectHandshakeHelper: 'Mengaktifkan ini boleh mengelakkan kebocoran sijil, menetapkan laman web lalai akan membatalkan tetapan ini', @@ -4191,7 +4181,7 @@ const message = { 'Semakin banyak sambungan, semakin tinggi penggunaan CPU semasa membuat imej. Sambungan boleh dipasang selepas persekitaran dibuat.', openrestyWarn: 'PHP perlu dinaik taraf kepada OpenResty versi 1.21.4.1 atau lebih tinggi untuk digunakan', toupgrade: 'Naik Taraf', - edit: 'Edit runtime', + edit: 'Sunting persekitaran masa jalan', extendHelper: 'Sambungan yang tidak disenaraikan boleh dimasukkan dan dipilih secara manual. Sebagai contoh, masukkan "sockets" dan pilih pilihan pertama dari senarai juntai bawah untuk melihat senarai sambungan.', rebuildHelper: 'Selepas mengedit sambungan, anda perlu membina semula aplikasi PHP untuk ia berkesan', @@ -4262,42 +4252,41 @@ const message = { environment: 'Pembolehubah persekitaran', }, process: { - pid: 'Process ID', - ppid: 'Parent PID', - numThreads: 'Threads', - memory: 'Memory', - diskRead: 'Disk read', - diskWrite: 'Disk write', - netSent: 'uplink', - netRecv: 'downstream', - numConnections: 'Connections', - startTime: 'Start time', - state: 'State', - running: 'Running', - sleep: 'sleep', - stop: 'stop', - idle: 'idle', - zombie: 'zombie process', - wait: 'waiting', - lock: 'lock', - blocked: 'blocked', - cmdLine: 'Start command', - basic: 'Basic', - mem: 'Memory', - openFiles: 'Open files', - env: 'Environments', - noenv: 'None', - net: 'Network connections', - laddr: 'Source address/port', - raddr: 'Destination address/port', - stopProcess: 'End', - viewDetails: 'Details', - stopProcessWarn: 'Are you sure you want to end this process (PID:{0})?', + pid: 'ID Proses', + ppid: 'PID Induk', + numThreads: 'Thread', + memory: 'Memori', + diskRead: 'Bacaan cakera', + diskWrite: 'Tulisan cakera', + netSent: 'Muat naik', + netRecv: 'Muat turun', + numConnections: 'Sambungan', + startTime: 'Masa mula', + running: 'Berjalan', + sleep: 'Tidur', + stop: 'Berhenti', + idle: 'Melahu', + zombie: 'Proses zombi', + wait: 'Menunggu', + lock: 'Dikunci', + blocked: 'Disekat', + cmdLine: 'Perintah mula', + basic: 'Asas', + mem: 'Memori', + openFiles: 'Fail terbuka', + env: 'Pemboleh ubah persekitaran', + noenv: 'Tiada', + net: 'Sambungan rangkaian', + laddr: 'Alamat/port sumber', + raddr: 'Alamat/port destinasi', + stopProcess: 'Tamatkan', + viewDetails: 'Butiran', + stopProcessWarn: 'Adakah anda pasti mahu menamatkan proses ini (PID:{0})?', kill: 'Hentikan Proses', killNow: 'Hentikan Sekarang', killHelper: 'Menghentikan proses {0} mungkin menyebabkan beberapa program tidak berfungsi dengan normal. Teruskan?', - processName: 'Process name', + processName: 'Nama proses', }, tool: { supervisor: { @@ -4333,7 +4322,7 @@ const message = { ERROR: 'Ralat', statusCode: 'Kod status', manage: 'Pengurusan', - autoRestart: 'Auto Restart', + autoRestart: 'Mulakan Semula Automatik', EXITED: 'Telah keluar', autoRestartHelper: 'Sama ada untuk memulakan semula program secara automatik selepas ia tamat secara luar jangka', @@ -4357,7 +4346,7 @@ const message = { management: 'Pengurusan cakera', partition: 'Sekatan', unmount: 'Nyahlekap', - unmountHelper: 'Selepas nyahlekap, data mungkin tidak boleh diakses sementara. Teruskan?', + unmountHelper: 'Nyahlekap partition {0}?', mount: 'Lekap', partitionAlert: 'Operasi ini memformat seluruh cakera. Pastikan data telah dibackup!', mountPoint: 'Titik lekap', @@ -4489,8 +4478,10 @@ const message = { scorePanelHTTPSDisabled: 'Panel HTTPS dilumpuhkan', scoreSSHRootLogin: 'Log masuk root SSH dibenarkan', scoreSSHPasswordAuth: 'Kata laluan SSH didayakan tanpa pengesahan kunci', + scoreSSLExpired: 'Sijil {0} telah tamat tempoh', scoreSSLHigh: 'Sijil {0} tamat tempoh dalam {1} hari', scoreSSLMedium: 'Sijil {0} tamat tempoh dalam {1} hari', + scoreWebsiteExpired: 'Laman web {0} telah tamat tempoh', scoreWebsiteExpire: 'Laman web {0} tamat tempoh dalam {1} hari', scoreWebsiteHTTP: '{0} tidak menggunakan HTTPS', scoreWebsiteStopped: 'Status {0} tidak normal', @@ -4537,6 +4528,7 @@ const message = { panelLogin: 'Log Masuk Panel', sshLogin: 'Log Masuk SSH', failedRecord: 'Rekod Gagal', + expired: 'Tamat tempoh', expiredDays: 'Tamat tempoh {0} hari lalu', remainingDays: '{0} · Baki {1} hari', enabled: 'Didayakan', @@ -4590,7 +4582,7 @@ const message = { sshSecurityItems: 'Item Keselamatan SSH', loginSecurityHealthStatus: 'Status Kesihatan Keselamatan Log Masuk', adjustSSHSecurity: 'Laraskan Keselamatan SSH', - viewLoginLogs: 'Lihat Log Log Masuk', + viewLoginLogs: 'Lihat Log Masuk', riskLevel: 'Tahap Risiko', goConfig: 'Konfigurasi', viewMore: 'Lihat Lagi', @@ -4617,6 +4609,7 @@ const message = { 'IP dibenarkan atau domain terikat dikonfigurasi untuk mengehadkan sumber akses panel', accessRestrictionRiskDesc: 'IP dibenarkan dan domain terikat tidak dikonfigurasi atau akses tidak terhad. Konfigurasikan sekurang-kurangnya satu', + mfa: 'MFA', mfaNormalDesc: 'MFA telah diaktifkan', mfaRiskDesc: 'MFA belum diaktifkan. Disyorkan untuk mengaktifkannya bagi meningkatkan keselamatan akaun', @@ -4806,9 +4799,9 @@ const message = { abnormalSites: 'Tapak Tidak Normal', count5xxSource: 'Bilangan berdasarkan permintaan 5xx', wafIntercept: 'Sekatan WAF', - highRiskHit: 'Hit Risiko Tinggi', websiteMonitorDisabledOrNoData: 'Pemantauan laman web dilumpuhkan atau tiada data pemantauan', wafDisabledOrNoData: 'WAF dilumpuhkan atau tiada data sekatan', + serviceEnabledButAbnormal: 'Didayakan tetapi berada dalam keadaan tidak normal', noWafData: 'Tiada data sekatan WAF', sourceIP: 'IP Sumber', hitCount: 'Jumlah Hit', @@ -4868,6 +4861,7 @@ const message = { successRate: 'Kadar Kejayaan', failedJobs: 'Tugas Gagal', recentRecoveryPoint: 'Titik Pemulihan Terkini', + disabledCronjobTasks: 'Tugas berjadual yang dilumpuhkan', remoteCoverage: 'Liputan Jauh', recent7Days: '7 Hari Terakhir', taskTypeStats: 'Statistik Jenis Tugas', @@ -4888,6 +4882,7 @@ const message = { cronjobReasonDisabled: '{0} tugas dilumpuhkan', cronjobReasonLocalOnlyBackup: '{0} tugas sandaran setempat sahaja', cronjobReasonNormal: 'Pelaksanaan tugas dan liputan sandaran normal', + riskLow: 'Risiko Rendah', viewFailedRecords: 'Lihat Tugas Gagal', viewCronjobTasks: 'Lihat Tugas Berjadual', checkBackupTasks: 'Semak Tugas Sandaran', @@ -4987,6 +4982,14 @@ const message = { authManage: 'Pengurusan pengesahan', auth: { providerNavigation: 'Pembekal pengesahan', + defaultNode: 'Nod lalai', + defaultNodePlaceholder: 'Pilih nod', + defaultNodeHelper: 'Untuk pengguna baharu sahaja.', + defaultNodeRequired: 'Pilih nod lalai yang sah.', + nodesLoadFailed: 'Gagal memuatkan nod. Cuba lagi sebelum memilih nod lalai.', + nodeHandling: 'Pengendalian nod', + assignDefaultNode: 'Tetapkan nod lalai: {node}', + keepExistingNode: 'Kekalkan kebenaran nod sedia ada', providers: { ldap: 'AD/LDAP', passkey: 'Passkey', @@ -5014,7 +5017,411 @@ const message = { planned: 'Terancang', plannedTitle: 'Tetapan pengesahan {0}', plannedDesc: 'Pembekal pengesahan ini telah dirancang dan belum tersedia lagi.', + oidc: { + accessMode: 'Mod sambungan', + accessModeDesc: 'Gunakan Discovery standard setiap kali pembekal identiti menyokongnya.', + actionCreate: 'Buat pengguna', + actionKeepName: 'Kekalkan nama pengguna semasa', + actionPending: 'Menunggu keputusan', + actionReject: 'Tolak log masuk', + actionUpdate: 'Kemas kini maklumat identiti', + advanced: 'Tetapan lanjutan', + advancedDesc: 'Kekalkan lalai selamat melainkan pembekal memerlukan pilihan keserasian.', + assignDefaultRole: 'Berikan peranan lalai: {role}', + authorizationEndpoint: 'Authorization Endpoint', + authorizationEndpointInvalid: 'Masukkan Authorization Endpoint yang sah.', + authorizationFlow: 'Aliran kebenaran', + automatic: 'Automatik', + automaticPolicy: 'Dasar pengendalian automatik', + automaticPolicyDesc: 'Peraturan ini dikuatkuasakan oleh backend, bukan melalui suis pentadbir.', + basic: 'Tetapan asas', + basicDesc: 'Pilih mod pembekal, kemudian konfigurasikan klien dan panggil balik.', + browserTest: 'Ujian log masuk pelayar', + browserTestConflict: 'Identiti disahkan, tetapi nama pengguna bercanggah', + browserTestConflictHelper: + 'Nama pengguna yang dipetakan adalah milik identiti lain dan tidak akan dituntut.', + browserTestExpired: 'Ujian penyemak imbas tamat tempoh', + browserTestExpiredHelper: + 'Mulakan ujian penyemak imbas baharu dan lengkapkan kebenaran sebelum tamat tempoh.', + browserTestFailed: 'Ujian penyemak imbas gagal', + browserTestFailedHelper: + 'Pratonton identiti tidak dapat diselesaikan. Semak ralat backend yang telah diterjemahkan.', + browserTestIsolation: + 'Ini melakukan perjalanan pergi balik kebenaran sebenar tetapi tidak mencipta atau mengemas kini pengguna, menetapkan peranan atau mencipta sesi panel yang telah disahkan.', + browserTestPopupBlocked: + 'Benarkan pop timbul untuk tapak ini, kemudian mulakan ujian penyemak imbas semula.', + browserTestPopupClosed: 'Tetingkap kebenaran ditutup sebelum ujian selesai.', + browserTestSuccess: 'Pengesahan Provider berjaya', + browserTestSuccessHelper: 'Pemetaan identiti telah dipratonton tanpa menukar pengguna atau sesi.', + browserTestTitle: 'Log masuk ujian pelayar OIDC', + browserTestWaiting: 'Menunggu kebenaran Provider', + browserTestWaitingHelper: + 'Lengkapkan log masuk dalam tetingkap penyemak imbas baharu. Halaman ini akan dikemas kini secara automatik.', + callbackCopied: 'OIDC panggil balik URL disalin.', + callbackURL: 'Panggil balik URL', + callbackURLHelper: + 'Tambahkan URL ini pada senarai URL panggil balik yang dibenarkan untuk klien dalam penyedia identiti.', + cancelClearSecret: 'Batalkan pembersihan', + clearSecret: 'Kosongkan Client Secret', + clearSecretConfirm: 'Client Secret akan dialih keluar hanya selepas anda menyimpan. teruskan?', + clientAuthMethod: 'Kaedah pengesahan pelanggan', + clientAuthMethodHelper: + 'Pilih kaedah pengesahan yang dikonfigurasi untuk klien ini dalam penyedia identiti.', + clientAuthMethodRequired: 'Pilih kaedah pengesahan pelanggan.', + clientID: 'Client ID', + clientIDRequired: 'Masukkan Client ID.', + clientSecret: 'Client Secret', + clockSkew: 'Toleransi masa token', + clockSkewHelper: + 'Membenarkan sedikit perbezaan masa antara penyedia identiti dan 1Panel. Kekalkan nilai lalai 60 saat.', + clockSkewRequired: 'Masukkan toleransi masa token.', + compatibilityMode: 'Mod keserasian', + compatibilityModeHelper: + 'Gunakan hanya untuk Discovery yang tidak lengkap atau titik akhir yang ditulis semula. Pengesahan teras OIDC kekal didayakan.', + configurationFailedHelper: + 'Ujian itu gagal. Halaman hanya memaparkan ralat backend yang telah diterjemahkan.', + configurationFailedTag: 'Ujian gagal', + configurationHighRiskPassed: + 'Konfigurasi diluluskan, tetapi mengandungi pilihan keserasian berisiko tinggi.', + configurationHighRiskTag: 'Konfigurasi berisiko tinggi diluluskan', + configurationNotTested: 'Konfigurasi semasa belum diuji.', + configurationNotTestedTag: 'Tidak diuji', + configurationPassed: 'Konfigurasi semasa melepasi semakan keselamatan dan keupayaan.', + configurationPassedTag: 'Ujian lulus', + configurationStaleHelper: 'Konfigurasi telah diubah. Uji semula sebelum menyimpan.', + configurationStaleTag: 'Keputusan tamat tempoh', + configurationTestMeta: + 'Diuji pada {time}; selesai dalam {duration} ms. Respons mentah Provider tidak disimpan.', + configurationTestResult: 'Keputusan ujian konfigurasi', + configurationTestResultDesc: + 'Ini menyemak Discovery dan keupayaan sahaja; ia tidak menukar kod kebenaran atau membuktikan Client Secret. Gunakan log masuk ujian penyemak imbas untuk pengesahan hujung ke hujung.', + configurationTestSuccess: 'Ujian konfigurasi OIDC berjaya.', + configurationTesting: 'Menguji konfigurasi OIDC semasa…', + configurationTestingTag: 'Menguji', + configureSecret: 'Konfigurasikan rahsia', + conflictExistingRename: 'subject terikat mengembalikan name baharu yang telah diduduki', + conflictExistingRenameResult: + 'Simpan User.Name sedia ada dan benarkan pengguna terikat untuk log masuk', + conflictLDAP: 'Pengguna LDAP', + conflictLocal: 'Pengguna tempatan', + conflictNewAvailable: 'subject baharu dan name yang dipetakan tersedia', + conflictNewAvailableResult: 'Buat pengguna perusahaan dan tetapkan peranan lalai', + conflictNone: 'Tiada konflik', + conflictOIDC: 'Satu lagi identiti OIDC', + conflictOccupied: 'name yang dipetakan adalah milik tempatan, LDAP atau identiti OIDC yang lain', + conflictOccupiedResult: + 'Tolak identiti baharu; jangan sekali-kali mengikat atau bergabung secara automatik', + conflictType: 'Jenis konflik', + connectionSecurity: 'Keselamatan sambungan', + connectionSecurityDesc: 'Dasar TLS digunakan untuk permintaan Discovery, Token, JWKS dan UserInfo.', + connectionTest: 'Ujian sambungan dan konfigurasi', + connectionTestCompatibilityDesc: 'Sahkan titik akhir tersuai dan dasar keselamatan protokol.', + connectionTestStandardDesc: 'Titik akhir dan keupayaan ditemui secara automatik daripada Issuer.', + connectionTestTab: 'Ujian sambungan', + customCA: 'CA tersuai', + customCAHelper: 'Terpakai hanya pada sumber pengesahan ini dan tidak pernah ditulis pada log.', + customCARequired: 'Sediakan sijil tersuai CA.', + defaultRole: 'Peranan lalai', + defaultRoleHelper: + 'Ditugaskan hanya apabila pengguna pertama kali dicipta; log masuk seterusnya tidak mengubah peranan.', + defaultRolePlaceholder: 'Pilih peranan', + defaultRoleRequired: 'Pilih peranan lalai yang sah.', + disableAfterSave: 'OIDC akan dilumpuhkan selepas disimpan.', + disableConfirm: + 'Melumpuhkan OIDC serta-merta membatalkan akses untuk pengguna sumber ini. teruskan?', + disableDiscardConfirm: + 'Melumpuhkan OIDC ialah tindakan kecemasan: ia hanya menutup entri log masuk dan serta-merta membatalkan akses untuk pengguna sumber ini. Perubahan lain yang belum disimpan pada halaman ini, termasuk perubahan Client Secret, akan dibuang. teruskan?', + disableTitle: 'Lumpuhkan OIDC', + disabled: 'Dilumpuhkan', + discoveryAllowlist: 'Discovery ∩ senarai kebenaran keselamatan', + enable: 'Dayakan', + enableAfterSave: 'OIDC akan didayakan selepas simpanan berjaya.', + enabled: 'Didayakan', + endSessionEndpoint: 'End Session Endpoint', + endSessionEndpointHelper: + 'Disimpan untuk kegunaan masa hadapan; Log keluar yang dimulakan Provider tidak disertakan dalam keluaran ini.', + endSessionEndpointInvalid: 'Masukkan End Session Endpoint yang sah.', + endpointDiscoveryPlaceholder: 'Dipaparkan selepas ujian sambungan', + firstLogin: 'Log masuk pertama', + firstLoginPolicy: + 'Buat pengguna perusahaan tempatan dan tetapkan peranan lalai yang dikonfigurasikan.', + fixedAuthorizationCode: 'Authorization Code Flow', + fixedNoTokenPersistence: 'Tokens, Claims dan verifier tidak pernah berterusan', + fixedSecurityPolicy: 'Sentiasa dikuatkuasakan; tiada konfigurasi diperlukan', + fixedStateNonce: 'state dan nonce sekali', + fixedTokenValidation: 'Tandatangan ID Token dan pengesahan Claims', + highRiskSaveConfirm: + 'Konfigurasi yang didayakan ini mengandungi pilihan keserasian berisiko tinggi. Sahkan bahawa persekitaran terpencil memerlukannya.', + highRiskTitle: 'Konfigurasi OIDC berisiko tinggi', + hs256Compatibility: 'HS256 (keserasian)', + hs256KeyHelper: + 'HS256 sentiasa menggunakan Client Secret sumber ini dan tidak menerima kunci tandatangan yang berasingan.', + hs256Warning: + 'HS256 menggunakan rahsia simetri yang dikongsi untuk tandatangan ID Token. Gunakannya hanya apabila Provider tidak boleh menggunakan algoritma asimetri.', + identityBindingPolicy: + 'Identiti ditetapkan kepada AuthSourceID + issuer + subject. Nama pengguna yang sepadan tidak pernah menuntut akaun lain.', + identityMissing: 'Identiti tidak aktif', + issuer: 'Issuer URL', + issuerHelper: + 'Nilai iss ID Token dan Discovery issuer mesti sepadan dengan nilai ini dengan tepat.', + issuerInvalid: 'Masukkan HTTP atau HTTPS Issuer URL yang sah tanpa pertanyaan atau serpihan.', + issuerRequired: 'Masukkan Issuer URL.', + jwksRotation: 'Putaran JWKS automatik', + jwksURI: 'JWKS URI', + jwksURIHelper: 'Diperlukan untuk tandatangan asimetri apabila sumber utama ialah JWKS.', + jwksURIInvalid: 'Masukkan JWKS URI yang sah untuk sumber kunci tandatangan yang dipilih.', + keepExistingRole: 'Kekalkan peranan sedia ada dan kebenaran setempat', + localSecurityData: 'Data keselamatan tempatan', + localSecurityDataPolicy: + 'Jangan sekali-kali menulis ganti peranan, MFA, API Keys, Passkeys atau kebenaran setempat.', + localCredentialsManaged: + 'Nama pengguna dan kata laluan tempatan diuruskan oleh OIDC dan tidak boleh diedit di sini. Peranan, kebenaran, MFA, API Keys dan Passkeys kekal setempat.', + localUserFields: 'Medan pengguna tempatan', + localUserFieldsDesc: + 'Keluaran pertama hanya memetakan User.Name dan tidak menggunakan ungkapan pemetaan JSON.', + loginWith: 'Log masuk dengan {provider}', + manualEndpoints: 'Titik akhir tersuai', + manualEndpointsDesc: + 'Gunakan hanya apabila Discovery tidak lengkap atau get laluan huluan menulis semula titik akhir.', + mappingResult: 'Hasil pemetaan', + mode: 'Mod sambungan', + modeRequired: 'Pilih mod sambungan.', + nameClaim: 'Claim nama pengguna', + nameClaimHelper: 'Masukkan medan yang mengandungi nama pengguna, seperti preferred_username.', + nameClaimRequired: 'Masukkan Claim nama pengguna.', + nameConflict: 'Nama dasar konflik', + panelURL: '1Panel awam URL', + panelURLHTTPWarning: + 'HTTP tidak melindungi respons kebenaran. Gunakannya hanya dalam persekitaran peribadi terpencil yang diterima oleh Provider.', + panelURLHelper: + 'Masukkan alamat yang digunakan untuk mengakses 1Panel. Alamat ini digunakan untuk menjana URL panggil balik.', + panelURLInvalid: 'Masukkan asal yang mengandungi hanya skema, hos dan port pilihan.', + panelURLRequired: 'Masukkan 1Panel awam URL.', + pkceDisabled: 'Dilumpuhkan (keserasian sahaja)', + pkceDisabledWarning: + 'Melumpuhkan PKCE mengurangkan perlindungan terhadap pemintasan kod kebenaran.', + pkceHelper: 'Lebih suka S256. Kaedah cabaran plain tidak pernah ditawarkan.', + pkceS256: 'S256 (disyorkan)', + plannedHandling: 'Pengendalian terancang', + privateNetworkIdP: 'IdP rangkaian persendirian', + privateNetworkIdPHelper: + 'Membenarkan alamat peribadi secara eksplisit; metadata, gelung balik, pautan setempat, ubah hala dan penjilidan semula DNS kekal disekat.', + privateNetworkWarning: 'Akses rangkaian peribadi didayakan untuk sumber pengesahan ini.', + protocolCompatibility: 'Keserasian protokol', + protocolCompatibilityDesc: 'Pengesahan tandatangan ID Token tidak boleh dilumpuhkan.', + providerAndClient: 'Provider dan pelanggan', + providerAndClientDesc: + 'Client Secret hanya boleh diganti atau dibersihkan dan tidak pernah dikembalikan oleh halaman.', + providerCapabilities: 'Keupayaan Provider', + recentTestSuccess: 'Ujian terakhir berjaya: {0}', + recommended: 'Disyorkan', + rejectPlain: 'plain ditolak', + replaceSecret: 'Gantikan rahsia', + requestAndClaims: 'Permintaan dan sifat', + requestAndClaimsDesc: + 'Konfigurasikan skop kebenaran, pelengkap maklumat pengguna dan parameter permintaan.', + requestTimeout: 'Tamat masa permintaan', + requestTimeoutRequired: 'Masukkan tamat masa permintaan.', + restore: 'Pulihkan', + restored: 'Tetapan OIDC yang terakhir disimpan telah dipulihkan.', + result: 'Hasilnya', + rolesLoadFailed: 'Peranan tidak dapat dimuatkan. Cuba semula sebelum memilih peranan lalai.', + roleHandling: 'Pengendalian peranan', + scenario: 'Senario', + scopes: 'Skop kebenaran', + scopesHelper: 'Mesti mengandungi openid. Pisahkan berbilang skop dengan ruang.', + scopesRequired: 'Scopes mesti termasuk openid.', + seconds: 'detik', + secretClearHelper: + 'Selepas mengosongkan, Client Secret baharu diperlukan sebelum OIDC boleh didayakan semula.', + secretConfigured: 'Dikonfigurasikan', + secretNotConfigured: 'Tidak dikonfigurasikan', + secretPlaceholder: 'Masukkan Client Secret baharu', + secretReplaceHelper: + 'Rahsia baharu akan menggantikan nilai yang disimpan apabila anda menyimpan. Kemas kini juga Client Secret pada Provider OIDC.', + secretRequiredHelper: 'Konfigurasikan Client Secret sebelum mendayakan OIDC.', + secretRequiredToEnable: 'Konfigurasikan Client Secret sebelum mendayakan OIDC.', + secretSavedHelper: + 'Disimpan dalam bentuk disulitkan. Biarkan kosong untuk mengekalkan rahsia klien semasa.', + secretWaiting: 'Menunggu input', + secretWillClear: 'Akan dibersihkan', + secretWillReplace: 'Akan diganti', + signingAlgorithm: 'Algoritma tandatangan ID Token', + signingAlgorithmHelper: 'Hanya algoritma dalam senarai dibenarkan keselamatan backend tersedia.', + signingKey: 'Kunci tandatangan', + signingKeyClientSecret: 'Client Secret (HS256 sahaja)', + signingKeyJWKS: 'JWKS URI dengan putaran automatik', + signingKeySource: 'Sumber kunci tandatangan', + signingKeySourceHelper: 'Lebih suka JWKS. Kunci awam statik tidak boleh berputar secara automatik.', + signingKeyStatic: 'Kunci awam JWK atau PEM statik', + standardDiscovery: 'Discovery OIDC standard', + standardDiscoveryDesc: + '1Panel menemui titik akhir dan keupayaan dan tidak menyimpan dokumen mentah.', + standardMode: 'Mod standard', + standardModeHelper: + 'Temui titik akhir, keupayaan menandatangani dan sokongan PKCE daripada Issuer.', + standardProtocolPolicy: 'Dasar protokol standard', + standardProtocolPolicyDesc: + 'Keupayaan menandatangani dirundingkan secara automatik; tiada kunci tandatangan dimasukkan di sini.', + staticSigningKey: 'Kunci awam tandatangan statik', + staticSigningKeyHelper: + 'Hanya bahan kunci awam diterima. Putar secara manual apabila kunci Provider berubah.', + staticSigningKeyPlaceholder: 'Tampal kunci awam JWK, JWKS JSON atau PEM', + staticSigningKeyRequired: 'Sediakan kunci awam tandatangan statik.', + staticSigningKeyWarning: + 'Kunci tandatangan statik tidak boleh berputar secara automatik; kemas kini sebelum Provider memutar kunci.', + settingLoadFailed: 'Tetapan OIDC tidak dapat dimuatkan', + settingLoadFailedHelper: + 'Borang dikunci untuk mengelakkan menyimpan konfigurasi lalai kosong pada tetapan semasa. Cuba semula selepas sambungan pulih.', + subsequentLogin: 'Log masuk seterusnya', + subsequentLoginPolicy: + 'Cari pengikatan dengan subject dan kemas kini hanya User.Name apabila nama baharu tersedia.', + testBeforeBrowserTest: 'Uji konfigurasi semasa sebelum memulakan ujian log masuk penyemak imbas.', + testBeforeEnable: 'Uji konfigurasi semasa sebelum menyimpan perubahan konfigurasi.', + testConfiguration: 'Uji konfigurasi', + testDiscovery: 'Uji Discovery', + tlsCustomCA: 'HTTPS · Sijil CA tersuai', + tlsPrivateHTTP: 'HTTP · Rangkaian peribadi sahaja (berbahaya)', + tlsPrivateHTTPWarning: + 'HTTP tidak menyediakan penyulitan pengangkutan dan terhad kepada sasaran peribadi yang dibenarkan secara eksplisit.', + tlsSkipVerify: 'HTTPS · Langkau pengesahan sijil (berbahaya)', + tlsSystem: 'HTTPS · Pengesahan sijil sistem (disyorkan)', + tokenEndpoint: 'Token Endpoint', + tokenEndpointInvalid: 'Masukkan Token Endpoint yang sah.', + transportSecurity: 'Keselamatan pengangkutan', + transportSecurityHelper: + 'Lebih suka HTTPS. HTTP persendirian juga memerlukan akses private-network yang jelas.', + unsavedChanges: 'Terdapat perubahan OIDC yang belum disimpan.', + usedClaim: 'Claim digunakan', + userInfoEndpoint: 'UserInfo Endpoint', + userInfoEndpointHelper: + 'Apabila medan nama pengguna tiada, sistem melengkapkannya daripada endpoint ini. Biarkan kosong untuk tidak melengkapkannya.', + userInfoEndpointInvalid: 'Masukkan UserInfo Endpoint yang sah.', + userMapping: 'Tetapan pengguna', + userMappingDesc: + 'Konfigurasikan pemetaan nama pengguna OIDC serta nod dan peranan lalai untuk mencipta pengguna pada log masuk pertama.', + }, + saml2: { + actionCreate: 'Buat pengguna', + actionPending: 'Menunggu keputusan', + actionReject: 'Tolak log masuk', + actionReuse: 'Gunakan pengguna terikat', + assignDefaultRole: 'Berikan peranan lalai: {role}', + basic: 'Tetapan asas', + basicDesc: 'Konfigurasikan pilihan umum yang diperlukan oleh kebanyakan penyedia SAML2 standard.', + browserTest: 'Uji log masuk', + browserTestConflict: 'Identiti disahkan, tetapi nama pengguna bercanggah', + browserTestConflictHelper: + 'Nama pengguna yang dipetakan adalah milik identiti lain dan tidak akan dituntut.', + browserTestExpired: 'Ujian penyemak imbas tamat tempoh', + browserTestExpiredHelper: + 'Mulakan ujian penyemak imbas baharu dan lengkapkan kebenaran sebelum tamat tempoh.', + browserTestFailed: 'Ujian penyemak imbas gagal', + browserTestFailedHelper: + 'Pratonton identiti tidak dapat diselesaikan. Semak ralat backend yang telah diterjemahkan.', + browserTestIsolation: + 'Ini melakukan perjalanan pergi balik kebenaran sebenar tetapi tidak mencipta atau mengemas kini pengguna, menetapkan peranan atau mencipta sesi panel yang telah disahkan.', + browserTestPopupBlocked: + 'Benarkan pop timbul untuk tapak ini, kemudian mulakan ujian penyemak imbas semula.', + browserTestPopupClosed: 'Tetingkap kebenaran ditutup sebelum ujian selesai.', + browserTestSuccess: 'Pengesahan Provider berjaya', + browserTestSuccessHelper: 'Pemetaan identiti telah dipratonton tanpa menukar pengguna atau sesi.', + browserTestTitle: 'Log masuk ujian pelayar SAML2', + browserTestWaiting: 'Menunggu kebenaran Provider', + browserTestWaitingHelper: + 'Lengkapkan log masuk dalam tetingkap penyemak imbas baharu. Halaman ini akan dikemas kini secara automatik.', + certificateFileInvalid: 'Pilih fail sijil PEM, CRT atau CER yang sah.', + configured: 'Dikonfigurasi', + configurationFailedHelper: + 'Ujian itu gagal. Halaman hanya memaparkan ralat backend yang telah diterjemahkan.', + configurationNotTested: 'Konfigurasi semasa belum diuji.', + configurationPassed: 'Konfigurasi semasa melepasi semakan keselamatan dan keupayaan.', + configurationStaleHelper: 'Tetapan sensitif pengesahan ditukar. Uji draf semasa sekali lagi.', + configurationTestSuccess: 'Ujian konfigurasi SAML2 berjaya.', + configurationTesting: 'Menguji konfigurasi SAML2 semasa…', + conflictLDAP: 'Pengguna LDAP', + conflictLocal: 'Pengguna tempatan', + conflictNone: 'Tiada konflik', + conflictOIDC: 'Satu lagi identiti OIDC', + conflictSAML2: 'Identiti SAML2 lain', + conflictType: 'Jenis konflik', + credentialFileReadFailed: 'Fail kelayakan tidak dapat dibaca.', + credentialFileTooLarge: 'Fail kelayakan tidak boleh melebihi 256 KiB.', + credentialsRequired: 'Konfigurasikan kunci peribadi dan sijil SP.', + defaultRole: 'Peranan pengguna baharu', + defaultRoleHelper: + 'Ditetapkan pada penciptaan pertama sahaja; log masuk seterusnya mengekalkan peranan, MFA dan kebenaran setempat.', + defaultRolePlaceholder: 'Pilih peranan', + defaultRoleRequired: 'Pilih peranan lalai yang sah.', + disableConfirm: + 'Melumpuhkan SAML2 serta-merta menolak log masuk baharu dan membatalkan sesi penggunanya. Teruskan?', + disableDiscardConfirm: + 'Melumpuhkan SAML2 membuang perubahan lain yang belum disimpan pada halaman ini dan serta-merta membatalkan sesi penggunanya. Teruskan?', + disableTitle: 'Lumpuhkan SAML2', + disabled: 'Dilumpuhkan', + enable: 'Dayakan', + enabled: 'Didayakan', + idpMetadata: 'Metadata IdP', + idpMetadataDesc: 'Masukkan URL atau tampal XML. Jika kedua-duanya ada, URL diutamakan.', + keepExistingRole: 'Kekalkan peranan sedia ada dan kebenaran setempat', + loginWith: 'Log masuk dengan {provider}', + mappingResult: 'Hasil pemetaan', + metadataRequired: 'Masukkan URL atau XML Metadata IdP.', + metadataURLHelper: + 'Bahagian belakang memuat turun dan mengesahkan metadata semasa ujian dan simpanan.', + metadataURLInvalid: 'Masukkan URL metadata HTTPS yang sah tanpa kelayakan atau fragmen.', + metadataURLRecommended: 'URL metadata (disyorkan)', + metadataXML: 'XML metadata', + metadataXMLHelper: 'Gunakan apabila IdP tidak menyediakan URL metadata yang boleh dicapai.', + metadataXMLInvalid: 'Masukkan XML metadata EntityDescriptor yang sah.', + metadataXMLPlaceholder: 'Tampal ...', + nameAttribute: 'Atribut nama pengguna', + nameAttributeHelper: + 'Membaca atribut ini daripada SAML Assertion yang disahkan dan memetakannya kepada nama pengguna 1Panel.', + nameAttributePlaceholder: 'Contohnya: uid, username atau account', + nameAttributeRequired: 'Masukkan atribut nama pengguna.', + notConfigured: 'Belum dikonfigurasi', + or: 'atau', + pageDesc: 'Sambungkan SSO perusahaan melalui Metadata IdP dengan tetapan umum pada satu halaman.', + plannedHandling: 'Pengendalian terancang', + privateKeyFileInvalid: 'Pilih fail kunci peribadi PEM yang sah.', + recentTestSuccess: 'Ujian terakhir berjaya: {0}', + restore: 'Pulihkan', + restored: 'Tetapan SAML2 yang terakhir disimpan telah dipulihkan.', + roleHandling: 'Pengendalian peranan', + rolesLoadFailed: 'Peranan tidak dapat dimuatkan. Cuba semula sebelum memilih peranan lalai.', + selectFile: 'Pilih fail', + serviceStatus: 'Status perkhidmatan', + serviceStatusDesc: 'Konfigurasi semasa mesti lulus ujian sebelum SAML2 boleh didayakan.', + settingLoadFailed: 'Tetapan SAML2 tidak dapat dimuatkan', + settingLoadFailedHelper: + 'Borang dikunci untuk mengelakkan menyimpan konfigurasi lalai kosong pada tetapan semasa. Cuba semula selepas sambungan pulih.', + spCertificate: 'Sijil SP', + spCertificateHelper: + 'Diterbitkan dalam metadata SP supaya IdP boleh mengesahkan permintaan log masuk dan log keluar.', + spCredentials: 'Kunci peribadi dan sijil SP', + spCredentialsDesc: + 'Digunakan untuk menandatangani mesej log masuk dan log keluar. Dasar tandatangan dan pengesahan ditetapkan oleh bahagian belakang.', + spPrivateKey: 'Kunci peribadi SP', + spPrivateKeyHelper: + 'Digunakan untuk menandatangani AuthnRequest dan mesej log keluar. Ia disulitkan semasa disimpan dan tidak pernah dipaparkan.', + syncLogout: 'Log keluar segerak', + syncLogoutHelper: + 'Log keluar daripada 1Panel atau penyedia identiti turut melog keluar bahagian yang lain.', + testBeforeBrowserTest: 'Uji konfigurasi semasa sebelum memulakan ujian log masuk penyemak imbas.', + testBeforeEnable: 'Uji konfigurasi semasa sebelum mendayakan atau menyimpan perubahan sensitif.', + testConfiguration: 'Uji konfigurasi', + unsavedChanges: 'Terdapat perubahan SAML2 yang belum disimpan.', + usedAttribute: 'Pemetaan nama pengguna', + usersAndRoles: 'Pengguna dan peranan', + usersAndRolesDesc: + 'Konfigurasikan pemetaan nama pengguna panel serta nod dan peranan lalai untuk mencipta pengguna pada log masuk pertama.', + }, ldap: { + basic: 'Tetapan asas', + loginTitle: 'Log masuk LDAP', + loginWith: 'Log masuk dengan LDAP', + backToLocalLogin: 'Kembali ke log masuk panel', enable: 'Dayakan', enabled: 'Didayakan', disabled: 'Dilumpuhkan', @@ -5234,6 +5641,7 @@ const message = { deleteConfirm: 'Padam rekod eksport dan fail ini?', }, waf: { + WAF: 'WAF', name: 'WAF', blackWhite: 'Senarai Hitam dan Putih', globalSetting: 'Tetapan Global', @@ -5853,6 +6261,15 @@ const message = { nodeUpgradePackageCleanHelper: 'Semua pakej kemas kini versi lebih rendah akan dibersihkan. Teruskan?', nodeUpgradeOfflinePackageHelper: 'Dalam persekitaran luar talian, nod berbeza seni bina perlu memuat naik pakej kemas kini yang sepadan sebelum dikemas kini.', + healthCheck: 'Pemeriksaan Kesihatan', + healthCheckFrequency: 'Kekerapan Pemeriksaan', + healthCheckFrequencyHelper: + 'Periksa kesihatan nod backend secara berkala. Masukkan 0 untuk melumpuhkan pemeriksaan.', + healthCheckFrequencyLimit: + 'Kekerapan pemeriksaan tidak boleh melebihi satu hari dan mesti berupa integer bukan negatif.', + loadFailedNodeResources: 'Muat sumber nod yang gagal', + loadFailedNodeResourcesHelper: + 'Apabila membuka senarai nod, turut muat maklumat sumber untuk nod yang gagal.', nodeUnhealthy: 'Status nod tidak normal', deletedNode: 'Nod {0} yang telah dipadam tidak menyokong operasi naik taraf buat masa ini!', nodeUnhealthyHelper: 'Status nod tidak normal dikesan. Sila semak dalam [Pengurusan Nod] dan cuba lagi!', @@ -5946,6 +6363,8 @@ const message = { offlineHelper: 'Digunakan apabila nod berada dalam persekitaran luar talian', appUpgrade: 'Naik Taraf Apl', appUpgradeHelper: 'Terdapat {0} apl yang perlu dinaik taraf', + dashboardSetting: 'Tetapan Gambaran Keseluruhan', + keepOneDashboardComponent: 'Kekalkan sekurang-kurangnya satu bahagian gambaran keseluruhan', }, customApp: { name: 'Repositori Aplikasi Khusus', @@ -6349,35 +6768,35 @@ const message = { cpu: 'CPU', memory: 'Memori', disk: 'Cakera', - overview: 'Overview', - kvmUnavailable: 'No available KVM hardware virtualization capability was detected.', - kvmCheckCpu: 'Confirm that the host CPU supports Intel VT-x or AMD-V virtualization.', - kvmCheckBios: 'Enable virtualization options in BIOS/UEFI.', - kvmCheckModule: 'Confirm that the kvm, kvm_intel, or kvm_amd kernel module is loaded correctly.', + overview: 'Gambaran keseluruhan', + kvmUnavailable: 'Tiada keupayaan virtualisasi perkakasan KVM tersedia dikesan.', + kvmCheckCpu: 'Pastikan CPU hos menyokong virtualisasi Intel VT-x atau AMD-V.', + kvmCheckBios: 'Dayakan pilihan virtualisasi dalam BIOS/UEFI.', + kvmCheckModule: 'Pastikan modul kernel kvm, kvm_intel atau kvm_amd dimuatkan dengan betul.', kvmCheckDevice: - 'Confirm that /dev/kvm exists and the current environment is not a container or cloud host without KVM support.', - abnormal: 'Abnormal', - resourceOverview: 'Resource Overview', - cpuAllocated: 'CPU Allocated', - memoryAllocated: 'Memory Allocated', - storageUsed: 'Storage Used', - riskReminder: 'Risk Reminders', - noRisk: 'No risks', - runtimeHealth: 'Runtime Health', - runtimeAbnormal: 'VM runtime is abnormal', - noDependency: 'No dependency check data', - storageOverview: 'Storage Overview', - totalAllocated: 'Calculated by total VM configuration', - runningAllocated: 'Running allocation: {0}', - storageAvailable: 'Available: {0}', - inProgress: 'In progress', - needAttention: 'Needs attention', + 'Pastikan /dev/kvm wujud dan persekitaran semasa bukan kontena atau hos awan tanpa sokongan KVM.', + abnormal: 'Tidak normal', + resourceOverview: 'Gambaran keseluruhan sumber', + cpuAllocated: 'CPU diperuntukkan', + memoryAllocated: 'Memori diperuntukkan', + storageUsed: 'Storan digunakan', + riskReminder: 'Peringatan risiko', + noRisk: 'Tiada risiko', + runtimeHealth: 'Kesihatan masa jalan', + runtimeAbnormal: 'Masa jalan VM tidak normal', + noDependency: 'Tiada data semakan kebergantungan', + storageOverview: 'Gambaran keseluruhan storan', + totalAllocated: 'Dikira daripada jumlah konfigurasi VM', + runningAllocated: 'Peruntukan sedang berjalan: {0}', + storageAvailable: 'Tersedia: {0}', + inProgress: 'Sedang berjalan', + needAttention: 'Perlu perhatian', normal: 'Normal', - environmentRisk: 'The VM runtime is not ready. Fix dependencies or virtualization services.', - storageRisk: 'Storage pool {0} usage has reached {1}%.', - abnormalRisk: '{0} VMs are in an abnormal state.', - pausedRisk: '{0} VMs are paused.', - memoryRisk: 'VM memory allocation has reached {0}%.', + environmentRisk: 'Masa jalan VM belum tersedia. Betulkan kebergantungan atau perkhidmatan virtualisasi.', + storageRisk: 'Penggunaan kolam storan {0} telah mencapai {1}%.', + abnormalRisk: '{0} VM berada dalam keadaan tidak normal.', + pausedRisk: '{0} VM dijeda.', + memoryRisk: 'Peruntukan memori VM telah mencapai {0}%.', cpuLimitHelper: 'CPU tersedia semasa: {0} teras', cpuLimitExceeded: 'CPU melebihi had. Maksimum tersedia semasa: {0} teras.', memoryLimitHelper: 'Memori yang boleh diperuntukkan semasa: {0} (hos mesti merizab {1} memori)', @@ -6386,11 +6805,11 @@ const message = { storageLimitExceeded: 'Kapasiti cakera melebihi had. Maksimum tersedia semasa: {0}.', iso: 'ISO', createFromTemplate: 'Cipta daripada templat', - template: 'Template', - templateName: 'Template Name', - convertToTemplate: 'Convert to Template', - sourceVM: 'Source VM', - templateSize: 'Template Size', + template: 'Templat', + templateName: 'Nama templat', + convertToTemplate: 'Tukar kepada templat', + sourceVM: 'VM sumber', + templateSize: 'Saiz templat', deleteTemplateConfirm: 'Padam templat {0}. Operasi ini tidak boleh dibuat asal. Teruskan?', orphanClean: 'Pembersihan data yatim', orphanScan: 'Imbas semula', @@ -6434,21 +6853,21 @@ const message = { available: 'Tersedia', vmCount: 'VM Terpaut', usedIPs: 'IP Digunakan', - monitor: 'Monitor', - monitorNotReady: 'The virtual machine is not running. Monitoring data is unavailable.', - monitorLoadFailed: 'Failed to get VM monitoring data.', - monitorLoadFailedWithReason: 'Failed to get VM monitoring data: {0}', - rename: 'Rename', + monitor: 'Pemantauan', + monitorNotReady: 'Mesin maya tidak berjalan. Data pemantauan tidak tersedia.', + monitorLoadFailed: 'Gagal mendapatkan data pemantauan VM.', + monitorLoadFailedWithReason: 'Gagal mendapatkan data pemantauan VM: {0}', + rename: 'Namakan semula', newName: 'Nama baru', - renameHelper: 'Enter a new VM name. The VM must be shut down before renaming.', - renameConfirm: 'Rename virtual machine [{0}] to [{1}]?', - renameRunningHelper: 'Shut down the virtual machine before renaming it.', - cpuUsage: 'CPU Usage', - memoryUsage: 'Memory Usage', - diskIO: 'Disk IO', - networkIO: 'Network IO', - diskReadWrite: 'Disk Read / Write', - networkRxTx: 'Network RX / TX', + renameHelper: 'Masukkan nama VM baharu. VM mesti dimatikan sebelum dinamakan semula.', + renameConfirm: 'Namakan semula mesin maya [{0}] kepada [{1}]?', + renameRunningHelper: 'Matikan mesin maya sebelum menamakannya semula.', + cpuUsage: 'Penggunaan CPU', + memoryUsage: 'Penggunaan memori', + diskIO: 'I/O cakera', + networkIO: 'I/O rangkaian', + diskReadWrite: 'Baca / Tulis cakera', + networkRxTx: 'RX / TX rangkaian', rx: 'RX', tx: 'TX', console: 'Konsol', @@ -6456,16 +6875,18 @@ const message = { consoleDisconnected: 'Konsol VNC telah terputus.', consoleConnectFailed: 'Gagal menyambung ke konsol VNC. Semak perkhidmatan proksi konsol.', consoleCredentialsRequired: 'Konsol VNC memerlukan kelayakan. Semak konfigurasi proksi backend.', - snapshot: 'Snapshot', - createSnapshot: 'Create Snapshot', - recoverSnapshot: 'Recover Snapshot', + snapshot: 'Syot kilat', + createSnapshot: 'Cipta syot kilat', + recoverSnapshot: 'Pulihkan syot kilat', snapshotSize: 'Penggunaan', - currentSnapshot: 'Current', - snapshotEmpty: 'No snapshots', + currentSnapshot: 'Semasa', + snapshotEmpty: 'Tiada syot kilat', snapshotHelper: - 'A snapshot saves the current VM state as a restore point. Subsequent data changes are recorded in a delta file without changing the original disk. Restoring a snapshot returns the VM to that point in time.', + 'Syot kilat menyimpan keadaan semasa VM sebagai titik pemulihan. Perubahan data seterusnya direkodkan dalam fail delta tanpa mengubah cakera asal. Memulihkan syot kilat mengembalikan VM ke keadaan tersebut.', + snapshotOperationHelper: + 'Syot kilat semasa tidak boleh dipadam. Syot kilat hanya boleh dipulihkan apabila mesin maya dimatikan.', snapshotRecoverConfirm: - 'Recover virtual machine [{1}] to snapshot [{0}]? The VM disk will be restored to the snapshot state.', + 'Pulihkan mesin maya [{1}] kepada syot kilat [{0}]? Cakera VM akan dipulihkan kepada keadaan syot kilat.', interface: 'Antara Muka Rangkaian', device: 'Peranti', path: 'Laluan', @@ -6543,7 +6964,8 @@ const message = { varTypeSelectHelper: 'Pilih daripada pilihan pratetap, pilihan perlu diisi', varTypeColor: 'Warna', varTypeColorHelper: 'Pemilih warna', - autoDetectHelper: 'Pemboleh ubah dalam kurungan kerinting berganda dikesan secara automatik dan ditambah ke jadual', + autoDetectHelper: + 'Pemboleh ubah dalam kurungan kerinting berganda dikesan secara automatik dan ditambah ke jadual', selectTemplate: 'Pilih Templat', fillVariables: 'Isi Pemboleh Ubah', noVariables: 'Tiada pemboleh ubah ditakrifkan dalam templat ini', diff --git a/frontend/src/lang/modules/pt-br.ts b/frontend/src/lang/modules/pt-br.ts index 0728de74d..c91ad5338 100644 --- a/frontend/src/lang/modules/pt-br.ts +++ b/frontend/src/lang/modules/pt-br.ts @@ -11,6 +11,7 @@ const message = { button: { run: 'Executar', add: 'Adicionar', + select: 'Selecionar', save: 'Salvar', set: 'Configurações', sync: 'Sincronizar', @@ -29,7 +30,6 @@ const message = { selectAll: 'Selecionar tudo', login: 'Entrar', close: 'Fechar', - off: 'Fechar', stop: 'Parar', start: 'Iniciar', view: 'Visualizar', @@ -54,6 +54,7 @@ const message = { power: 'Enviar', search: 'Pesquisar', refresh: 'Atualizar', + reconnect: 'Reconectar', get: 'Obter', upgrade: 'Fazer upgrade', update: 'Atualizar', @@ -119,6 +120,9 @@ const message = { card: 'Cartao', table: 'Tabela', status: 'Status', + statusSuccess: 'Sucesso', + statusFailed: 'Falha', + statusWaiting: 'Aguardando...', records: 'Registros', group: 'Grupo', createdAt: 'Data de criação', @@ -163,6 +167,7 @@ const message = { deleteSuccess: 'Excluído com sucesso', loginSuccess: 'Login realizado com sucesso', operationSuccess: 'Operação concluída com sucesso', + operationFailed: 'Falha na operação', copySuccess: 'Copiado com sucesso', notSupportOperation: 'Esta operação não é suportada', requestTimeout: 'A solicitação expirou, tente novamente mais tarde', @@ -206,6 +211,7 @@ const message = { username: 'Usuário', password: 'Senha', passkey: 'Login com Passkey', + otherLoginMethods: 'Outras formas de login', welcome: 'Bem-vindo de volta, insira seu usuário e senha para acessar!', errorAuthInfo: 'O nome de usuário ou senha que você inseriu está incorreto, tente novamente!', errorMfaInfo: 'Informações de autenticação incorretas, tente novamente!', @@ -287,6 +293,9 @@ const message = { length128Err: 'O comprimento não pode exceder 128 caracteres', maxLength: 'O comprimento não pode exceder {0} caracteres', alias: 'Suporta letras, números, - e _, comprimento de 1 a 128, e não pode começar ou terminar com -_.', + vmName: 'Aceita letras, números, ".", "-" e "_"; comprimento: 1-64; deve começar com uma letra ou um número.', + vmNetwork: + 'Aceita letras, números, ".", ":", "-" e "_"; comprimento: 1-64; deve começar com uma letra ou um número.', }, res: { paramError: 'A solicitação falhou, por favor, tente novamente mais tarde!', @@ -305,7 +314,6 @@ const message = { success: 'Sucesso', waiting: 'Aguardando', waitForUpgrade: 'Aguardar Atualização', - waiting1: 'Aguardando', failed: 'Falhou', stopped: 'Parado', error: 'Erro', @@ -329,7 +337,6 @@ const message = { deny: 'Negado', accept: 'Aceito', used: 'Usado', - unUsed: 'Não usado', starting: 'Iniciando', recreating: 'Reconstruindo', creating: 'Criando', @@ -400,7 +407,7 @@ const message = { database: 'Banco de Dados | Bancos de Dados', aiTools: 'AI', mcp: 'MCP', - container: 'Container | Containers', + container: 'Contêineres', cronjob: 'Tarefa Cron | Tarefas Cron', system: 'Sistema', security: 'Segurança', @@ -471,7 +478,7 @@ const message = { cpuSteal: 'Roubado', cpuTop: 'Top 5 Processos por Uso de CPU', memTop: 'Top 5 Processos por Uso de Memória', - loadAverage: 'Média de carga nos últimos 1 minuto | Média de carga nos últimos {n} minutos', + loadAverage: 'Média de carga nos últimos {0} minutos', load: 'Carga', mount: 'Ponto de montagem', fileSystem: 'Sistema de arquivos', @@ -507,6 +514,7 @@ const message = { deleteBackupHelper: 'Excluir backups do banco de dados simultaneamente', delete: 'A operação de exclusão não pode ser desfeita, insira "', deleteHelper: '" para excluir este banco de dados', + deleteUserHelper: '" para excluir este usuário', userBoundDatabases: 'tem acesso aos seguintes bancos de dados:', noMysql: 'Serviço de banco de dados (MySQL ou MariaDB)', noPostgresql: 'Serviço de banco de dados PostgreSQL', @@ -557,6 +565,7 @@ const message = { revokeAuthorizationHelper: 'Revogar o acesso do usuário {0} ao banco de dados {1}?', supplementPassword: 'Adicionar senha', supplementPasswordHelper: 'Apenas salva a senha existente no 1Panel; não altera a senha no MySQL.', + noUserBind: 'Sem vínculo', pgBindHelper: 'Esta operação cria um novo usuário e o vincula ao banco de dados alvo. A seleção de usuários já existentes no banco de dados não é suportada.', pgSuperUser: 'Superusuário', @@ -937,9 +946,9 @@ const message = { 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', ollama_sync: - 'Menyelaraskan model Ollama mendapati model berikut tidak wujud, adakah anda ingin memadamnya?', - from_remote: 'Model ini tidak dimuat turun melalui 1Panel, tiada log pengambilan berkaitan.', - no_logs: 'Log pengambilan untuk model ini telah dipadam dan tidak dapat dilihat.', + 'Ao sincronizar os modelos Ollama, os modelos a seguir não foram encontrados. Deseja excluí-los?', + from_remote: 'Este modelo não foi baixado pelo 1Panel; não há logs de download relacionados.', + no_logs: 'Os logs de download deste modelo foram excluídos e não podem ser visualizados.', vllmVersionHelper: 'Para servidores FusionXpark GB 10, selecione a versão -cu130.', vllmCommandPortHelper: 'O comando de inicialização deve usar a porta {0}; caso contrário, o serviço ficará inacessível.', @@ -1002,9 +1011,6 @@ const message = { failureCount: 'Falhas', lastError: 'Último erro', modelMap: 'Mapeamento de modelos', - apiKeyKeepEmpty: 'API Key (deixe vazio para manter)', - apiKeyOnceHint: 'A API Key é exibida apenas uma vez após a criação. Copie e salve agora.', - apiKeyOnceSave: 'A API Key é exibida apenas uma vez. Salve agora:', qpsLimit: 'Limite de QPS', tokenLimit: 'Limite de tokens', tokenUsed: 'Tokens usados', @@ -1146,23 +1152,23 @@ const message = { modelGroupGuide: 'Grupos de modelos contêm os nomes de modelo expostos pelo gateway de IA. Configure os modelos upstream no mapeamento de modelos do pool de contas. auto é um nome de modelo virtual e não deve ser adicionado ao grupo.', modelGroupModelCount: '{0} modelos', - contentCompliance: 'Content Compliance', - contentAction: 'Action', - actionBlock: 'Block', - actionAuditOnly: 'Audit only', + contentCompliance: 'Conformidade de Conteúdo', + contentAction: 'Ação', + actionBlock: 'Bloquear', + actionAuditOnly: 'Somente auditar', actionDropHistory: 'Remover histórico', - severity: 'Severity', - severityHigh: 'High', - severityMedium: 'Medium', - severityLow: 'Low', - sensitiveWord: 'Sensitive word', - sensitiveGroup: 'Sensitive word group', - sensitiveWordCount: 'Words', - normalizedWord: 'Normalized word', - matchedWords: 'Matched words', - matchedGroups: 'Matched groups', - importResult: 'Imported {0}, duplicated {1}, invalid {2}', - auditLogs: 'Audit Logs', + severity: 'Severidade', + severityHigh: 'Alta', + severityMedium: 'Média', + severityLow: 'Baixa', + sensitiveWord: 'Palavra sensível', + sensitiveGroup: 'Grupo de palavras sensíveis', + sensitiveWordCount: 'Palavras', + normalizedWord: 'Palavra normalizada', + matchedWords: 'Palavras correspondentes', + matchedGroups: 'Grupos correspondentes', + importResult: 'Importados {0}, duplicados {1}, inválidos {2}', + auditLogs: 'Logs de Auditoria', smartRoute: 'Roteamento inteligente', smartRouteGuideTitle: 'Use model=auto no cliente para entrar no roteamento inteligente', smartRouteGuideReady: @@ -1485,14 +1491,14 @@ const message = { streamableHttpPathHelper: 'Por exemplo: /mcp, certifique-se de que não se sobreponha a outros Servidores', npxHelper: 'Adequado para mcp iniciado com npx ou binário', uvxHelper: 'Adequado para mcp iniciado com uvx', - protocolVersion: 'Protocol Version', + protocolVersion: 'Versão do Protocolo', protocolVersionHelper: - 'Only used by stateless Streamable HTTP to auto-initialize the downstream stdio MCP Server', + 'Usado apenas pelo Streamable HTTP sem estado para inicializar automaticamente o MCP Server stdio a jusante', gatewayArgsHelper: 'Os argumentos são adicionados ao comando supergateway. Os parâmetros de transporte, porta, caminho e protocolo gerenciados pelo 1Panel não podem ser alterados', - testConnection: 'Test Connection', - connectionSuccess: 'Connection succeeded', - connectionFailed: 'Connection failed', + testConnection: 'Testar Conexão', + connectionSuccess: 'Conexão bem-sucedida', + connectionFailed: 'Falha na conexão', }, tensorRT: { llm: 'TensorRT LLM', @@ -1568,8 +1574,9 @@ const message = { lastHour: 'Última hora', last10Min: 'Últimos 10 minutos', cleanLog: 'Limpar log', + cleanLogscope: 'Tipo de limpeza', downLogHelper1: 'Isso fará o download de todos os logs do contêiner {0}. Deseja continuar?', - downLogHelper2: 'Isso fará o download dos últimos {0} logs do contêiner {0}. Deseja continuar?', + downLogHelper2: 'Isso baixará os {1} logs mais recentes do contêiner {0}. Deseja continuar?', cleanLogHelper: 'Isso exigirá a reinicialização do contêiner e não poderá ser desfeito. Deseja continuar?', newName: 'Novo nome', source: 'Uso de recursos', @@ -1715,7 +1722,7 @@ const message = { scope: 'Escopo IP', gateway: 'Gateway', auxAddress: 'Excluir IP', - volume: 'Volume | Volumes', + volume: 'Volumes', volumeDir: 'Diretório do volume', nfsEnable: 'Habilitar armazenamento NFS', nfsAddress: 'Endereço', @@ -1771,7 +1778,8 @@ const message = { daemonJsonPathHelper: 'Certifique-se de que o caminho de configuração seja o mesmo especificado no docker.service.', mirrors: 'Espelhos de registro', - mirrorsHelper: '', + mirrorsHelper: + 'Use primeiro as URLs de espelho do registro nas operações de imagem. Deixe vazio para desativar os espelhos do registro.', mirrorsHelper2: 'Para mais detalhes, consulte a documentação oficial.', registries: 'Registries inseguros', ipv6Helper: @@ -1839,7 +1847,6 @@ const message = { stopHelper: 'Esta operação forçará a parada da execução da tarefa atual. Continuar?', log: 'Logs de backup', logHelper: 'Backup do log do sistema', - ogHelper1: '1. Log do sistema 1Panel', logHelper2: '2. Log de login SSH do servidor', logHelper3: '3. Todos os logs do site', containerCheckBox: 'No container (não é necessário inserir o comando do container)', @@ -1869,8 +1876,6 @@ const message = { curl: 'URL de acesso', taskName: 'Nome', cronSpec: 'Ciclo de execução', - cronSpeDoc: - 'Ciclos de execução personalizados suportam apenas o formato [minuto hora dia mês semana], por exemplo, 0 0 * * *. Consulte a documentação oficial para obter detalhes.', cronSpecHelper: 'Digite o período correto de execução', cleanHelper: 'Esta operação registra todos os registros de execução de tarefas, arquivos de backup e logs. Você deseja continuar?', @@ -1909,10 +1914,7 @@ const message = { perNHour: 'A cada N hora(s)', perNMinute: 'A cada N minuto(s)', perNSecond: 'A cada N segundo(s)', - per: 'A cada ', - handle: '', day: 'dia(s)', - dayUnit: 'd', monday: 'Segunda-feira', tuesday: 'Terça-feira', wednesday: 'Quarta-feira', @@ -2058,14 +2060,13 @@ const message = { nodeAdminLocalOnly: 'Administradores de nó só podem usar o terminal local.', localHelper: 'O nome local é usado apenas para identificação local do sistema.', connLocalErr: - 'Невозможно автоматически аутентифицироваться, пожалуйста, заполните информацию для входа на локальный сервер.', + 'Não foi possível autenticar automaticamente. Preencha as informações de login do servidor local.', testConn: 'Testar conexão', saveAndConn: 'Salvar e conectar', connTestOk: 'Informações de conexão disponíveis', connTestFailed: 'Conexão indisponível, por favor, verifique as informações de conexão.', - host: 'Host | Hosts', + host: 'Hosts', createConn: 'Nova conexão', - manageGroup: 'Gerenciar grupos', noHost: 'Nenhum host', groupChange: 'Alterar grupo', expand: 'Expandir todos', @@ -2151,6 +2152,8 @@ const message = { 'Quando houver múltiplos DNS, coloque cada um em uma nova linha. Ex.:\n114.114.114.114\n8.8.8.8', hostsHelper: 'Resolução de hostname', hosts: 'Domínio', + hostAlert: + 'Os registros comentados estão ocultos. Clique em "Todas as configurações" para visualizá-los ou configurá-los.', toolbox: 'Configurações rápidas', hostname: 'Hostname', passwd: 'Senha do sistema', @@ -2256,119 +2259,6 @@ const message = { alertTitle: 'Tarefa de varredura de vírus "{0}" detectou arquivo infectado', }, }, - device: { - dnsHelper: 'Servidor DNS', - dnsAlert: - 'Atenção! Modificar a configuração do arquivo /etc/resolv.conf restaurará o arquivo para seus valores padrão após a reinicialização do sistema.', - dnsHelper1: - 'Quando houver várias entradas DNS, elas devem ser exibidas em novas linhas. Exemplo:\n114.114.114.114\n8.8.8.8', - hostsHelper: 'Resolução de hostname', - hosts: 'Domínio', - hostAlert: - 'Registros comentados ocultos, clique no botão "Todas as configurações" para visualizar ou configurar', - toolbox: 'Configurações rápidas', - hostname: 'Nome do host', - passwd: 'Senha do sistema', - passwdHelper: 'Os caracteres de entrada não podem incluir $ e &', - timeZone: 'Fuso horário', - localTime: 'Hora do servidor', - timeZoneChangeHelper: - 'Modificar o fuso horário do sistema requer a reinicialização do serviço. Deseja continuar?', - timeZoneHelper: - 'Se você não instalar o comando "timedatectl", poderá não conseguir alterar o fuso horário. O sistema usa esse comando para alterar o fuso horário.', - timeZoneCN: 'Pequim', - timeZoneAM: 'Los Angeles', - timeZoneNY: 'Nova York', - ntpALi: 'Alibaba', - ntpGoogle: 'Google', - syncSite: 'Servidor NTP', - hostnameHelper: - 'A modificação do nome do host depende do comando "hostnamectl". Se o comando não estiver instalado, a modificação pode falhar.', - userHelper: - 'O nome de usuário depende do comando "whoami" para recuperação. Se o comando não estiver instalado, a recuperação pode falhar.', - passwordHelper: - 'A modificação da senha depende do comando "chpasswd". Se o comando não estiver instalado, a modificação pode falhar.', - hostHelper: 'Há um valor vazio no conteúdo fornecido. Verifique e tente novamente após a modificação!', - dnsCheck: 'Testar disponibilidade', - dnsOK: 'As informações de configuração do DNS estão disponíveis!', - dnsTestFailed: 'As informações de configuração do DNS não estão disponíveis.', - }, - fail2ban: { - sshPort: 'Porta de escuta do SSH', - sshPortHelper: 'O Fail2ban atual escuta a porta de conexão SSH do host', - unActive: 'O serviço Fail2ban não está ativado no momento.', - operation: 'Você realizará a operação "{0}" no serviço Fail2ban. Deseja continuar?', - fail2banChange: 'Modificação da configuração do Fail2ban', - ignoreHelper: 'A lista de IPs na lista de permissão será ignorada para bloqueio. Deseja continuar?', - bannedHelper: 'A lista de IPs na lista de bloqueio será bloqueada pelo servidor. Deseja continuar?', - maxRetry: 'Máximo de tentativas de reclusão', - banTime: 'Tempo de banimento', - banTimeHelper: 'O tempo de banimento padrão é 10 minutos, -1 indica banimento permanente', - banTimeRule: 'Por favor, insira um tempo de banimento válido ou -1', - banAllTime: 'Banimento permanente', - findTime: 'Período de descoberta', - banAction: 'Ação de bloqueio', - banActionOption: 'Bloquear endereços IP especificados usando {0}', - allPorts: ' (Todas as portas)', - ignoreIP: 'Lista de permissão de IP', - bannedIP: 'Lista de bloqueio de IP', - logPath: 'Caminho do log', - logPathHelper: 'O padrão é /var/log/secure ou /var/log/auth.log', - }, - ftp: { - ftp: 'Conta FTP | Contas FTP', - notStart: 'O serviço FTP não está em execução, por favor, inicie-o primeiro!', - operation: 'Isso realizará a operação "{0}" no serviço FTP. Deseja continuar?', - noPasswdMsg: 'Não foi possível obter a senha atual da conta FTP, por favor, defina a senha e tente novamente!', - enableHelper: 'Ativar a conta FTP selecionada restaurará suas permissões de acesso. Deseja continuar?', - disableHelper: 'Desativar a conta FTP selecionada revogará suas permissões de acesso. Deseja continuar?', - syncHelper: 'Sincronizar os dados da conta FTP entre o servidor e o banco de dados. Deseja continuar?', - dirSystem: - 'Este diretório é reservado do sistema. Modificações podem causar falhas no sistema. Por favor, modifique e tente novamente!', - dirHelper: 'Habilitar FTP requer alterações nas permissões do diretório - por favor, escolha com cuidado', - dirMsg: 'Habilitar FTP modificará as permissões de todo o diretório {0}. Continuar?', - }, - clam: { - clam: 'Scan de vírus', - cron: 'Scan agendado', - cronHelper: 'A edição comercial oferece suporte a scans agendados', - specErr: 'Erro no formato do agendamento, por favor, verifique e tente novamente!', - disableMsg: - 'Parar a execução agendada impedirá que esta tarefa de scan seja executada automaticamente. Deseja continuar?', - enableMsg: - 'Ativar a execução agendada permitirá que esta tarefa de scan seja executada automaticamente em intervalos regulares. Deseja continuar?', - showFresh: 'Mostrar serviço de atualização de assinaturas', - hideFresh: 'Ocultar serviço de atualização de assinaturas', - clamHelper: - 'A configuração mínima recomendada para o ClamAV é: 3 GiB de RAM ou mais, CPU de 1 núcleo com 2.0 GHz ou superior, e pelo menos 5 GiB de espaço livre no disco rígido.', - notStart: 'O serviço ClamAV não está em execução, por favor, inicie-o primeiro!', - removeRecord: 'Excluir arquivos de relatório', - noRecords: 'Clique no botão "Acionar" para iniciar o scan e você verá registros aqui.', - removeInfected: 'Excluir arquivos infectados', - removeInfectedHelper: - 'Excluir arquivos de vírus detectados durante a tarefa para garantir a segurança e o funcionamento normal do servidor.', - clamCreate: 'Criar regra de scan', - infectedStrategy: 'Estratégia de arquivos infectados', - removeHelper: 'Excluir arquivos de vírus, escolha com cuidado!', - move: 'Mover', - moveHelper: 'Mover arquivos de vírus para o diretório especificado', - copyHelper: 'Copiar arquivos de vírus para o diretório especificado', - none: 'Não fazer nada', - noneHelper: 'Não tomar nenhuma ação sobre arquivos de vírus', - scanDir: 'Diretório de scan', - infectedDir: 'Diretório de arquivos infectados', - scanDate: 'Data do scan', - scanResult: 'Últimos logs de scan', - tail: 'Linhas', - infectedFiles: 'Arquivos infectados', - log: 'Detalhes', - clamConf: 'Daemon Clam AV', - clamLog: '@:toolbox.clam.clamConf logs', - freshClam: 'FreshClam', - freshClamLog: '@:toolbox.clam.freshClam logs', - alertHelper: 'A edição comercial oferece suporte a scans agendados e alertas por SMS', - alertTitle: 'Tarefa de scan de vírus 「{0}」 detectou alerta de arquivo infectado', - }, logs: { core: 'Serviço de Painel', agent: 'Monitoramento de Nós', @@ -2426,6 +2316,7 @@ const message = { nodes: 'nós', commands: 'Comandos Rápidos', opsReport: 'Relatório de Operações', + ops_report: 'Relatório de Operações', users: 'Gerenciamento de usuários', roles: 'Função', auth: 'Autenticação de login', @@ -2446,10 +2337,6 @@ const message = { fileDirNum: '{0} diretórios, {1} arquivos,', currentDir: 'Diretório atual', dir: 'Pasta', - upload: 'Carregar', - uploadFile: '@:file.upload @.lower:file.file', - uploadDirectory: '@:file.upload @.lower:file.dir', - download: 'Baixar', fileName: 'Nome do arquivo', search: 'Pesquisar', mode: 'Permissões', @@ -2465,7 +2352,6 @@ const message = { role: 'Permissões', info: 'Atributos', linkFile: 'Link simbólico', - batchoperation: 'Operação em lote', shareList: 'Lista de compartilhamento', fileTools: 'Ferramentas de arquivo', aiSearchHitLines: 'Linhas correspondentes', @@ -2619,42 +2505,42 @@ const message = { 'O lado esquerdo mostra a versão do histórico e o lado direito mostra a versão mais recente do arquivo selecionado', copyDir: 'Copiar', shareFile: 'Compartilhar arquivo', - shareExpire: 'Expires in', - shareExpire1h: '1 hour', - shareExpire6h: '6 hours', - shareExpire24h: '24 hours', - shareExpire3d: '3 days', - shareExpire7d: '7 days', - sharePassword: 'Password', - sharePasswordPlaceholder: 'Leave empty for no password', - shareMaxDownloads: 'Max downloads', - shareMaxDownloadsHint: '0 means unlimited', - shareGenerate: 'Create link', - shareRegenerate: 'Share again', - shareClose: 'Close', + shareExpire: 'Expira em', + shareExpire1h: '1 hora', + shareExpire6h: '6 horas', + shareExpire24h: '24 horas', + shareExpire3d: '3 dias', + shareExpire7d: '7 dias', + sharePassword: 'Senha', + sharePasswordPlaceholder: 'Deixe vazio para não usar senha', + shareMaxDownloads: 'Máximo de downloads', + shareMaxDownloadsHint: '0 significa ilimitado', + shareGenerate: 'Criar link', + shareRegenerate: 'Compartilhar novamente', + shareClose: 'Fechar', shareCancel: 'Cancelar compartilhamento', shareCancelConfirm: 'Tem certeza de que deseja cancelar este compartilhamento de arquivo?', - shareDetail: 'Details', - shareCopyLink: 'Copy link', - shareLinkLabel: 'Share link', - shareQrCode: 'QR code', - shareQrDialogTitle: 'Share link QR code', - shareQrDialogHelper: 'Scan this QR code with your mobile device', - shareSaveImage: 'Save image', - shareOpenImage: 'Open image', - shareExtractFile: 'Extract file', - shareDownloadingHint: 'Preparing your file, download will begin shortly.', - shareInvalid: 'Invalid or expired share link', - shareDownloadFailed: 'Download failed, please try again later', - sharePasswordRequired: 'Password', - sharePasswordRequiredInput: 'Please enter the share password', - sharePasswordLengthHint: 'Share password length must be 4-256 characters', - shareDownloadPasswordTip: 'This link is password-protected. Enter the password before downloading.', + shareDetail: 'Detalhes', + shareCopyLink: 'Copiar link', + shareLinkLabel: 'Link de compartilhamento', + shareQrCode: 'Código QR', + shareQrDialogTitle: 'Código QR do link de compartilhamento', + shareQrDialogHelper: 'Leia este código QR com seu dispositivo móvel', + shareSaveImage: 'Salvar imagem', + shareOpenImage: 'Abrir imagem', + shareExtractFile: 'Obter arquivo', + shareDownloadingHint: 'Preparando o arquivo. O download começará em breve.', + shareInvalid: 'Link de compartilhamento inválido ou expirado', + shareDownloadFailed: 'Falha no download. Tente novamente mais tarde', + sharePasswordRequired: 'Senha de acesso', + sharePasswordRequiredInput: 'Digite a senha de compartilhamento', + sharePasswordLengthHint: 'A senha de compartilhamento deve ter de 4 a 256 caracteres', + shareDownloadPasswordTip: 'Este link é protegido por senha. Digite a senha antes de fazer o download.', shareRiskAlert: - 'Shared links may carry security risks. Only share with trusted people and avoid exposing sensitive information.', + 'Links compartilhados podem apresentar riscos de segurança. Compartilhe apenas com pessoas confiáveis e evite expor informações confidenciais.', sharePasswordSeparate: - 'A password is set. Share it securely. Recipients must add &password=... to the URL or use a client that can pass the password query parameter.', - shareExpiresAt: 'Expires at', + 'Uma senha foi definida. Compartilhe-a com segurança. Os destinatários devem adicionar &password=... à URL ou usar um cliente que envie o parâmetro de consulta da senha.', + shareExpiresAt: 'Expira em', paste: 'Colar', changeOwner: 'Modificar usuário e grupo de usuários', containSub: 'Aplicar mudança de permissões recursivamente', @@ -2954,7 +2840,6 @@ const message = { 'O nó atual não tem um endereço de acesso padrão configurado. Por favor, vá para as configurações do painel para configurá-lo!', systemIPWarning1: 'O endereço atual do servidor está configurado como {0}, e o redirecionamento rápido não é possível!', - defaultNetwork: 'Placa de rede', syncTime: 'Hora do servidor', timeZone: 'Fuso horário', timeZoneChangeHelper: 'Alterar o fuso horário exige reiniciar o serviço. Deseja continuar?', @@ -3002,7 +2887,7 @@ const message = { codeWarning: 'O formato atual do código de autorização está incorreto, por favor, verifique novamente!', code: 'Código de autorização', codeHelper: - 'Clique no botão "Adquirir", faça login no OneDrive e copie o conteúdo após "code" no link redirecionado. Cole-o neste campo. Para instruções específicas, consulte a documentação oficial.', + 'Clique no botão "Adquirir", faça login em {0} e copie o conteúdo após "code" no link redirecionado. Cole-o neste campo. Para instruções específicas, consulte a documentação oficial.', googleHelper: 'Por favor, primeiro crie um aplicativo Google e obtenha as informações do cliente, preencha o formulário e clique no botão obter. Para operações específicas, consulte a documentação oficial.', loadCode: 'Obter', @@ -3326,8 +3211,6 @@ const message = { versionHelper: 'Regras de nome: [versão principal].[versão funcional].[versão de correção], como no exemplo abaixo:', upgradeCheck: 'Verificar atualizações', - panelSSLHelper: - 'Após a renovação automática do SSL do painel, reinicie manualmente o serviço 1Panel para aplicar as mudanças.', }, license: { offLine: 'Versão Offline', @@ -3356,9 +3239,8 @@ const message = { authorizedUser: 'Usuário autorizado', lostHelper: 'A licença atingiu o limite de tentativas. Execute a sincronização manualmente para garantir que os recursos da edição comercial continuem funcionando. detalhes: ', - disableHelper: - 'A verificação da sincronização da licença falhou. Execute a sincronização manualmente para garantir que os recursos da edição comercial funcionem corretamente. detalhes: ', quickUpdate: 'Atualização rápida', + import: 'Importar', power: 'Autorizar', unbindHelper: 'Todas as configurações relacionadas à edição comercial serão limpas após a desvinculação. Você deseja continuar?', @@ -3419,6 +3301,7 @@ const message = { fileExchange: 'Atualize para a edição comercial para transferir arquivos rapidamente entre vários servidores.', app: 'Faça upgrade para a edição comercial para visualizar informações do serviço e monitoramento de anomalias no aplicativo móvel.', cluster: 'Atualize para a edição comercial para gerenciar clusters primário-réplica de MySQL/Postgres/Redis.', + vllm: 'Atualize para a edição comercial para gerenciar serviços vLLM de forma centralizada no 1Panel, incluindo implantação, configuração, operações de ciclo de vida e acompanhamento de tarefas.', 'model-downloader': 'Atualize para a edição comercial para pesquisar, baixar e gerenciar arquivos de modelos locais do HuggingFace, ModelScope ou mirrors compatíveis, com diretórios de modelos e tarefas de download centralizados.', exceptionalHelper: @@ -3475,7 +3358,7 @@ const message = { volumes: 'Volumes', buildCache: 'Cache de construção do container', appTmpDownload: 'Arquivo de download temporário do aplicativo', - unknownWebsiteLog: 'Fail sandaran log laman web tidak dikaitkan', + unknownWebsiteLog: 'Arquivo de backup de log de site não vinculado', snapshot: 'Arquivos temporários de snapshot do sistema', }, app: { @@ -3546,8 +3429,6 @@ const message = { allReadyInstalled: 'Instalado', installHelper: 'Se houver problemas ao puxar a imagem, configure a aceleração da imagem.', sortMode: 'Ordenar', - upgradeHelper: - 'Coloque aplicativos anormais de volta ao estado normal antes de atualizar. Se a atualização falhar, vá para "Logs > Logs do Sistema" para verificar a razão da falha.', installWarn: 'O acesso externo não foi habilitado, o que impede que o aplicativo seja acessado via redes externas. Deseja continuar?', showIgnore: 'Exibir aplicativos ignorados', @@ -3638,7 +3519,6 @@ const message = { ftpHelper: 'Após criar um site, uma conta FTP correspondente será criada e o diretório FTP será vinculado ao diretório do site.', remark: 'Observação', - manageGroup: 'Gerenciar grupos', groupSetting: 'Gerenciamento de grupos', createGroup: 'Criar grupo', appNew: 'Novo Aplicativo', @@ -3702,7 +3582,6 @@ const message = { nginxPer: 'Ajuste de desempenho', neverExpire: 'Nunca', setDefault: 'Definir como padrão', - default: 'Padrão', deleteHelper: 'O status do aplicativo relacionado está anômalo, por favor verifique', toApp: 'Ir para a lista de aplicativos instalados', cycle: 'Ciclo', @@ -3817,8 +3696,6 @@ const message = { proxyHelper1: 'Ao acessar este diretório, o conteúdo da URL de destino será retornado e exibido.', proxyPassHelper: 'A URL de destino deve ser válida e acessível.', proxyHostHelper: 'Passe o nome de domínio no cabeçalho da requisição para o servidor proxy.', - replacementHelper: - 'Até 5 substituições podem ser adicionadas, deixe em branco se não houver substituição necessária.', modifier: 'Regras de correspondência', modifierHelper: 'Exemplo: "=" é correspondência exata, "~" é correspondência regular, "^~" corresponde ao início do caminho, etc.', @@ -3930,7 +3807,6 @@ const message = { subsite: 'Subsite', subsiteHelper: 'Um subsite pode selecionar o diretório de um site PHP ou estático existente como seu diretório raiz.', - parentWebsite: 'Site Pai', deleteSubsite: 'Para excluir o site atual, você deve primeiro excluir o subsite {0}.', loadBalance: 'Balanceamento de Carga', server: 'Nó', @@ -3961,7 +3837,6 @@ const message = { cacheExpire: 'Tempo de Expiração do Cache', shareCacheHelper: '1M de memória pode armazenar aproximadamente 8000 objetos de cache.', cacheLimitHelper: 'Exceder o limite excluirá automaticamente os caches antigos.', - cacheExpireHelper: 'Caches não acessados dentro do tempo de expiração serão excluídos.', realIP: 'IP Real', ipFrom: 'Fonte do IP', ipFromHelper: @@ -4024,8 +3899,6 @@ const message = { syncHtmlHelper: 'Sincronizar com PHP e sites estáticos', wafValueHelper: 'Valor', parentWbeiste: 'Site pai', - shareCahe: 'Tamanho de memória da contagem de cache', - shareCaheHelper: 'Aproximadamente 8000 objetos de cache podem ser armazenados por 1M de memória', cacheExpireJHelper: 'O cache será excluído se não houver acesso após o tempo de expiração', }, php: { @@ -4059,26 +3932,26 @@ const message = { extensionsHelper: 'Para várias extensões, separe por vírgulas', }, nginx: { - serverNamesHashBucketSizeHelper: 'The hash table size of the server name', - clientHeaderBufferSizeHelper: 'The header buffer size requested by the client', - clientMaxBodySizeHelper: 'Maximum Upload File', - keepaliveTimeoutHelper: 'Connection Timeout', - gzipMinLengthHelper: 'Minimum Compressed File', - gzipCompLevelHelper: 'Compression Rate', - gzipHelper: 'Enable compression for transmission', - connections: 'Active connections', + serverNamesHashBucketSizeHelper: 'Tamanho da tabela hash dos nomes de servidor', + clientHeaderBufferSizeHelper: 'Tamanho do buffer de cabeçalho solicitado pelo cliente', + clientMaxBodySizeHelper: 'Tamanho máximo de upload', + keepaliveTimeoutHelper: 'Tempo limite da conexão', + gzipMinLengthHelper: 'Tamanho mínimo para compressão', + gzipCompLevelHelper: 'Nível de compressão', + gzipHelper: 'Ativar compressão na transmissão', + connections: 'Conexões ativas', accepts: 'Accepts', handled: 'Handled', requests: 'Requests', reading: 'Reading', writing: 'Writing', waiting: 'Waiting', - status: 'Current Status', - configResource: 'Configuration', - saveAndReload: 'Save and reload', - clearProxyCache: 'Clean reverse proxy cache', + status: 'Status atual', + configResource: 'Configuração', + saveAndReload: 'Salvar e recarregar', + clearProxyCache: 'Limpar cache do proxy reverso', clearProxyCacheWarn: - 'All websites that have configured with cache will be affected and "OpenResty" will be restarted. Do you want to continue?', + 'Todos os sites com cache configurado serão afetados e o "OpenResty" será reiniciado. Deseja continuar?', create: 'Criar Módulo', update: 'Editar Módulo', params: 'Parâmetros', @@ -4112,7 +3985,7 @@ const message = { 'Script a ser executado antes da compilação, geralmente para baixar o código-fonte do módulo, instalar dependências, etc.', buildHelper: 'Módulos dinâmicos são carregados pela configuração após a compilação; módulos estáticos ainda recompilam o OpenResty.', - defaultHttps: 'HTTPS Anti-tampering', + defaultHttps: 'Proteção contra adulteração HTTPS', defaultHttpsHelper1: 'A ativação desta opção pode resolver problemas de adulteração HTTPS.', sslRejectHandshake: 'Rejeitar handshake SSL padrão', sslRejectHandshakeHelper: @@ -4412,7 +4285,6 @@ const message = { netRecv: 'Recebimento (downlink)', numConnections: 'Conexões', startTime: 'Hora de Início', - state: 'Estado', running: 'Executando', sleep: 'Dormindo', stop: 'Parado', @@ -4629,8 +4501,10 @@ const message = { scorePanelHTTPSDisabled: 'HTTPS do painel desativado', scoreSSHRootLogin: 'Login SSH como Root permitido', scoreSSHPasswordAuth: 'Autenticação por senha SSH ativada sem autenticação por chave', + scoreSSLExpired: 'O certificado {0} expirou', scoreSSLHigh: 'Certificado {0} expira em {1} dias', scoreSSLMedium: 'Certificado {0} expira em {1} dias', + scoreWebsiteExpired: 'O site {0} expirou', scoreWebsiteExpire: 'Site {0} expira em {1} dias', scoreWebsiteHTTP: '{0} não utiliza HTTPS', scoreWebsiteStopped: 'Status de {0} anormal', @@ -4677,6 +4551,7 @@ const message = { panelLogin: 'Login do painel', sshLogin: 'Login SSH', failedRecord: 'Registros com falha', + expired: 'Expirado', expiredDays: 'Expirado há {0} dias', remainingDays: '{0} · {1} dias restantes', enabled: 'Ativado', @@ -4943,9 +4818,9 @@ const message = { abnormalSites: 'Sites anormais', count5xxSource: 'Contagem por requisições 5xx', wafIntercept: 'Bloqueios WAF', - highRiskHit: 'Detecções de alto risco', websiteMonitorDisabledOrNoData: 'Monitoramento de sites desativado ou sem dados disponíveis', wafDisabledOrNoData: 'WAF desativado ou sem dados de bloqueio disponíveis', + serviceEnabledButAbnormal: 'Ativado, mas em estado anormal', noWafData: 'Nenhum dado de bloqueio WAF', sourceIP: 'IP de origem', hitCount: 'Detecções', @@ -5006,6 +4881,7 @@ const message = { successRate: 'Taxa de sucesso', failedJobs: 'Tarefas com falha', recentRecoveryPoint: 'Último ponto de recuperação', + disabledCronjobTasks: 'Tarefas agendadas desativadas', remoteCoverage: 'Cobertura remota', recent7Days: 'Últimos 7 dias', taskTypeStats: 'Estatísticas por tipo de tarefa', @@ -5027,6 +4903,7 @@ const message = { cronjobReasonDisabled: '{0} tarefas desativadas', cronjobReasonLocalOnlyBackup: '{0} backups somente locais', cronjobReasonNormal: 'A execução das tarefas e a cobertura de backup estão normais', + riskLow: 'Baixo risco', viewFailedRecords: 'Ver tarefas com falha', viewCronjobTasks: 'Ver tarefas agendadas', checkBackupTasks: 'Verificar tarefas de backup', @@ -5128,6 +5005,14 @@ const message = { authManage: 'Gerenciamento de autenticação', auth: { providerNavigation: 'Provedores de autenticação', + defaultNode: 'Nó padrão', + defaultNodePlaceholder: 'Selecione um nó', + defaultNodeHelper: 'Somente para novos usuários.', + defaultNodeRequired: 'Selecione um nó padrão válido.', + nodesLoadFailed: 'Falha ao carregar os nós. Tente novamente antes de selecionar o nó padrão.', + nodeHandling: 'Tratamento do nó', + assignDefaultNode: 'Atribuir nó padrão: {node}', + keepExistingNode: 'Manter as permissões de nó existentes', providers: { ldap: 'AD/LDAP', passkey: 'Passkey', @@ -5155,7 +5040,413 @@ const message = { planned: 'Planejado', plannedTitle: 'Configurações de autenticação {0}', plannedDesc: 'Este provedor de autenticação está planejado e ainda não está disponível.', + oidc: { + accessMode: 'Modo de conexão', + accessModeDesc: 'Use o Discovery padrão sempre que o provedor de identidade oferecer suporte.', + actionCreate: 'Criar usuário', + actionKeepName: 'Mantenha o nome de usuário atual', + actionPending: 'Aguardando resultado', + actionReject: 'Rejeitar login', + actionUpdate: 'Atualizar informações de identidade', + advanced: 'Configurações avançadas', + advancedDesc: + 'Mantenha os padrões seguros, a menos que o provedor exija uma opção de compatibilidade.', + assignDefaultRole: 'Atribuir função padrão: {role}', + authorizationEndpoint: 'Authorization Endpoint', + authorizationEndpointInvalid: 'Insira um Authorization Endpoint válido.', + authorizationFlow: 'Fluxo de autorização', + automatic: 'Automático', + automaticPolicy: 'Política de tratamento automático', + automaticPolicyDesc: 'Essas regras são aplicadas pelo back-end e não são opções de administrador.', + basic: 'Configurações básicas', + basicDesc: 'Selecione o modo do provedor e configure o cliente e o retorno de chamada.', + browserTest: 'Teste de login no navegador', + browserTestConflict: 'Identidade verificada, mas o nome de usuário está em conflito', + browserTestConflictHelper: + 'O nome de usuário mapeado pertence a outra identidade e não será reivindicado.', + browserTestExpired: 'O teste do navegador expirou', + browserTestExpiredHelper: + 'Inicie um novo teste do navegador e conclua a autorização antes que ela expire.', + browserTestFailed: 'Falha no teste do navegador', + browserTestFailedHelper: + 'A visualização da identidade não pôde ser concluída. Revise o erro de back-end localizado.', + browserTestIsolation: + 'Isso executa um fluxo real de autorização de ida e volta, mas não cria nem atualiza usuários, não atribui funções e não cria uma sessão autenticada do painel.', + browserTestPopupBlocked: 'Permita pop-ups para este site e reinicie o teste do navegador.', + browserTestPopupClosed: 'A janela de autorização foi fechada antes da conclusão do teste.', + browserTestSuccess: 'Verificação Provider bem-sucedida', + browserTestSuccessHelper: + 'O mapeamento de identidade foi visualizado sem alterar usuários ou sessões.', + browserTestTitle: 'Login de teste do navegador OIDC', + browserTestWaiting: 'Aguardando autorização Provider', + browserTestWaitingHelper: + 'Conclua o login na nova janela do navegador. Esta página será atualizada automaticamente.', + callbackCopied: 'Retorno de chamada OIDC URL copiado.', + callbackURL: 'Retorno de chamada URL', + callbackURLHelper: + 'Adicione esta URL às URLs de retorno permitidas do cliente no provedor de identidade.', + cancelClearSecret: 'Cancelar limpeza', + clearSecret: 'Limpar segredo', + clearSecretConfirm: 'O Client Secret será removido somente após você salvar. Continuar?', + clientAuthMethod: 'Método de autenticação do cliente', + clientAuthMethodHelper: + 'Selecione o método de autenticação configurado para este cliente no provedor de identidade.', + clientAuthMethodRequired: 'Selecione um método de autenticação do cliente.', + clientID: 'Client ID', + clientIDRequired: 'Insira o Client ID.', + clientSecret: 'Client Secret', + clockSkew: 'Tolerância de tempo do token', + clockSkewHelper: + 'Permite uma pequena diferença de horário entre o provedor de identidade e o 1Panel. Mantenha o padrão de 60 segundos.', + clockSkewRequired: 'Insira a tolerância de tempo do token.', + compatibilityMode: 'Modo de compatibilidade', + compatibilityModeHelper: + 'Use apenas para Discovery incompletos ou endpoints reescritos. A validação do núcleo OIDC permanece habilitada.', + configurationFailedHelper: 'O teste falhou. A página exibe apenas o erro de back-end localizado.', + configurationFailedTag: 'Falha no teste', + configurationHighRiskPassed: + 'A configuração foi aprovada, mas contém opções de compatibilidade de alto risco.', + configurationHighRiskTag: 'Configuração de alto risco aprovada', + configurationNotTested: 'A configuração atual não foi testada.', + configurationNotTestedTag: 'Não testado', + configurationPassed: 'A configuração atual passou nas verificações de segurança e capacidade.', + configurationPassedTag: 'Teste aprovado', + configurationStaleHelper: 'A configuração foi alterada. Teste-a novamente antes de salvar.', + configurationStaleTag: 'Resultado expirou', + configurationTestMeta: + 'Testado em {time}; concluído em {duration} ms. As respostas Provider brutas não são armazenadas.', + configurationTestResult: 'Resultado do teste de configuração', + configurationTestResultDesc: + 'Isso verifica apenas Discovery e recursos; não troca código de autorização nem comprova o Client Secret. Use o login de teste do navegador para verificação ponta a ponta.', + configurationTestSuccess: 'O teste de configuração do OIDC foi bem-sucedido.', + configurationTesting: 'Testando a configuração atual do OIDC…', + configurationTestingTag: 'Teste', + configureSecret: 'Configurar segredo', + conflictExistingRename: 'Um subject vinculado retorna um novo name que está ocupado', + conflictExistingRenameResult: + 'Mantenha o User.Name existente e permita que o usuário vinculado faça login', + conflictLDAP: 'Usuário LDAP', + conflictLocal: 'Usuário local', + conflictNewAvailable: 'O novo subject e o name mapeado estão disponíveis', + conflictNewAvailableResult: 'Crie um usuário corporativo e atribua a função padrão', + conflictNone: 'Sem conflito', + conflictOIDC: 'Outra identidade OIDC', + conflictOccupied: 'O name mapeado pertence a uma identidade local, LDAP ou outra identidade OIDC', + conflictOccupiedResult: 'Rejeite a nova identidade; nunca vincule ou mescle automaticamente', + conflictType: 'Tipo de conflito', + connectionSecurity: 'Segurança de conexão', + connectionSecurityDesc: + 'A política TLS se aplica às solicitações Discovery, Token, JWKS e UserInfo.', + connectionTest: 'Teste de conexão e configuração', + connectionTestCompatibilityDesc: + 'Valide os endpoints personalizados e a política de segurança do protocolo.', + connectionTestStandardDesc: 'Endpoints e recursos são descobertos automaticamente no Issuer.', + connectionTestTab: 'Teste de conexão', + customCA: 'CA personalizado', + customCAHelper: 'Aplica-se somente a esta fonte de autenticação e nunca é gravado em logs.', + customCARequired: 'Forneça o certificado CA personalizado.', + defaultRole: 'Função padrão', + defaultRoleHelper: + 'Atribuída somente na primeira criação do usuário; logins posteriores não alteram a função.', + defaultRolePlaceholder: 'Selecione uma função', + defaultRoleRequired: 'Selecione uma função padrão válida.', + disableAfterSave: 'OIDC será desativado após salvar.', + disableConfirm: + 'Desativar OIDC invalida imediatamente o acesso dos usuários desta fonte. Continuar?', + disableDiscardConfirm: + 'Desabilitar o OIDC é uma ação emergencial: apenas fecha a entrada de login e invalida imediatamente o acesso dos usuários desta fonte. Outras alterações não salvas nesta página, incluindo alterações no Client Secret, serão descartadas. Continuar?', + disableTitle: 'Desativar OIDC', + disabled: 'Desativado', + discoveryAllowlist: 'Discovery ∩ lista de permissões de segurança', + enable: 'Ativar', + enableAfterSave: 'OIDC será habilitado após um salvamento bem-sucedido.', + enabled: 'Ativado', + endSessionEndpoint: 'End Session Endpoint', + endSessionEndpointHelper: + 'Salvo para uso futuro; O logout iniciado pelo Provider não está incluído nesta versão.', + endSessionEndpointInvalid: 'Insira um End Session Endpoint válido.', + endpointDiscoveryPlaceholder: 'Exibido após o teste de conexão', + firstLogin: 'Primeiro login', + firstLoginPolicy: 'Crie um usuário corporativo local e atribua a função padrão configurada.', + fixedAuthorizationCode: 'Authorization Code Flow', + fixedNoTokenPersistence: 'Tokens, Claims e verifier nunca são persistidos', + fixedSecurityPolicy: 'Sempre aplicado; nenhuma configuração necessária', + fixedStateNonce: 'state e nonce únicos', + fixedTokenValidation: 'Assinatura ID Token e validação Claims', + highRiskSaveConfirm: + 'Esta configuração habilitada contém opções de compatibilidade de alto risco. Confirme se o ambiente isolado os exige.', + highRiskTitle: 'Configuração OIDC de alto risco', + hs256Compatibility: 'HS256 (compatibilidade)', + hs256KeyHelper: + 'HS256 sempre usa o Client Secret desta fonte e não aceita uma chave de assinatura separada.', + hs256Warning: + 'HS256 usa um segredo simétrico compartilhado para assinaturas ID Token. Use-o somente quando o Provider não puder usar um algoritmo assimétrico.', + identityBindingPolicy: + 'A identidade é fixada por AuthSourceID + issuer + subject. Uma coincidência de nome de usuário nunca vincula outra conta.', + identityMissing: 'Identidade inativa', + issuer: 'Issuer URL', + issuerHelper: + 'O valor iss de ID Token e Discovery issuer devem corresponder exatamente a esse valor.', + issuerInvalid: 'Insira um HTTP ou HTTPS Issuer URL válido sem consulta ou fragmento.', + issuerRequired: 'Insira o Issuer URL.', + jwksRotation: 'Rotação automática JWKS', + jwksURI: 'JWKS URI', + jwksURIHelper: 'Necessário para assinatura assimétrica quando a origem da chave é JWKS.', + jwksURIInvalid: 'Insira um JWKS URI válido para a fonte de chave de assinatura selecionada.', + keepExistingRole: 'Mantenha as funções e permissões locais existentes', + localSecurityData: 'Dados de segurança local', + localSecurityDataPolicy: 'Nunca substitua funções, MFA, API Keys, Passkeys ou permissões locais.', + localCredentialsManaged: + 'O nome de usuário e a senha local são gerenciados pelo OIDC e não podem ser editados aqui. Funções, permissões, MFA, API Keys e Passkeys permanecem locais.', + localUserFields: 'Campos de usuário local', + localUserFieldsDesc: + 'A primeira versão mapeia apenas User.Name e não usa uma expressão de mapeamento JSON.', + loginWith: 'Entrar com {provider}', + manualEndpoints: 'Endpoints personalizados', + manualEndpointsDesc: + 'Use somente quando Discovery estiver incompleto ou um gateway upstream reescrever endpoints.', + mappingResult: 'Resultado do mapeamento', + mode: 'Modo de conexão', + modeRequired: 'Selecione um modo de conexão.', + nameClaim: 'Claim de nome de usuário', + nameClaimHelper: 'Informe o campo que contém o nome de usuário, como preferred_username.', + nameClaimRequired: 'Insira o Claim de nome de usuário.', + nameConflict: 'Política de conflito de nomes', + panelURL: '1Panel público URL', + panelURLHTTPWarning: + 'HTTP não protege a resposta de autorização. Use-o apenas em um ambiente privado isolado aceito pelo Provider.', + panelURLHelper: + 'Informe o endereço usado para acessar o 1Panel. Ele será usado para gerar a URL de retorno.', + panelURLInvalid: 'Insira uma origem contendo apenas esquema, host e porta opcional.', + panelURLRequired: 'Insira o 1Panel público URL.', + pkceDisabled: 'Desativado (somente compatibilidade)', + pkceDisabledWarning: + 'A desativação do PKCE reduz a proteção contra interceptação de código de autorização.', + pkceHelper: 'Prefira S256. O método de desafio plain nunca é oferecido.', + pkceS256: 'S256 (recomendado)', + plannedHandling: 'Manuseio planejado', + privateNetworkIdP: 'IdP de rede privada', + privateNetworkIdPHelper: + 'Permite explicitamente endereços privados; metadados, loopback, link local, redirecionamentos e religação DNS permanecem bloqueados.', + privateNetworkWarning: 'O acesso à rede privada está habilitado para esta fonte de autenticação.', + protocolCompatibility: 'Compatibilidade de protocolo', + protocolCompatibilityDesc: 'A validação da assinatura ID Token nunca pode ser desativada.', + providerAndClient: 'Provider e cliente', + providerAndClientDesc: + 'O Client Secret só pode ser substituído ou apagado e nunca é devolvido pela página.', + providerCapabilities: 'Capacidades do Provider', + recentTestSuccess: 'Último teste bem-sucedido: {0}', + recommended: 'Recomendado', + rejectPlain: 'plain rejeitado', + replaceSecret: 'Substituir segredo', + requestAndClaims: 'Solicitações e atributos', + requestAndClaimsDesc: + 'Configure os escopos de autorização, o complemento de informações do usuário e os parâmetros da solicitação.', + requestTimeout: 'Tempo limite da solicitação', + requestTimeoutRequired: 'Insira o tempo limite da solicitação.', + restore: 'Restaurar', + restored: 'As últimas configurações salvas do OIDC foram restauradas.', + result: 'Resultado', + rolesLoadFailed: + 'Não foi possível carregar as funções. Tente novamente antes de selecionar a função padrão.', + roleHandling: 'Manipulação de funções', + scenario: 'Cenário', + scopes: 'Escopos de autorização', + scopesHelper: 'Deve incluir openid. Separe vários escopos com espaços.', + scopesRequired: 'Scopes deve incluir openid.', + seconds: 'segundos', + secretClearHelper: + 'Após a limpeza, um novo Client Secret é necessário antes que o OIDC possa ser ativado novamente.', + secretConfigured: 'Configurado', + secretNotConfigured: 'Não configurado', + secretPlaceholder: 'Insira um novo Client Secret', + secretReplaceHelper: + 'O novo segredo substituirá o valor salvo ao salvar. Atualize também o Client Secret no Provider OIDC.', + secretRequiredHelper: 'Configure um Client Secret antes de ativar o OIDC.', + secretRequiredToEnable: 'Configure um Client Secret antes de ativar o OIDC.', + secretSavedHelper: + 'Armazenado de forma criptografada. Deixe em branco para manter o segredo atual.', + secretWaiting: 'Aguardando entrada', + secretWillClear: 'Será limpo', + secretWillReplace: 'Será substituído', + signingAlgorithm: 'Algoritmo de assinatura ID Token', + signingAlgorithmHelper: + 'Somente algoritmos na lista de permissões de segurança de back-end estão disponíveis.', + signingKey: 'Chave de assinatura', + signingKeyClientSecret: 'Client Secret (somente HS256)', + signingKeyJWKS: 'JWKS URI com rotação automática', + signingKeySource: 'Fonte de chave de assinatura', + signingKeySourceHelper: + 'Prefira JWKS. Uma chave pública estática não pode ser rotacionada automaticamente.', + signingKeyStatic: 'Chave pública estática JWK ou PEM', + standardDiscovery: 'Padrão OIDC Discovery', + standardDiscoveryDesc: '1Panel descobre endpoints e recursos e não armazena o documento bruto.', + standardMode: 'Modo padrão', + standardModeHelper: 'Descubra endpoints, recursos de assinatura e suporte PKCE do Issuer.', + standardProtocolPolicy: 'Política de protocolo padrão', + standardProtocolPolicyDesc: + 'Os recursos de assinatura são negociados automaticamente; nenhuma chave de assinatura é inserida aqui.', + staticSigningKey: 'Chave pública de assinatura estática', + staticSigningKeyHelper: + 'Somente material de chave pública é aceito. Gire-o manualmente quando a chave Provider mudar.', + staticSigningKeyPlaceholder: 'Cole uma chave pública JWK, JWKS JSON ou PEM', + staticSigningKeyRequired: 'Forneça a chave pública de assinatura estática.', + staticSigningKeyWarning: + 'Uma chave de assinatura estática não pode ser rotacionada automaticamente; atualize-a antes que o Provider gire as chaves.', + settingLoadFailed: 'As configurações do OIDC não puderam ser carregadas', + settingLoadFailedHelper: + 'O formulário é bloqueado para evitar salvar uma configuração padrão vazia sobre as configurações atuais. Tente novamente depois que a conexão for recuperada.', + subsequentLogin: 'Login subsequente', + subsequentLoginPolicy: + 'Encontre a ligação por subject e atualize apenas User.Name quando o novo nome estiver disponível.', + testBeforeBrowserTest: + 'Teste a configuração atual antes de iniciar um teste de login do navegador.', + testBeforeEnable: 'Teste a configuração atual antes de salvar as alterações de configuração.', + testConfiguration: 'Testar configuração', + testDiscovery: 'Testar Discovery', + tlsCustomCA: 'HTTPS · Certificado CA personalizado', + tlsPrivateHTTP: 'HTTP · Somente rede privada (perigoso)', + tlsPrivateHTTPWarning: + 'HTTP não fornece criptografia de transporte e é restrito a alvos privados explicitamente permitidos.', + tlsSkipVerify: 'HTTPS · Ignorar verificação de certificado (perigoso)', + tlsSystem: 'HTTPS · Verificação do certificado do sistema (recomendado)', + tokenEndpoint: 'Token Endpoint', + tokenEndpointInvalid: 'Insira um Token Endpoint válido.', + transportSecurity: 'Segurança de transporte', + transportSecurityHelper: + 'Prefira HTTPS. O HTTP privado também requer acesso explícito ao private-network.', + unsavedChanges: 'Há alterações de OIDC não salvas.', + usedClaim: 'Claim usado', + userInfoEndpoint: 'UserInfo Endpoint', + userInfoEndpointHelper: + 'Quando o campo de nome de usuário estiver ausente, o sistema o preencherá a partir deste endpoint. Deixe em branco para não preencher.', + userInfoEndpointInvalid: 'Insira um UserInfo Endpoint válido.', + userMapping: 'Configurações do usuário', + userMappingDesc: + 'Configure o mapeamento do nome de usuário OIDC e o nó e a função padrão usados ao criar um usuário no primeiro acesso.', + }, + saml2: { + actionCreate: 'Criar usuário', + actionPending: 'Aguardando resultado', + actionReject: 'Rejeitar login', + actionReuse: 'Usar usuário vinculado', + assignDefaultRole: 'Atribuir função padrão: {role}', + basic: 'Configurações básicas', + basicDesc: 'Configure as opções comuns exigidas pela maioria dos provedores SAML2.', + browserTest: 'Testar login', + browserTestConflict: 'Identidade verificada, mas o nome de usuário está em conflito', + browserTestConflictHelper: + 'O nome de usuário mapeado pertence a outra identidade e não será reivindicado.', + browserTestExpired: 'O teste do navegador expirou', + browserTestExpiredHelper: + 'Inicie um novo teste do navegador e conclua a autorização antes que ela expire.', + browserTestFailed: 'Falha no teste do navegador', + browserTestFailedHelper: + 'A visualização da identidade não pôde ser concluída. Revise o erro de back-end localizado.', + browserTestIsolation: + 'Isso executa um fluxo real de autorização de ida e volta, mas não cria nem atualiza usuários, não atribui funções e não cria uma sessão autenticada do painel.', + browserTestPopupBlocked: 'Permita pop-ups para este site e reinicie o teste do navegador.', + browserTestPopupClosed: 'A janela de autorização foi fechada antes da conclusão do teste.', + browserTestSuccess: 'Verificação Provider bem-sucedida', + browserTestSuccessHelper: + 'O mapeamento de identidade foi visualizado sem alterar usuários ou sessões.', + browserTestTitle: 'Login de teste do navegador SAML2', + browserTestWaiting: 'Aguardando autorização Provider', + browserTestWaitingHelper: + 'Conclua o login na nova janela do navegador. Esta página será atualizada automaticamente.', + certificateFileInvalid: 'Selecione um arquivo de certificado PEM, CRT ou CER válido.', + configured: 'Configurado', + configurationFailedHelper: 'O teste falhou. A página exibe apenas o erro de back-end localizado.', + configurationNotTested: 'A configuração atual não foi testada.', + configurationPassed: 'A configuração atual passou nas verificações de segurança e capacidade.', + configurationStaleHelper: + 'Configurações sensíveis à autenticação alteradas. Teste o rascunho atual novamente.', + configurationTestSuccess: 'O teste de configuração do SAML2 foi bem-sucedido.', + configurationTesting: 'Testando a configuração atual do SAML2…', + conflictLDAP: 'Usuário LDAP', + conflictLocal: 'Usuário local', + conflictNone: 'Sem conflito', + conflictOIDC: 'Outra identidade OIDC', + conflictSAML2: 'Outra identidade SAML2', + conflictType: 'Tipo de conflito', + credentialFileReadFailed: 'Não foi possível ler o arquivo de credenciais.', + credentialFileTooLarge: 'Os arquivos de credenciais não devem exceder 256 KiB.', + credentialsRequired: 'Configure a chave privada e o certificado do SP.', + defaultRole: 'Função do novo usuário', + defaultRoleHelper: + 'Atribuída apenas na primeira criação; logins posteriores preservam funções, MFA e permissões locais.', + defaultRolePlaceholder: 'Selecione uma função', + defaultRoleRequired: 'Selecione uma função padrão válida.', + disableConfirm: + 'Desativar o SAML2 rejeita imediatamente novos logins e invalida suas sessões de usuário. Continuar?', + disableDiscardConfirm: + 'Desativar o SAML2 descarta outras alterações não salvas nesta página e invalida imediatamente suas sessões de usuário. Continuar?', + disableTitle: 'Desativar SAML2', + disabled: 'Desativado', + enable: 'Ativar', + enabled: 'Ativado', + idpMetadata: 'Metadados do IdP', + idpMetadataDesc: 'Informe uma URL ou cole o XML. Se ambos existirem, a URL terá prioridade.', + keepExistingRole: 'Mantenha as funções e permissões locais existentes', + loginWith: 'Entrar com {provider}', + mappingResult: 'Resultado do mapeamento', + metadataRequired: 'Informe a URL ou o XML dos metadados do IdP.', + metadataURLHelper: 'O backend baixa e valida os metadados durante o teste e o salvamento.', + metadataURLInvalid: 'Insira uma URL HTTPS de metadados válida, sem credenciais nem fragmento.', + metadataURLRecommended: 'URL de metadados (recomendada)', + metadataXML: 'XML de metadados', + metadataXMLHelper: 'Use quando o IdP não expuser uma URL de metadados acessível.', + metadataXMLInvalid: 'Insira um XML de metadados EntityDescriptor válido.', + metadataXMLPlaceholder: 'Cole ...', + nameAttribute: 'Atributo de nome de usuário', + nameAttributeHelper: + 'Lê este atributo da asserção SAML verificada e o mapeia para o nome de usuário do 1Panel.', + nameAttributePlaceholder: 'Por exemplo: uid, username ou account', + nameAttributeRequired: 'Insira o atributo de nome de usuário.', + notConfigured: 'Não configurado', + or: 'ou', + pageDesc: 'Conecte o SSO corporativo por metadados do IdP com as opções comuns em uma página.', + plannedHandling: 'Manuseio planejado', + privateKeyFileInvalid: 'Selecione um arquivo de chave privada PEM válido.', + recentTestSuccess: 'Último teste bem-sucedido: {0}', + restore: 'Restaurar', + restored: 'As últimas configurações salvas do SAML2 foram restauradas.', + roleHandling: 'Manipulação de funções', + rolesLoadFailed: + 'Não foi possível carregar as funções. Tente novamente antes de selecionar a função padrão.', + selectFile: 'Selecionar arquivo', + serviceStatus: 'Status do serviço', + serviceStatusDesc: 'A configuração atual deve passar no teste antes de ativar o SAML2.', + settingLoadFailed: 'As configurações do SAML2 não puderam ser carregadas', + settingLoadFailedHelper: + 'O formulário é bloqueado para evitar salvar uma configuração padrão vazia sobre as configurações atuais. Tente novamente depois que a conexão for recuperada.', + spCertificate: 'Certificado do SP', + spCertificateHelper: + 'Publicado nos metadados do SP para que o IdP possa verificar solicitações de login e logout.', + spCredentials: 'Chave privada e certificado do SP', + spCredentialsDesc: + 'Usados para assinar mensagens de login e logout. A política de assinatura e validação é definida pelo backend.', + spPrivateKey: 'Chave privada do SP', + spPrivateKeyHelper: + 'Usada para assinar AuthnRequest e mensagens de logout. É criptografada em repouso e nunca exibida.', + syncLogout: 'Logout sincronizado', + syncLogoutHelper: + 'Sair do 1Panel ou do provedor de identidade também encerra a sessão do outro lado.', + testBeforeBrowserTest: + 'Teste a configuração atual antes de iniciar um teste de login do navegador.', + testBeforeEnable: 'Teste a configuração atual antes de ativar ou salvar alterações confidenciais.', + testConfiguration: 'Testar configuração', + unsavedChanges: 'Há alterações de SAML2 não salvas.', + usedAttribute: 'Mapeamento de nome de usuário', + usersAndRoles: 'Usuários e funções', + usersAndRolesDesc: + 'Configure o mapeamento do nome de usuário do painel e o nó e a função padrão usados ao criar um usuário no primeiro acesso.', + }, ldap: { + basic: 'Configurações básicas', + loginTitle: 'Login LDAP', + loginWith: 'Entrar com LDAP', + backToLocalLogin: 'Voltar ao login do painel', enable: 'Habilitar', enabled: 'Habilitado', disabled: 'Desativado', @@ -5377,6 +5668,7 @@ const message = { deleteConfirm: 'Excluir este registro e arquivo de exportação?', }, waf: { + WAF: 'WAF', name: 'WAF', blackWhite: 'Lista negra e branca', globalSetting: 'Configurações globais', @@ -6003,6 +6295,15 @@ const message = { 'Todos os pacotes de atualização de versões anteriores serão limpos. Continuar?', nodeUpgradeOfflinePackageHelper: 'Em ambientes offline, nós com arquiteturas diferentes devem enviar o pacote de atualização correspondente antes de atualizar.', + healthCheck: 'Verificação de Integridade', + healthCheckFrequency: 'Frequência da Verificação', + healthCheckFrequencyHelper: + 'Verifica periodicamente a integridade dos nós de backend. Digite 0 para desativar as verificações.', + healthCheckFrequencyLimit: + 'A frequência da verificação não pode exceder um dia e deve ser um número inteiro não negativo.', + loadFailedNodeResources: 'Carregar recursos de nós com falha', + loadFailedNodeResourcesHelper: + 'Ao abrir a lista de nós, carregue também as informações de recursos dos nós com falha.', nodeUnhealthy: 'Estado do nó anormal', deletedNode: 'O nó excluído {0} não suporta atualmente operações de atualização!', nodeUnhealthyHelper: @@ -6025,12 +6326,12 @@ const message = { addNode: 'Adicionar Nó', connInfo: 'Informações de Conexão', nodeInfo: 'Informações do Nó', - withProxy: 'Включить Доступ через Прокси', - withoutProxy: 'Отключить Доступ через Прокси', + withProxy: 'Ativar acesso por proxy', + withoutProxy: 'Desativar acesso por proxy', withProxyHelper: - 'Будет использовать системный прокси {0}, поддерживаемый в настройках панели, для доступа к дочерним узлам. Продолжить?', + 'O proxy do sistema {0}, mantido nas configurações do painel, será usado para acessar os nós secundários. Continuar?', withoutProxyHelper: - 'Прекратит использование системного прокси, поддерживаемого в настройках панели, для доступа к дочерним узлам. Продолжить?', + 'O uso do proxy do sistema mantido nas configurações do painel para acessar os nós secundários será interrompido. Continuar?', syncInfo: 'Sincronização de dados,', syncHelper: 'Quando os dados do nó mestre mudam, são sincronizados em tempo real para este nó filho,', syncBackupAccount: 'Configurações de conta de backup', @@ -6096,6 +6397,8 @@ const message = { offlineHelper: 'Usado quando o nó está em ambiente offline', appUpgrade: 'Atualização do Aplicativo', appUpgradeHelper: 'Existem {0} aplicativos que precisam ser atualizados', + dashboardSetting: 'Configurações da Visão Geral', + keepOneDashboardComponent: 'Mantenha pelo menos uma seção na visão geral', }, customApp: { name: 'Repositório de Aplicativos Personalizados', @@ -6127,9 +6430,9 @@ const message = { alert: { isAlert: 'Alerta', alertCount: 'Contagem de Alertas', - clamHelper: 'Dispara alerta via ao detectar arquivos infectados durante a varredura', - cronJobHelper: 'Dispara alerta via ao falhar na execução de tarefas', - licenseHelper: 'A edição comercial oferece suporte a alertas via', + clamHelper: 'Dispara um alerta ao detectar arquivos infectados durante a varredura', + cronJobHelper: 'Dispara um alerta quando a execução da tarefa falha', + licenseHelper: 'A edição comercial oferece suporte a mais recursos de alerta', alertCountHelper: 'Frequência máxima diária de alertas', alert: 'Alerta por SMS', logs: 'Registros de Alerta', @@ -6503,35 +6806,36 @@ const message = { cpu: 'CPU', memory: 'Memória', disk: 'Disco', - overview: 'Overview', - kvmUnavailable: 'No available KVM hardware virtualization capability was detected.', - kvmCheckCpu: 'Confirm that the host CPU supports Intel VT-x or AMD-V virtualization.', - kvmCheckBios: 'Enable virtualization options in BIOS/UEFI.', - kvmCheckModule: 'Confirm that the kvm, kvm_intel, or kvm_amd kernel module is loaded correctly.', + overview: 'Visão geral', + kvmUnavailable: 'Nenhum recurso de virtualização de hardware KVM disponível foi detectado.', + kvmCheckCpu: 'Confirme se a CPU do host oferece virtualização Intel VT-x ou AMD-V.', + kvmCheckBios: 'Ative as opções de virtualização no BIOS/UEFI.', + kvmCheckModule: 'Confirme se o módulo de kernel kvm, kvm_intel ou kvm_amd foi carregado corretamente.', kvmCheckDevice: - 'Confirm that /dev/kvm exists and the current environment is not a container or cloud host without KVM support.', - abnormal: 'Abnormal', - resourceOverview: 'Resource Overview', - cpuAllocated: 'CPU Allocated', - memoryAllocated: 'Memory Allocated', - storageUsed: 'Storage Used', - riskReminder: 'Risk Reminders', - noRisk: 'No risks', - runtimeHealth: 'Runtime Health', - runtimeAbnormal: 'VM runtime is abnormal', - noDependency: 'No dependency check data', - storageOverview: 'Storage Overview', - totalAllocated: 'Calculated by total VM configuration', - runningAllocated: 'Running allocation: {0}', - storageAvailable: 'Available: {0}', - inProgress: 'In progress', - needAttention: 'Needs attention', + 'Confirme se /dev/kvm existe e se o ambiente atual não é um contêiner nem um host de nuvem sem suporte a KVM.', + abnormal: 'Anormal', + resourceOverview: 'Visão geral de recursos', + cpuAllocated: 'CPU alocada', + memoryAllocated: 'Memória alocada', + storageUsed: 'Armazenamento usado', + riskReminder: 'Alertas de risco', + noRisk: 'Sem riscos', + runtimeHealth: 'Integridade do ambiente', + runtimeAbnormal: 'O ambiente de execução da VM está anormal', + noDependency: 'Sem dados de verificação de dependências', + storageOverview: 'Visão geral do armazenamento', + totalAllocated: 'Calculado pela configuração total das VMs', + runningAllocated: 'Alocação em execução: {0}', + storageAvailable: 'Disponível: {0}', + inProgress: 'Em andamento', + needAttention: 'Requer atenção', normal: 'Normal', - environmentRisk: 'The VM runtime is not ready. Fix dependencies or virtualization services.', - storageRisk: 'Storage pool {0} usage has reached {1}%.', - abnormalRisk: '{0} VMs are in an abnormal state.', - pausedRisk: '{0} VMs are paused.', - memoryRisk: 'VM memory allocation has reached {0}%.', + environmentRisk: + 'O ambiente de execução da VM não está pronto. Corrija as dependências ou os serviços de virtualização.', + storageRisk: 'O uso do pool de armazenamento {0} atingiu {1}%.', + abnormalRisk: '{0} VMs estão em estado anormal.', + pausedRisk: '{0} VMs estão pausadas.', + memoryRisk: 'A alocação de memória das VMs atingiu {0}%.', cpuLimitHelper: 'CPU disponível no momento: {0} núcleos', cpuLimitExceeded: 'CPU excede o limite. Máximo disponível no momento: {0} núcleos.', memoryLimitHelper: 'Memória alocável no momento: {0} (o host deve reservar {1} de memória)', @@ -6540,11 +6844,11 @@ const message = { storageLimitExceeded: 'A capacidade do disco excede o limite. Máximo disponível no momento: {0}.', iso: 'ISO', createFromTemplate: 'Criar a partir de modelo', - template: 'Template', - templateName: 'Template Name', - convertToTemplate: 'Convert to Template', - sourceVM: 'Source VM', - templateSize: 'Template Size', + template: 'Modelo', + templateName: 'Nome do modelo', + convertToTemplate: 'Converter em modelo', + sourceVM: 'VM de origem', + templateSize: 'Tamanho do modelo', deleteTemplateConfirm: 'Excluir modelo {0}. Esta operação não pode ser desfeita. Continuar?', orphanClean: 'Limpeza de dados órfãos', orphanScan: 'Verificar novamente', @@ -6588,21 +6892,21 @@ const message = { available: 'Disponível', vmCount: 'VMs Vinculadas', usedIPs: 'IPs Usados', - monitor: 'Monitor', - monitorNotReady: 'The virtual machine is not running. Monitoring data is unavailable.', - monitorLoadFailed: 'Failed to get VM monitoring data.', - monitorLoadFailedWithReason: 'Failed to get VM monitoring data: {0}', - rename: 'Rename', + monitor: 'Monitoramento', + monitorNotReady: 'A máquina virtual não está em execução. Os dados de monitoramento não estão disponíveis.', + monitorLoadFailed: 'Falha ao obter os dados de monitoramento da VM.', + monitorLoadFailedWithReason: 'Falha ao obter os dados de monitoramento da VM: {0}', + rename: 'Renomear', newName: 'Novo nome', - renameHelper: 'Enter a new VM name. The VM must be shut down before renaming.', - renameConfirm: 'Rename virtual machine [{0}] to [{1}]?', - renameRunningHelper: 'Shut down the virtual machine before renaming it.', - cpuUsage: 'CPU Usage', - memoryUsage: 'Memory Usage', - diskIO: 'Disk IO', - networkIO: 'Network IO', - diskReadWrite: 'Disk Read / Write', - networkRxTx: 'Network RX / TX', + renameHelper: 'Digite um novo nome para a VM. Ela deve estar desligada antes de ser renomeada.', + renameConfirm: 'Renomear a máquina virtual [{0}] para [{1}]?', + renameRunningHelper: 'Desligue a máquina virtual antes de renomeá-la.', + cpuUsage: 'Uso de CPU', + memoryUsage: 'Uso de memória', + diskIO: 'E/S de disco', + networkIO: 'E/S de rede', + diskReadWrite: 'Leitura / Gravação em disco', + networkRxTx: 'RX / TX de rede', rx: 'RX', tx: 'TX', console: 'Console', @@ -6611,15 +6915,17 @@ const message = { consoleConnectFailed: 'Falha ao conectar ao console VNC. Verifique o serviço de proxy do console.', consoleCredentialsRequired: 'O console VNC requer credenciais. Verifique a configuração do proxy backend.', snapshot: 'Snapshot', - createSnapshot: 'Create Snapshot', - recoverSnapshot: 'Recover Snapshot', + createSnapshot: 'Criar snapshot', + recoverSnapshot: 'Restaurar snapshot', snapshotSize: 'Uso', - currentSnapshot: 'Current', - snapshotEmpty: 'No snapshots', + currentSnapshot: 'Atual', + snapshotEmpty: 'Nenhum snapshot', snapshotHelper: - 'A snapshot saves the current VM state as a restore point. Subsequent data changes are recorded in a delta file without changing the original disk. Restoring a snapshot returns the VM to that point in time.', + 'Um snapshot salva o estado atual da VM como ponto de restauração. As alterações posteriores são registradas em um arquivo delta sem modificar o disco original. Restaurar um snapshot devolve a VM a esse estado.', + snapshotOperationHelper: + 'O snapshot atual não pode ser excluído. Snapshots só podem ser restaurados quando a máquina virtual estiver desligada.', snapshotRecoverConfirm: - 'Recover virtual machine [{1}] to snapshot [{0}]? The VM disk will be restored to the snapshot state.', + 'Restaurar a máquina virtual [{1}] para o snapshot [{0}]? O disco da VM será restaurado ao estado do snapshot.', interface: 'Interface de Rede', device: 'Dispositivo', path: 'Caminho', diff --git a/frontend/src/lang/modules/ru.ts b/frontend/src/lang/modules/ru.ts index b2d86baf5..8f70ef9a9 100644 --- a/frontend/src/lang/modules/ru.ts +++ b/frontend/src/lang/modules/ru.ts @@ -11,6 +11,7 @@ const message = { button: { run: 'Запустить', add: 'Добавить', + select: 'Выбрать', save: 'Сохранить', set: 'Настройки', sync: 'Синхронизировать', @@ -29,7 +30,6 @@ const message = { selectAll: 'Выбрать все', login: 'Войти', close: 'Закрыть', - off: 'Закрыть', stop: 'Остановить', start: 'Запустить', view: 'Просмотр', @@ -54,6 +54,7 @@ const message = { power: 'Отправить', search: 'Поиск', refresh: 'Обновить', + reconnect: 'Переподключиться', get: 'Получить', upgrade: 'Обновить', update: 'Обновить', @@ -119,6 +120,9 @@ const message = { card: 'Карточка', table: 'Таблица', status: 'Статус', + statusSuccess: 'Успешно', + statusFailed: 'Ошибка', + statusWaiting: 'Ожидание...', records: 'Записи', group: 'Группа', createdAt: 'Время создания', @@ -163,6 +167,7 @@ const message = { deleteSuccess: 'Успешно удалено', loginSuccess: 'Успешный вход', operationSuccess: 'Операция выполнена успешно', + operationFailed: 'Не удалось выполнить операцию', copySuccess: 'Успешно скопировано', notSupportOperation: 'Эта операция не поддерживается', requestTimeout: 'Время запроса истекло, попробуйте позже', @@ -206,6 +211,7 @@ const message = { username: 'пользователя', password: 'Пароль', passkey: 'Вход по passkey', + otherLoginMethods: 'Другие способы входа', welcome: 'Добро пожаловать, введите имя пользователя и пароль для входа!', errorAuthInfo: 'Введенное имя пользователя или пароль неверны, пожалуйста, введите заново!', errorMfaInfo: 'Неверная информация аутентификации, попробуйте еще раз!', @@ -285,6 +291,9 @@ const message = { length128Err: 'Длина не может превышать 128 символов', maxLength: 'Длина не может превышать {0} символов', alias: 'Поддерживает английский, цифры, - и _, длина 1-128, и не может начинаться или заканчиваться на -_.', + vmName: 'Допустимы латинские буквы, цифры, ".", "-" и "_"; длина: 1-64; значение должно начинаться с буквы или цифры.', + vmNetwork: + 'Допустимы латинские буквы, цифры, ".", ":", "-" и "_"; длина: 1-64; значение должно начинаться с буквы или цифры.', }, res: { paramError: 'Запрос не удался, попробуйте позже!', @@ -303,7 +312,6 @@ const message = { success: 'Успешно', waiting: 'Ожидание', waitForUpgrade: 'Ожидание Обновления', - waiting1: 'Ожидание', failed: 'Ошибка', stopped: 'Остановлен', error: 'Ошибка', @@ -327,7 +335,6 @@ const message = { deny: 'Отказано', accept: 'Принято', used: 'Используется', - unUsed: 'Не используется', starting: 'Запуск', recreating: 'Пересоздание', creating: 'Создание', @@ -468,7 +475,7 @@ const message = { cpuSteal: 'Steal', cpuTop: 'Топ 5 Процессов по Использованию ЦПУ', memTop: 'Топ 5 Процессов по Использованию Памяти', - loadAverage: 'Средняя нагрузка за последнюю минуту | Средняя нагрузка за последние {n} минут', + loadAverage: 'Средняя нагрузка за последние {0} мин.', load: 'Нагрузка', mount: 'Точка монтирования', fileSystem: 'Файловая система', @@ -504,6 +511,7 @@ const message = { deleteBackupHelper: 'Удалить резервные копии базы данных одновременно', delete: 'Операция удаления не может быть отменена, пожалуйста, введите "', deleteHelper: '" для удаления этой базы данных', + deleteUserHelper: '" для удаления этого пользователя', userBoundDatabases: 'имеет доступ к следующим базам данных:', noMysql: 'Сервис базы данных (MySQL или MariaDB)', noPostgresql: 'Сервис базы данных PostgreSQL', @@ -551,6 +559,7 @@ const message = { revokeAuthorizationHelper: 'Отозвать у пользователя {0} доступ к базе данных {1}?', supplementPassword: 'Добавить пароль', supplementPasswordHelper: 'Сохраняет текущий пароль только в 1Panel и не изменяет пароль в MySQL.', + noUserBind: 'Нет привязки', pgBindHelper: 'Эта операция используется для создания нового пользователя и привязки его к целевой базе данных. В настоящее время выбор уже существующих пользователей в базе данных не поддерживается.', pgSuperUser: 'Суперпользователь', @@ -585,7 +594,6 @@ const message = { initialDB: 'Исходная База Данных', formatHelper: 'Текущая кодировка базы данных - {0}, несоответствие кодировок может привести к ошибке восстановления', - selectFile: 'Выбрать файл', dropHelper: 'Вы можете перетащить загружаемый файл сюда или', clickHelper: 'нажмите для загрузки', supportUpType: @@ -995,9 +1003,6 @@ const message = { failureCount: 'Ошибки', lastError: 'Последняя ошибка', modelMap: 'Сопоставление моделей', - apiKeyKeepEmpty: 'API Key (оставьте пустым, чтобы не менять)', - apiKeyOnceHint: 'API Key отображается только один раз после создания. Скопируйте и сохраните его сейчас.', - apiKeyOnceSave: 'API Key отображается только один раз. Сохраните его сейчас:', qpsLimit: 'Лимит QPS', tokenLimit: 'Лимит Token', tokenUsed: 'Использовано Token', @@ -1139,23 +1144,23 @@ const message = { modelGroupGuide: 'Группы моделей содержат имена моделей, доступные клиентам AI-шлюза. Upstream-модели настраиваются в сопоставлении моделей пула аккаунтов. auto — виртуальное имя и не добавляется в группу моделей.', modelGroupModelCount: '{0} моделей', - contentCompliance: 'Content Compliance', - contentAction: 'Action', - actionBlock: 'Block', - actionAuditOnly: 'Audit only', + contentCompliance: 'Соответствие содержимого', + contentAction: 'Действие', + actionBlock: 'Блокировать', + actionAuditOnly: 'Только аудит', actionDropHistory: 'Удалить историю', - severity: 'Severity', - severityHigh: 'High', - severityMedium: 'Medium', - severityLow: 'Low', - sensitiveWord: 'Sensitive word', - sensitiveGroup: 'Sensitive word group', - sensitiveWordCount: 'Words', - normalizedWord: 'Normalized word', - matchedWords: 'Matched words', - matchedGroups: 'Matched groups', - importResult: 'Imported {0}, duplicated {1}, invalid {2}', - auditLogs: 'Audit Logs', + severity: 'Серьёзность', + severityHigh: 'Высокая', + severityMedium: 'Средняя', + severityLow: 'Низкая', + sensitiveWord: 'Чувствительное слово', + sensitiveGroup: 'Группа чувствительных слов', + sensitiveWordCount: 'Слова', + normalizedWord: 'Нормализованное слово', + matchedWords: 'Совпавшие слова', + matchedGroups: 'Совпавшие группы', + importResult: 'Импортировано: {0}, дубликатов: {1}, недействительных: {2}', + auditLogs: 'Журнал аудита', smartRoute: 'Умная маршрутизация', smartRouteGuideTitle: 'Используйте model=auto на клиенте для умной маршрутизации', smartRouteGuideReady: @@ -1479,14 +1484,14 @@ const message = { streamableHttpPathHelper: 'Например: /mcp, обратите внимание, чтобы не перекрывать другие серверы', npxHelper: 'Подходит для mcp, запущенного с помощью npx или бинарного файла', uvxHelper: 'Подходит для mcp, запущенного с помощью uvx', - protocolVersion: 'Protocol Version', + protocolVersion: 'Версия протокола', protocolVersionHelper: - 'Only used by stateless Streamable HTTP to auto-initialize the downstream stdio MCP Server', + 'Используется только Streamable HTTP без состояния для автоматической инициализации нижестоящего stdio MCP Server', gatewayArgsHelper: 'Аргументы добавляются к команде supergateway. Параметры транспорта, порта, пути и протокола, управляемые 1Panel, изменить нельзя', - testConnection: 'Test Connection', - connectionSuccess: 'Connection succeeded', - connectionFailed: 'Connection failed', + testConnection: 'Проверить подключение', + connectionSuccess: 'Подключение успешно', + connectionFailed: 'Ошибка подключения', }, tensorRT: { llm: 'TensorRT LLM', @@ -1562,8 +1567,9 @@ const message = { lastHour: 'Последний час', last10Min: 'Последние 10 минут', cleanLog: 'Очистить лог', + cleanLogscope: 'Тип очистки', downLogHelper1: 'Это загрузит все логи из контейнера {0}. Хотите продолжить?', - downLogHelper2: 'Это загрузит последние {0} логов из контейнера {1}. Хотите продолжить?', + downLogHelper2: 'Это загрузит последние {1} записей журнала из контейнера {0}. Продолжить?', cleanLogHelper: 'Это потребует перезапуска контейнера и не может быть отменено. Хотите продолжить?', newName: 'Новое имя', source: 'Использование ресурсов', @@ -1759,7 +1765,8 @@ const message = { dockerStatus: 'Служба Docker', daemonJsonPathHelper: 'Убедитесь, что путь конфигурации совпадает с указанным в docker.service.', mirrors: 'Зеркала реестра', - mirrorsHelper: '', + mirrorsHelper: + 'Сначала используйте URL зеркал реестра для операций с образами. Оставьте поле пустым, чтобы отключить зеркала реестра.', mirrorsHelper2: 'Подробности см. в официальной документации. ', registries: 'Небезопасные реестры', ipv6Helper: @@ -1826,7 +1833,6 @@ const message = { stopHelper: 'Эта операция принудительно остановит выполнение текущей задачи. Продолжить?', log: 'Логи резервного копирования', logHelper: 'Резервное копирование системного лога', - ogHelper1: '1. Системный лог 1Panel', logHelper2: '2. Лог SSH-входов на сервер', logHelper3: '3. Все логи сайта', containerCheckBox: 'В контейнере (не нужно вводить команду контейнера)', @@ -1905,7 +1911,6 @@ const message = { perNMinute: 'Каждые N минут', perNSecond: 'Каждые N секунд', day: 'дней', - dayUnit: 'д', monday: 'Понедельник', tuesday: 'Вторник', wednesday: 'Среда', @@ -2045,7 +2050,6 @@ const message = { connTestFailed: 'Подключение недоступно, пожалуйста, проверьте информацию подключения.', host: 'Хост | Хосты', createConn: 'Новое подключение', - manageGroup: 'Управление группами', noHost: 'Нет хостов', groupChange: 'Изменить группу', expand: 'Развернуть все', @@ -2295,6 +2299,7 @@ const message = { nodes: 'ноды', commands: 'Быстрые команды', opsReport: 'Операционный отчет', + ops_report: 'Операционный отчет', users: 'Управление пользователями', roles: 'Роль', auth: 'Аутентификация входа', @@ -2315,10 +2320,6 @@ const message = { fileDirNum: '{0} каталогов, {1} файлов,', currentDir: 'Текущий каталог', dir: 'Папка', - upload: 'Загрузить', - uploadFile: '@:file.upload @.lower:file.file', - uploadDirectory: '@:file.upload @.lower:file.dir', - download: 'Скачать', fileName: 'Имя файла', search: 'Поиск', mode: 'Права доступа', @@ -2334,7 +2335,6 @@ const message = { role: 'Права доступа', info: 'Атрибуты', linkFile: 'Символическая ссылка', - batchoperation: 'Пакетная операция', shareList: 'Список общих ресурсов', fileTools: 'Инструменты файлов', aiSearchHitLines: 'Строки с совпадениями', @@ -2485,42 +2485,42 @@ const message = { 'Слева показано содержимое версии из истории, справа - содержимое последней версии выбранного файла', copyDir: 'Копировать', shareFile: 'Поделиться файлом', - shareExpire: 'Expires in', - shareExpire1h: '1 hour', - shareExpire6h: '6 hours', - shareExpire24h: '24 hours', - shareExpire3d: '3 days', - shareExpire7d: '7 days', - sharePassword: 'Password', - sharePasswordPlaceholder: 'Leave empty for no password', - shareMaxDownloads: 'Max downloads', - shareMaxDownloadsHint: '0 means unlimited', - shareGenerate: 'Create link', - shareRegenerate: 'Share again', - shareClose: 'Close', + shareExpire: 'Срок действия', + shareExpire1h: '1 час', + shareExpire6h: '6 часов', + shareExpire24h: '24 часа', + shareExpire3d: '3 дня', + shareExpire7d: '7 дней', + sharePassword: 'Пароль', + sharePasswordPlaceholder: 'Оставьте пустым, чтобы не использовать пароль', + shareMaxDownloads: 'Максимум загрузок', + shareMaxDownloadsHint: '0 означает без ограничений', + shareGenerate: 'Создать ссылку', + shareRegenerate: 'Поделиться снова', + shareClose: 'Закрыть', shareCancel: 'Отменить общий доступ', shareCancelConfirm: 'Вы уверены, что хотите отменить общий доступ к этому файлу?', - shareDetail: 'Details', - shareCopyLink: 'Copy link', - shareLinkLabel: 'Share link', - shareQrCode: 'QR code', - shareQrDialogTitle: 'Share link QR code', - shareQrDialogHelper: 'Scan this QR code with your mobile device', - shareSaveImage: 'Save image', - shareOpenImage: 'Open image', - shareExtractFile: 'Extract file', - shareDownloadingHint: 'Preparing your file, download will begin shortly.', - shareInvalid: 'Invalid or expired share link', - shareDownloadFailed: 'Download failed, please try again later', - sharePasswordRequired: 'Password', - sharePasswordRequiredInput: 'Please enter the share password', - sharePasswordLengthHint: 'Share password length must be 4-256 characters', - shareDownloadPasswordTip: 'This link is password-protected. Enter the password before downloading.', + shareDetail: 'Сведения', + shareCopyLink: 'Копировать ссылку', + shareLinkLabel: 'Ссылка общего доступа', + shareQrCode: 'QR-код', + shareQrDialogTitle: 'QR-код ссылки общего доступа', + shareQrDialogHelper: 'Отсканируйте QR-код с мобильного устройства', + shareSaveImage: 'Сохранить изображение', + shareOpenImage: 'Открыть изображение', + shareExtractFile: 'Получить файл', + shareDownloadingHint: 'Файл подготавливается. Загрузка скоро начнётся.', + shareInvalid: 'Недействительная или просроченная ссылка общего доступа', + shareDownloadFailed: 'Не удалось загрузить файл. Повторите попытку позже', + sharePasswordRequired: 'Пароль доступа', + sharePasswordRequiredInput: 'Введите пароль общего доступа', + sharePasswordLengthHint: 'Длина пароля общего доступа должна составлять 4–256 символов', + shareDownloadPasswordTip: 'Эта ссылка защищена паролем. Введите пароль перед загрузкой.', shareRiskAlert: - 'Shared links may carry security risks. Only share with trusted people and avoid exposing sensitive information.', + 'Ссылки общего доступа могут представлять угрозу безопасности. Делитесь ими только с доверенными людьми и не раскрывайте конфиденциальные данные.', sharePasswordSeparate: - 'A password is set. Share it securely. Recipients must add &password=... to the URL or use a client that can pass the password query parameter.', - shareExpiresAt: 'Expires at', + 'Пароль задан. Передайте его безопасным способом. Получатель должен добавить &password=... к URL или использовать клиент, поддерживающий параметр пароля.', + shareExpiresAt: 'Истекает', paste: 'Вставить', changeOwner: 'Изменить пользователя и группу', containSub: 'Применить изменение прав рекурсивно', @@ -2816,7 +2816,6 @@ const message = { systemIPWarning: 'Текущий узел не имеет настроенного адреса доступа по умолчанию. Пожалуйста, перейдите в настройки панели для его настройки!', systemIPWarning1: 'Текущий адрес сервера установлен на {0}, быстрое перенаправление невозможно!', - defaultNetwork: 'Сетевой интерфейс', syncTime: 'Время сервера', timeZone: 'Часовой пояс', timeZoneChangeHelper: 'Изменение часового пояса требует перезапуска службы. Хотите продолжить?', @@ -2864,7 +2863,7 @@ const message = { codeWarning: 'Текущий формат кода авторизации неверен, пожалуйста, проверьте еще раз!', code: 'Код авторизации', codeHelper: - 'Пожалуйста, нажмите кнопку "Получить", затем войдите в OneDrive и скопируйте содержимое после "code" в перенаправленной ссылке. Вставьте его в это поле ввода. Подробные инструкции смотрите в официальной документации.', + 'Нажмите кнопку «Получить», затем войдите в {0} и скопируйте содержимое после «code» в перенаправленной ссылке. Вставьте его в это поле. Подробные инструкции смотрите в официальной документации.', googleHelper: 'Сначала создайте приложение Google и получите информацию о клиенте, заполните форму и нажмите кнопку получения. Конкретные операции см. в официальной документации.', loadCode: 'Получить', @@ -3184,8 +3183,6 @@ const message = { upgrading: 'Идет обновление, пожалуйста, подождите...', versionHelper: 'Правило именования: [мажор].[функции].[исправления], пример ниже:', upgradeCheck: 'Проверить обновления', - panelSSLHelper: - 'После автообновления SSL панели нужно вручную перезапустить сервис 1Panel, чтобы изменения вступили в силу.', }, license: { offLine: 'Офлайн версия', @@ -3214,9 +3211,8 @@ const message = { authorizedUser: 'Авторизованный пользователь', lostHelper: 'Лицензия достигла максимального количества попыток повторной проверки. Пожалуйста, вручную нажмите кнопку синхронизации, чтобы убедиться, что функции коммерческой версии работают правильно. Детали: ', - disableHelper: - 'Синхронизация лицензии не удалась. Пожалуйста, вручную нажмите кнопку синхронизации, чтобы убедиться, что функции коммерческой версии работают правильно. Детали: ', quickUpdate: 'Быстрое обновление', + import: 'Импортировать', power: 'Авторизовать', unbindHelper: 'Все настройки коммерческой версии будут очищены после отвязки. Хотите продолжить?', importLicense: 'Лицензия', @@ -3276,6 +3272,7 @@ const message = { fileExchange: 'Обновите до Коммерческой версии, чтобы быстро передавать файлы между несколькими серверами.', app: 'Обновите до коммерческой версии, чтобы просматривать информацию о сервисах, мониторинг аномалий и т.д. через мобильное приложение.', cluster: 'Обновление до коммерческой версии позволяет управлять кластерами мастер-слейв MySQL/Postgres/Redis.', + vllm: 'Обновите до коммерческой версии, чтобы централизованно управлять сервисами vLLM в 1Panel: развертыванием, настройкой, жизненным циклом и отслеживанием задач.', 'model-downloader': 'Обновите до коммерческой версии, чтобы искать, загружать и управлять локальными файлами моделей из HuggingFace, ModelScope или совместимых зеркал, централизованно управляя каталогами моделей и задачами загрузки.', exceptionalHelper: @@ -3331,7 +3328,7 @@ const message = { volumes: 'Тома', buildCache: 'Кэш сборки контейнеров', appTmpDownload: 'Временный файл загрузки приложения', - unknownWebsiteLog: 'Arquivo de backup de log de site não vinculado', + unknownWebsiteLog: 'Несвязанный файл резервной копии журнала сайта', snapshot: 'Временные файлы системного снимка', }, app: { @@ -3492,7 +3489,6 @@ const message = { ftpHelper: 'После создания веб-сайта будет создан соответствующий FTP-аккаунт, и FTP-директория будет связана с директорией веб-сайта.', remark: 'Примечание', - manageGroup: 'Управление группами', groupSetting: 'Управление группами', createGroup: 'Создать группу', appNew: 'Новое приложение', @@ -3556,7 +3552,6 @@ const message = { nginxPer: 'Настройка производительности', neverExpire: 'Никогда', setDefault: 'Установить по умолчанию', - default: 'По умолчанию', deleteHelper: 'Статус связанного приложения аномальный, пожалуйста, проверьте', toApp: 'Перейти к списку установленных', cycle: 'Цикл', @@ -3674,7 +3669,6 @@ const message = { proxyHelper1: 'При доступе к этой директории будет возвращено и отображено содержимое целевого URL.', proxyPassHelper: 'Целевой URL должен быть действительным и доступным.', proxyHostHelper: 'Передать доменное имя в заголовке запроса прокси-серверу.', - replacementHelper: 'Можно добавить до 5 замен, оставьте пустым, если замена не требуется.', modifier: 'Правила сопоставления', modifierHelper: 'Пример: "=" точное совпадение, "~" регулярное совпадение, "^~" совпадение начала пути и т.д.', replace: 'Замены текста', @@ -3770,7 +3764,6 @@ const message = { proxySslVerifyHelper: 'При включении прокси строго проверяет SSL-сертификат вышестоящего сервера (по умолчанию отключено).', huaweicloud: 'Huawei Cloud', - rcreateDb: 'Создать Базу Данных', enableSSLHelper: 'Неудача при включении SSL не повлияет на создание сайта.', batchAdd: 'Пакетное Добавление Доменов', batchInput: 'Пакетный ввод', @@ -3782,7 +3775,6 @@ const message = { subsite: 'Подсайт', subsiteHelper: 'Подсайт может выбрать каталог существующего PHP или статического сайта в качестве корневого каталога.', - parentWebsite: 'Родительский Сайт', deleteSubsite: 'Чтобы удалить текущий сайт, сначала необходимо удалить подсайт {0}.', loadBalance: 'Балансировка Нагрузки', server: 'Узел', @@ -3813,7 +3805,6 @@ const message = { cacheExpire: 'Время Истечения Кэша', shareCacheHelper: '1M памяти может хранить примерно 8000 объектов кэша.', cacheLimitHelper: 'Превышение лимита автоматически удалит старые кэши.', - cacheExpireHelper: 'Кэши, не попавшие в срок истечения, будут удалены.', realIP: 'Реальный IP', ipFrom: 'Источник IP', ipFromHelper: @@ -3841,7 +3832,7 @@ const message = { saveCustom: 'Сохранить как Шаблон', rainyun: 'Rainyun', volcengine: 'Volcengine', - runtimePortHelper: 'O ambiente de runtime atual possui várias portas. Por favor, selecione uma porta de proxy.', + runtimePortHelper: 'Текущая среда выполнения предоставляет несколько портов. Выберите порт прокси.', runtimePortWarn: 'В текущей среде выполнения нет портов, невозможно проксировать', cacheWarn: 'Пожалуйста, сначала выключите кэш в обратном прокси', loadBalanceHelper: @@ -3878,8 +3869,6 @@ const message = { wafValueHelper: 'Значение', createDb: 'Создать базу данных', parentWbeiste: 'Родительский сайт', - shareCahe: 'Размер памяти под кэш', - shareCaheHelper: 'На 1M памяти можно хранить около 8000 кэш-объектов', cacheExpireJHelper: 'Кэш будет удален, если после истечения срока по нему не было обращений', }, php: { @@ -4260,7 +4249,6 @@ const message = { netRecv: 'входящий', numConnections: 'Соединения', startTime: 'Время запуска', - state: 'Состояние', running: 'Работает', sleep: 'сон', stop: 'остановлен', @@ -4419,7 +4407,7 @@ const message = { 'Дружеское напоминание: ваша лицензия Enterprise Edition истечет через {0} дней, и все функции Enterprise Edition станут недоступны. Пожалуйста, продлите лицензию вовремя, чтобы обеспечить дальнейшее использование.', expiresProAlert: 'Дружеское напоминание: ваша лицензия Pro Edition истечет через {0} дней, и все функции Pro Edition станут недоступны. Пожалуйста, продлите лицензию вовремя, чтобы обеспечить дальнейшее использование.', - menu: 'Рro', + menu: 'Pro', upage: 'AI Конструктор сайтов', proAlert: 'Обновитесь до коммерческой версии, чтобы использовать эту функцию', opsReport: { @@ -4430,21 +4418,21 @@ const message = { website: 'Защита сайтов', resource: 'Ресурсы выполнения', cronjob: 'Плановые задачи', - alert: 'Alert Notifications', + alert: 'Уведомления', history: 'История экспорта', setting: 'Настройки', page: { - enterprise: 'Enterprise', - reportNode: 'Report Node', - selectReportNode: 'Select report node', - currentNode: 'Current', - scoreMeta: '{0} points deducted · {1} risks', - hostAddress: 'Host Address', - panelVersion: 'Panel Version', - cpuCores: 'Physical Cores', - coreUnit: '{0} cores', - memoryTotal: 'Memory Total', - reportDate: 'Report Date', + enterprise: 'Корпоративная версия', + reportNode: 'Узел отчёта', + selectReportNode: 'Выберите узел отчёта', + currentNode: 'Текущий', + scoreMeta: 'Снято {0} баллов · рисков: {1}', + hostAddress: 'Адрес узла', + panelVersion: 'Версия панели', + cpuCores: 'Физические ядра', + coreUnit: '{0} ядер', + memoryTotal: 'Общий объём памяти', + reportDate: 'Дата отчёта', serverSecurityOverview: 'Обзор безопасности сервера', securityScore: 'Оценка безопасности', overviewSummary: @@ -4477,8 +4465,10 @@ const message = { scorePanelHTTPSDisabled: 'HTTPS для панели не включён', scoreSSHRootLogin: 'SSH-вход под root разрешён', scoreSSHPasswordAuth: 'SSH-аутентификация по паролю включена без ключевой аутентификации', + scoreSSLExpired: '{0} — срок действия сертификата истёк', scoreSSLHigh: '{0} — сертификат истекает через {1} дней', scoreSSLMedium: '{0} — сертификат истекает через {1} дней', + scoreWebsiteExpired: '{0} — срок действия сайта истёк', scoreWebsiteExpire: '{0} — сайт истекает через {1} дней', scoreWebsiteHTTP: '{0} — HTTPS не включён', scoreWebsiteStopped: '{0} — аномальный статус', @@ -4525,6 +4515,7 @@ const message = { panelLogin: 'Вход в панель', sshLogin: 'SSH-вход', failedRecord: 'Неудачные записи', + expired: 'Истёк', expiredDays: 'Истёк {0} дней назад', remainingDays: '{0} · осталось {1} дней', enabled: 'Включено', @@ -4794,9 +4785,9 @@ const message = { abnormalSites: 'Аномальные сайты', count5xxSource: 'По количеству запросов 5xx', wafIntercept: 'Перехваты WAF', - highRiskHit: 'Высокорисковые срабатывания', websiteMonitorDisabledOrNoData: 'Мониторинг сайтов отключён или данные отсутствуют', wafDisabledOrNoData: 'WAF отключён или данные о перехватах отсутствуют', + serviceEnabledButAbnormal: 'Включено, но состояние ненормальное', noWafData: 'Данные о перехватах WAF отсутствуют', sourceIP: 'IP-источник', hitCount: 'Количество срабатываний', @@ -4857,6 +4848,7 @@ const message = { successRate: 'Процент успеха', failedJobs: 'Неудачные задачи', recentRecoveryPoint: 'Последняя точка восстановления', + disabledCronjobTasks: 'Отключённые плановые задачи', remoteCoverage: 'Удалённое покрытие', recent7Days: 'Последние 7 дней', taskTypeStats: 'Статистика по типам задач', @@ -4878,6 +4870,7 @@ const message = { cronjobReasonDisabled: '{0} задач отключено', cronjobReasonLocalOnlyBackup: '{0} бэкапов только локально', cronjobReasonNormal: 'Выполнение задач и покрытие бэкапов в норме', + riskLow: 'Низкий риск', viewFailedRecords: 'Показать сбойные задачи', viewCronjobTasks: 'Показать плановые задачи', checkBackupTasks: 'Проверить задачи бэкапа', @@ -4976,6 +4969,14 @@ const message = { authManage: 'Управление аутентификацией', auth: { providerNavigation: 'Поставщики аутентификации', + defaultNode: 'Узел по умолчанию', + defaultNodePlaceholder: 'Выберите узел', + defaultNodeHelper: 'Только для новых пользователей.', + defaultNodeRequired: 'Выберите допустимый узел по умолчанию.', + nodesLoadFailed: 'Не удалось загрузить узлы. Повторите попытку перед выбором узла по умолчанию.', + nodeHandling: 'Обработка узла', + assignDefaultNode: 'Назначить узел по умолчанию: {node}', + keepExistingNode: 'Сохранить существующие разрешения узла', providers: { ldap: 'AD/LDAP', passkey: 'Passkey', @@ -5003,7 +5004,419 @@ const message = { planned: 'Планируется', plannedTitle: 'Настройки аутентификации {0}', plannedDesc: 'Этот поставщик аутентификации запланирован и пока недоступен.', + oidc: { + accessMode: 'Режим подключения', + accessModeDesc: 'Используйте стандарт Discovery, если поставщик удостоверений поддерживает его.', + actionCreate: 'Создать пользователя', + actionKeepName: 'Сохранить текущее имя пользователя', + actionPending: 'Ожидание результата', + actionReject: 'Отклонить вход', + actionUpdate: 'Обновить идентификационную информацию', + advanced: 'Расширенные настройки', + advancedDesc: + 'Сохраняйте безопасные настройки по умолчанию, если поставщик не требует опции совместимости.', + assignDefaultRole: 'Назначить роль по умолчанию: {role}.', + authorizationEndpoint: 'Authorization Endpoint', + authorizationEndpointInvalid: 'Введите действительный Authorization Endpoint.', + authorizationFlow: 'Процесс авторизации', + automatic: 'Автоматический', + automaticPolicy: 'Политика автоматической обработки', + automaticPolicyDesc: + 'Эти правила применяются серверной частью и не являются переключателями администратора.', + basic: 'Основные настройки', + basicDesc: 'Выберите режим провайдера, затем настройте клиент и обратный вызов.', + browserTest: 'Тестовый вход в браузере', + browserTestConflict: 'Личность подтверждена, но имя пользователя уже занято.', + browserTestConflictHelper: + 'Сопоставленное имя пользователя принадлежит другой идентичности и не будет присвоено.', + browserTestExpired: 'Срок проверки браузера истек', + browserTestExpiredHelper: + 'Запустите новый тест браузера и завершите авторизацию до истечения срока его действия.', + browserTestFailed: 'Проверка браузера не удалась', + browserTestFailedHelper: + 'Не удалось выполнить предварительный просмотр личности. Просмотрите локализованную серверную ошибку.', + browserTestIsolation: + 'Выполняется полный цикл реальной авторизации, но пользователи не создаются и не обновляются, роли не назначаются и аутентифицированный сеанс панели не создаётся.', + browserTestPopupBlocked: + 'Разрешите всплывающие окна для этого сайта, затем снова запустите проверку браузера.', + browserTestPopupClosed: 'Окно авторизации было закрыто до завершения теста.', + browserTestSuccess: 'Проверка Provider прошла успешно', + browserTestSuccessHelper: + 'Сопоставление удостоверений было предварительно просмотрено без изменения пользователей или сеансов.', + browserTestTitle: 'OIDC тестовый вход в браузер', + browserTestWaiting: 'Ожидание авторизации Provider', + browserTestWaitingHelper: + 'Завершите вход в новом окне браузера. Эта страница будет обновляться автоматически.', + callbackCopied: 'Обратный вызов OIDC URL скопирован.', + callbackURL: 'Обратный звонок URL', + callbackURLHelper: + 'Добавьте этот URL в список разрешенных URL обратного вызова клиента у поставщика удостоверений.', + cancelClearSecret: 'Отменить очистку', + clearSecret: 'Очистить секрет', + clearSecretConfirm: 'Client Secret будет удален только после сохранения. Продолжать?', + clientAuthMethod: 'Метод аутентификации клиента', + clientAuthMethodHelper: + 'Выберите метод аутентификации, настроенный для этого клиента у поставщика удостоверений.', + clientAuthMethodRequired: 'Выберите метод аутентификации клиента.', + clientID: 'Client ID', + clientIDRequired: 'Введите Client ID.', + clientSecret: 'Client Secret', + clockSkew: 'Допуск времени токена', + clockSkewHelper: + 'Допускает небольшую разницу времени между поставщиком удостоверений и 1Panel. Оставьте значение по умолчанию 60 секунд.', + clockSkewRequired: 'Укажите допуск времени токена.', + compatibilityMode: 'Режим совместимости', + compatibilityModeHelper: + 'Используйте только для неполных Discovery или переписанных конечных точек. Проверка ядра OIDC остается включенной.', + configurationFailedHelper: + 'Тест провалился. На странице отображается только локализованная серверная ошибка.', + configurationFailedTag: 'Тест не пройден', + configurationHighRiskPassed: + 'Конфигурация прошла успешно, но содержит параметры совместимости с высоким уровнем риска.', + configurationHighRiskTag: 'Конфигурация высокого риска пройдена', + configurationNotTested: 'Текущая конфигурация не тестировалась.', + configurationNotTestedTag: 'Не проверено', + configurationPassed: 'Текущая конфигурация прошла проверку безопасности и возможностей.', + configurationPassedTag: 'Тест пройден', + configurationStaleHelper: 'Конфигурация изменена. Повторите проверку перед сохранением.', + configurationStaleTag: 'Срок действия результата истек', + configurationTestMeta: + 'Протестировано на {time}; завершено за {duration} мс. Необработанные ответы Provider не ​​сохраняются.', + configurationTestResult: 'Результат теста конфигурации', + configurationTestResultDesc: + 'При этом проверяется только Discovery и его возможности; он не обменивает код авторизации и не подтверждает Client Secret. Используйте тестовый вход в браузер для сквозной проверки.', + configurationTestSuccess: 'Тест конфигурации OIDC пройден успешно.', + configurationTesting: 'Тестирование текущей конфигурации OIDC…', + configurationTestingTag: 'Тестирование', + configureSecret: 'Настроить секрет', + conflictExistingRename: 'Связанный subject возвращает новый name, который занят.', + conflictExistingRenameResult: + 'Сохраните существующий User.Name и разрешите связанному пользователю войти в систему.', + conflictLDAP: 'Пользователь LDAP', + conflictLocal: 'Локальный пользователь', + conflictNewAvailable: 'Доступны новый subject и сопоставленный name.', + conflictNewAvailableResult: 'Создайте корпоративного пользователя и назначьте роль по умолчанию.', + conflictNone: 'Нет конфликта', + conflictOIDC: 'Еще одна личность OIDC', + conflictOccupied: + 'Сопоставленный name принадлежит локальному LDAP или другому идентификатору OIDC.', + conflictOccupiedResult: + 'Отклонить новую личность; никогда не связывать и не объединять автоматически', + conflictType: 'Тип конфликта', + connectionSecurity: 'Безопасность соединения', + connectionSecurityDesc: 'Политика TLS применяется к запросам Discovery, Token, JWKS и UserInfo.', + connectionTest: 'Проверка подключения и конфигурации', + connectionTestCompatibilityDesc: + 'Проверьте пользовательские конечные точки и политику безопасности протокола.', + connectionTestStandardDesc: 'Конечные точки и возможности автоматически обнаруживаются из Issuer.', + connectionTestTab: 'Проверка подключения', + customCA: 'Пользовательский CA', + customCAHelper: + 'Применяется только к этому источнику аутентификации и никогда не записывается в журналы.', + customCARequired: 'Предоставьте собственный сертификат CA.', + defaultRole: 'Роль по умолчанию', + defaultRoleHelper: + 'Назначается только при первом создании пользователя; последующие входы не изменяют роль.', + defaultRolePlaceholder: 'Выберите роль', + defaultRoleRequired: 'Выберите допустимую роль по умолчанию.', + disableAfterSave: 'OIDC будет отключен после сохранения.', + disableConfirm: + 'Отключение OIDC немедленно аннулирует доступ пользователей этого источника. Продолжать?', + disableDiscardConfirm: + 'Отключение OIDC является экстренным действием: оно лишь закрывает вход в систему и немедленно аннулирует доступ для пользователей этого источника. Другие несохраненные изменения на этой странице, включая изменения Client Secret, будут отменены. Продолжать?', + disableTitle: 'Отключить OIDC', + disabled: 'Отключено', + discoveryAllowlist: 'Discovery ∩ список разрешений безопасности', + enable: 'Включить', + enableAfterSave: 'OIDC будет включен после успешного сохранения.', + enabled: 'Включено', + endSessionEndpoint: 'End Session Endpoint', + endSessionEndpointHelper: + 'Сохранено для будущего использования; Выход из системы, инициированный Provider, не включен в эту версию.', + endSessionEndpointInvalid: 'Введите действительный End Session Endpoint.', + endpointDiscoveryPlaceholder: 'Отображается после проверки подключения', + firstLogin: 'Первый вход', + firstLoginPolicy: + 'Создайте локального корпоративного пользователя и назначьте настроенную роль по умолчанию.', + fixedAuthorizationCode: 'Authorization Code Flow', + fixedNoTokenPersistence: 'Token, Claims и verifier никогда не сохраняются.', + fixedSecurityPolicy: 'Всегда соблюдается; не требуется настройка', + fixedStateNonce: 'Одноразовые state и nonce', + fixedTokenValidation: 'Подпись ID Token и проверка Claims', + highRiskSaveConfirm: + 'Эта включенная конфигурация содержит параметры совместимости с высоким уровнем риска. Убедитесь, что они требуются для изолированной среды.', + highRiskTitle: 'Конфигурация OIDC высокого риска', + hs256Compatibility: 'HS256 (совместимость)', + hs256KeyHelper: + 'HS256 всегда использует Client Secret этого источника и не принимает отдельный ключ подписи.', + hs256Warning: + 'HS256 использует общий симметричный секрет для подписей ID Token. Используйте его только в том случае, если Provider не ​​может использовать асимметричный алгоритм.', + identityBindingPolicy: + 'Идентичность фиксируется по AuthSourceID + issuer + subject. Совпадение имени пользователя никогда не приводит к привязке другой учетной записи.', + identityMissing: 'Идентификатор неактивен', + issuer: 'Issuer URL', + issuerHelper: + 'Значение iss ID Token и Discovery issuer должны точно соответствовать этому значению.', + issuerInvalid: 'Введите действительный HTTP или HTTPS Issuer URL без запроса или фрагмента.', + issuerRequired: 'Введите Issuer URL.', + jwksRotation: 'Автоматическое вращение JWKS', + jwksURI: 'JWKS URI', + jwksURIHelper: 'Требуется для асимметричной подписи, когда источником ключа является JWKS.', + jwksURIInvalid: 'Введите действительный JWKS URI для выбранного источника ключа подписи.', + keepExistingRole: 'Сохраните существующие роли и локальные разрешения.', + localSecurityData: 'Данные локальной безопасности', + localSecurityDataPolicy: + 'Никогда не перезаписывайте роли, MFA, API Keys, Passkeys или локальные разрешения.', + localCredentialsManaged: + 'Имя пользователя и локальный пароль управляются OIDC и не могут быть изменены здесь. Роли, разрешения, MFA, API Keys и Passkeys остаются локальными.', + localUserFields: 'Поля локального пользователя', + localUserFieldsDesc: + 'Первый выпуск отображает только User.Name и не использует выражение сопоставления JSON.', + loginWith: 'Войти через {provider}', + manualEndpoints: 'Пользовательские конечные точки', + manualEndpointsDesc: + 'Используйте только в том случае, если Discovery неполный или вышестоящий шлюз перезаписывает конечные точки.', + mappingResult: 'Результат сопоставления', + mode: 'Режим подключения', + modeRequired: 'Выберите режим подключения.', + nameClaim: 'Claim имени пользователя', + nameClaimHelper: 'Укажите поле с именем пользователя, например preferred_username.', + nameClaimRequired: 'Введите Claim имени пользователя.', + nameConflict: 'Политика конфликта имен', + panelURL: '1Panel общедоступный URL', + panelURLHTTPWarning: + 'HTTP не ​​защищает ответ авторизации. Используйте его только в изолированной частной среде, разрешенной Provider.', + panelURLHelper: + 'Укажите адрес, по которому пользователи открывают 1Panel. Он используется для формирования URL обратного вызова.', + panelURLInvalid: 'Введите источник, содержащий только схему, хост и дополнительный порт.', + panelURLRequired: 'Введите общедоступный 1Panel URL.', + pkceDisabled: 'Отключено (только совместимость)', + pkceDisabledWarning: 'Отключение PKCE снижает защиту от перехвата кода авторизации.', + pkceHelper: 'Предпочитаю S256. Метод вызова plain никогда не предлагается.', + pkceS256: 'S256 (рекомендуется)', + plannedHandling: 'Плановая обработка', + privateNetworkIdP: 'IdP частной сети', + privateNetworkIdPHelper: + 'Явно разрешает частные адреса; метаданные, петля, локальная ссылка, перенаправление и повторное связывание DNS остаются заблокированными.', + privateNetworkWarning: 'Для этого источника аутентификации включен доступ к частной сети.', + protocolCompatibility: 'Совместимость протоколов', + protocolCompatibilityDesc: 'Проверка подписи ID Token никогда не может быть отключена.', + providerAndClient: 'Provider и клиент', + providerAndClientDesc: + 'Client Secret можно только заменить или очистить, и страница никогда не возвращает его.', + providerCapabilities: 'Возможности Provider', + recentTestSuccess: 'Последний тест прошел успешно: {0}', + recommended: 'Рекомендуется', + rejectPlain: 'plain отклонен', + replaceSecret: 'Заменить секрет', + requestAndClaims: 'Запросы и атрибуты', + requestAndClaimsDesc: + 'Настройте области авторизации, дополнение сведений о пользователе и параметры запросов.', + requestTimeout: 'Тайм-аут запроса', + requestTimeoutRequired: 'Введите тайм-аут запроса.', + restore: 'Восстановить', + restored: 'Были восстановлены последние сохраненные настройки OIDC.', + result: 'Результат', + rolesLoadFailed: + 'Не удалось загрузить роли. Повторите попытку, прежде чем выбирать роль по умолчанию.', + roleHandling: 'Обработка ролей', + scenario: 'Сценарий', + scopes: 'Области авторизации', + scopesHelper: 'Необходимо включить openid. Разделяйте несколько областей пробелами.', + scopesRequired: 'Scopes должен включать openid.', + seconds: 'секунды', + secretClearHelper: + 'После очистки потребуется новый Client Secret, прежде чем OIDC можно будет снова включить.', + secretConfigured: 'Настроен', + secretNotConfigured: 'Не настроено', + secretPlaceholder: 'Введите новый Client Secret', + secretReplaceHelper: + 'При сохранении новый секрет заменит прежнее значение. Также обновите Client Secret у OIDC-провайдера.', + secretRequiredHelper: 'Настройте Client Secret перед включением OIDC.', + secretRequiredToEnable: 'Настройте Client Secret перед включением OIDC.', + secretSavedHelper: + 'Хранится в зашифрованном виде. Оставьте поле пустым, чтобы сохранить текущий секрет.', + secretWaiting: 'Ожидание ввода', + secretWillClear: 'Будет очищено', + secretWillReplace: 'Будет заменен', + signingAlgorithm: 'Алгоритм подписи ID Token', + signingAlgorithmHelper: 'Доступны только алгоритмы из белого списка внутренней безопасности.', + signingKey: 'Ключ подписи', + signingKeyClientSecret: 'Client Secret (только HS256)', + signingKeyJWKS: 'JWKS URI с автоматической ротацией', + signingKeySource: 'Источник ключа подписи', + signingKeySourceHelper: + 'Предпочтительно использовать JWKS. Статический открытый ключ нельзя ротировать автоматически.', + signingKeyStatic: 'Статический открытый ключ JWK или PEM.', + standardDiscovery: 'Стандартный OIDC Discovery', + standardDiscoveryDesc: + '1Panel обнаруживает конечные точки и возможности и не сохраняет необработанный документ.', + standardMode: 'Стандартный режим', + standardModeHelper: + 'Откройте для себя конечные точки, возможности подписи и поддержку PKCE с помощью Issuer.', + standardProtocolPolicy: 'Стандартная политика протокола', + standardProtocolPolicyDesc: + 'Возможности подписи согласовываются автоматически; ключ подписи здесь не введен.', + staticSigningKey: 'Статический открытый ключ подписи', + staticSigningKeyHelper: + 'Принимается только материал открытого ключа. Выполните ротацию вручную при изменении ключа Provider.', + staticSigningKeyPlaceholder: 'Вставьте открытый ключ JWK, JWKS JSON или PEM.', + staticSigningKeyRequired: 'Предоставьте статический открытый ключ подписи.', + staticSigningKeyWarning: + 'Статический ключ подписи нельзя ротировать автоматически; обновите его до ротации ключей Provider.', + settingLoadFailed: 'Не удалось загрузить настройки OIDC.', + settingLoadFailedHelper: + 'Форма заблокирована, чтобы избежать сохранения пустой конфигурации по умолчанию поверх текущих настроек. Повторите попытку после восстановления соединения.', + subsequentLogin: 'Последующий вход', + subsequentLoginPolicy: + 'Найдите привязку по subject и обновляйте только User.Name, когда новое имя будет доступно.', + testBeforeBrowserTest: 'Проверьте текущую конфигурацию перед запуском проверки входа в браузер.', + testBeforeEnable: 'Перед сохранением изменений конфигурации проверьте текущую конфигурацию.', + testConfiguration: 'Проверить конфигурацию', + testDiscovery: 'Проверить Discovery', + tlsCustomCA: 'HTTPS · Пользовательский сертификат CA', + tlsPrivateHTTP: 'HTTP · Только частная сеть (опасно)', + tlsPrivateHTTPWarning: + 'HTTP не ​​обеспечивает транспортного шифрования и ограничен явно разрешенными частными целями.', + tlsSkipVerify: 'HTTPS · Пропустить проверку сертификата (опасно)', + tlsSystem: 'HTTPS · Проверка сертификата системы (рекомендуется)', + tokenEndpoint: 'Token Endpoint', + tokenEndpointInvalid: 'Введите действительный Token Endpoint.', + transportSecurity: 'Транспортная безопасность', + transportSecurityHelper: + 'Предпочитаю HTTPS. Частный HTTP также требует явного доступа к private-network.', + unsavedChanges: 'Есть несохраненные изменения OIDC.', + usedClaim: 'Claim б/у', + userInfoEndpoint: 'UserInfo Endpoint', + userInfoEndpointHelper: + 'Если поле имени пользователя отсутствует, система дополнит его через эту конечную точку. Оставьте поле пустым, чтобы не использовать дополнение.', + userInfoEndpointInvalid: 'Введите допустимый UserInfo Endpoint.', + userMapping: 'Настройки пользователя', + userMappingDesc: + 'Настройте сопоставление имени пользователя OIDC, а также узел и роль по умолчанию для создания пользователя при первом входе.', + }, + saml2: { + actionCreate: 'Создать пользователя', + actionPending: 'Ожидание результата', + actionReject: 'Отклонить вход', + actionReuse: 'Использовать привязанного пользователя', + assignDefaultRole: 'Назначить роль по умолчанию: {role}.', + basic: 'Основные настройки', + basicDesc: 'Настройте параметры, необходимые большинству стандартных поставщиков SAML2.', + browserTest: 'Проверить вход', + browserTestConflict: 'Личность подтверждена, но имя пользователя уже занято.', + browserTestConflictHelper: + 'Сопоставленное имя пользователя принадлежит другой идентичности и не будет присвоено.', + browserTestExpired: 'Срок проверки браузера истек', + browserTestExpiredHelper: + 'Запустите новый тест браузера и завершите авторизацию до истечения срока его действия.', + browserTestFailed: 'Проверка браузера не удалась', + browserTestFailedHelper: + 'Не удалось выполнить предварительный просмотр личности. Просмотрите локализованную серверную ошибку.', + browserTestIsolation: + 'Выполняется полный цикл реальной авторизации, но пользователи не создаются и не обновляются, роли не назначаются и аутентифицированный сеанс панели не создаётся.', + browserTestPopupBlocked: + 'Разрешите всплывающие окна для этого сайта, затем снова запустите проверку браузера.', + browserTestPopupClosed: 'Окно авторизации было закрыто до завершения теста.', + browserTestSuccess: 'Проверка Provider прошла успешно', + browserTestSuccessHelper: + 'Сопоставление удостоверений было предварительно просмотрено без изменения пользователей или сеансов.', + browserTestTitle: 'SAML2 тестовый вход в браузер', + browserTestWaiting: 'Ожидание авторизации Provider', + browserTestWaitingHelper: + 'Завершите вход в новом окне браузера. Эта страница будет обновляться автоматически.', + certificateFileInvalid: 'Выберите корректный файл сертификата PEM, CRT или CER.', + configured: 'Настроено', + configurationFailedHelper: + 'Тест провалился. На странице отображается только локализованная серверная ошибка.', + configurationNotTested: 'Текущая конфигурация не тестировалась.', + configurationPassed: 'Текущая конфигурация прошла проверку безопасности и возможностей.', + configurationStaleHelper: 'Изменены настройки аутентификации. Проверьте текущий проект еще раз.', + configurationTestSuccess: 'Тест конфигурации SAML2 пройден успешно.', + configurationTesting: 'Тестирование текущей конфигурации SAML2…', + conflictLDAP: 'Пользователь LDAP', + conflictLocal: 'Локальный пользователь', + conflictNone: 'Нет конфликта', + conflictOIDC: 'Еще одна личность OIDC', + conflictSAML2: 'Другая учетная запись SAML2', + conflictType: 'Тип конфликта', + credentialFileReadFailed: 'Не удалось прочитать файл учетных данных.', + credentialFileTooLarge: 'Размер файлов учетных данных не должен превышать 256 КиБ.', + credentialsRequired: 'Настройте закрытый ключ и сертификат SP.', + defaultRole: 'Роль нового пользователя', + defaultRoleHelper: + 'Назначается только при первом создании; последующие входы сохраняют локальные роли, MFA и права.', + defaultRolePlaceholder: 'Выберите роль', + defaultRoleRequired: 'Выберите допустимую роль по умолчанию.', + disableConfirm: + 'Отключение SAML2 немедленно отклоняет новые входы и аннулирует пользовательские сеансы. Продолжить?', + disableDiscardConfirm: + 'Отключение SAML2 отменяет другие несохраненные изменения на этой странице и немедленно аннулирует пользовательские сеансы. Продолжить?', + disableTitle: 'Отключить SAML2', + disabled: 'Отключено', + enable: 'Включить', + enabled: 'Включено', + idpMetadata: 'Метаданные IdP', + idpMetadataDesc: 'Укажите URL или вставьте XML. Если заполнены оба поля, используется URL.', + keepExistingRole: 'Сохраните существующие роли и локальные разрешения.', + loginWith: 'Войти через {provider}', + mappingResult: 'Результат сопоставления', + metadataRequired: 'Укажите URL или XML метаданных IdP.', + metadataURLHelper: 'Сервер загружает и проверяет метаданные при тестировании и сохранении.', + metadataURLInvalid: 'Введите корректный HTTPS URL метаданных без учетных данных и фрагмента.', + metadataURLRecommended: 'URL метаданных (рекомендуется)', + metadataXML: 'XML метаданных', + metadataXMLHelper: 'Используйте, если IdP не предоставляет доступный URL метаданных.', + metadataXMLInvalid: 'Введите корректный XML метаданных EntityDescriptor.', + metadataXMLPlaceholder: 'Вставьте ...', + nameAttribute: 'Атрибут имени пользователя', + nameAttributeHelper: + 'Считывает этот атрибут из проверенного SAML Assertion и сопоставляет его с именем пользователя 1Panel.', + nameAttributePlaceholder: 'Например: uid, username или account', + nameAttributeRequired: 'Введите атрибут имени пользователя.', + notConfigured: 'Не настроено', + or: 'или', + pageDesc: 'Подключите корпоративный SSO через метаданные IdP и настройте его на одной странице.', + plannedHandling: 'Плановая обработка', + privateKeyFileInvalid: 'Выберите корректный файл закрытого ключа PEM.', + recentTestSuccess: 'Последний тест прошел успешно: {0}', + restore: 'Восстановить', + restored: 'Были восстановлены последние сохраненные настройки SAML2.', + roleHandling: 'Обработка ролей', + rolesLoadFailed: + 'Не удалось загрузить роли. Повторите попытку, прежде чем выбирать роль по умолчанию.', + selectFile: 'Выбрать файл', + serviceStatus: 'Состояние службы', + serviceStatusDesc: 'Перед включением SAML2 текущая конфигурация должна пройти проверку.', + settingLoadFailed: 'Не удалось загрузить настройки SAML2.', + settingLoadFailedHelper: + 'Форма заблокирована, чтобы избежать сохранения пустой конфигурации по умолчанию поверх текущих настроек. Повторите попытку после восстановления соединения.', + spCertificate: 'Сертификат SP', + spCertificateHelper: + 'Публикуется в метаданных SP, чтобы IdP мог проверять запросы на вход и выход.', + spCredentials: 'Закрытый ключ и сертификат SP', + spCredentialsDesc: + 'Используются для подписи сообщений входа и выхода. Политика подписи и проверки задана сервером.', + spPrivateKey: 'Закрытый ключ SP', + spPrivateKeyHelper: + 'Используется для подписи AuthnRequest и сообщений выхода. Ключ хранится в зашифрованном виде и никогда не отображается.', + syncLogout: 'Синхронный выход', + syncLogoutHelper: 'Выход из 1Panel или IdP также завершает сеанс на другой стороне.', + testBeforeBrowserTest: 'Проверьте текущую конфигурацию перед запуском проверки входа в браузер.', + testBeforeEnable: + 'Проверьте текущую конфигурацию, прежде чем включать или сохранять важные изменения.', + testConfiguration: 'Проверить конфигурацию', + unsavedChanges: 'Есть несохраненные изменения SAML2.', + usedAttribute: 'Сопоставление имени пользователя', + usersAndRoles: 'Пользователи и роли', + usersAndRolesDesc: + 'Настройте сопоставление имени пользователя панели, а также узел и роль по умолчанию для создания пользователя при первом входе.', + }, ldap: { + basic: 'Основные настройки', + loginTitle: 'Вход через LDAP', + loginWith: 'Войти через LDAP', + backToLocalLogin: 'Вернуться ко входу в панель', enable: 'Включить', enabled: 'Включено', disabled: 'Отключено', @@ -5225,6 +5638,7 @@ const message = { deleteConfirm: 'Удалить эту запись экспорта и файл?', }, waf: { + WAF: 'WAF', name: 'WAF', blackWhite: 'Черный и белый список', globalSetting: 'Глобальные настройки', @@ -5847,6 +6261,15 @@ const message = { nodeUpgradePackageCleanHelper: 'Все пакеты обновления более ранних версий будут очищены. Продолжить?', nodeUpgradeOfflinePackageHelper: 'В автономной среде для узлов с другой архитектурой сначала загрузите соответствующий пакет обновления.', + healthCheck: 'Проверка состояния', + healthCheckFrequency: 'Частота проверки', + healthCheckFrequencyHelper: + 'Периодически проверяет состояние серверных узлов. Введите 0, чтобы отключить проверки.', + healthCheckFrequencyLimit: + 'Частота проверки не может превышать один день и должна быть неотрицательным целым числом.', + loadFailedNodeResources: 'Загружать ресурсы недоступных узлов', + loadFailedNodeResourcesHelper: + 'При открытии списка узлов также загружать сведения о ресурсах недоступных узлов.', nodeUnhealthy: 'Некорректное состояние узла', deletedNode: 'Удалённый узел {0} в настоящее время не поддерживает операции обновления!', nodeUnhealthyHelper: @@ -5869,12 +6292,12 @@ const message = { addNode: 'Добавить узел', connInfo: 'Информация о подключении', nodeInfo: 'Информация об узле', - withProxy: 'Proxy Erişimini Etkinleştir', - withoutProxy: 'Proxy Erişimini Devre Dışı Bırak', + withProxy: 'Включить доступ через прокси', + withoutProxy: 'Отключить доступ через прокси', withProxyHelper: - 'Alt düğümlere erişmek için panel ayarlarında tutulan sistem proxy {0} kullanılacak. Devam etmek istiyor musunuz?', + 'Для доступа к дочернему узлу будет использован системный прокси {0}, заданный в настройках панели. Продолжить?', withoutProxyHelper: - 'Alt düğümlere erişmek için panel ayarlarında tutulan sistem proxy kullanımı durdurulacak. Devam etmek istiyor musunuz?', + 'Доступ к дочернему узлу больше не будет использовать системный прокси, заданный в настройках панели. Продолжить?', syncInfo: 'Синхронизация данных,', syncHelper: 'При изменении данных главного узла, происходит синхронизация с этим дочерним узлом в реальном времени,', @@ -5942,6 +6365,8 @@ const message = { offlineHelper: 'Используется, когда узел находится в автономной среде', appUpgrade: 'Обновление приложения', appUpgradeHelper: 'Есть {0} приложений, которые необходимо обновить', + dashboardSetting: 'Настройки обзора', + keepOneDashboardComponent: 'Оставьте хотя бы один раздел обзора', }, customApp: { name: 'Пользовательское хранилище приложений', @@ -6348,35 +6773,35 @@ const message = { cpu: 'CPU', memory: 'Память', disk: 'Диск', - overview: 'Overview', - kvmUnavailable: 'No available KVM hardware virtualization capability was detected.', - kvmCheckCpu: 'Confirm that the host CPU supports Intel VT-x or AMD-V virtualization.', - kvmCheckBios: 'Enable virtualization options in BIOS/UEFI.', - kvmCheckModule: 'Confirm that the kvm, kvm_intel, or kvm_amd kernel module is loaded correctly.', + overview: 'Обзор', + kvmUnavailable: 'Доступные средства аппаратной виртуализации KVM не обнаружены.', + kvmCheckCpu: 'Убедитесь, что процессор хоста поддерживает виртуализацию Intel VT-x или AMD-V.', + kvmCheckBios: 'Включите параметры виртуализации в BIOS/UEFI.', + kvmCheckModule: 'Убедитесь, что модуль ядра kvm, kvm_intel или kvm_amd загружен правильно.', kvmCheckDevice: - 'Confirm that /dev/kvm exists and the current environment is not a container or cloud host without KVM support.', - abnormal: 'Abnormal', - resourceOverview: 'Resource Overview', - cpuAllocated: 'CPU Allocated', - memoryAllocated: 'Memory Allocated', - storageUsed: 'Storage Used', - riskReminder: 'Risk Reminders', - noRisk: 'No risks', - runtimeHealth: 'Runtime Health', - runtimeAbnormal: 'VM runtime is abnormal', - noDependency: 'No dependency check data', - storageOverview: 'Storage Overview', - totalAllocated: 'Calculated by total VM configuration', - runningAllocated: 'Running allocation: {0}', - storageAvailable: 'Available: {0}', - inProgress: 'In progress', - needAttention: 'Needs attention', - normal: 'Normal', - environmentRisk: 'The VM runtime is not ready. Fix dependencies or virtualization services.', - storageRisk: 'Storage pool {0} usage has reached {1}%.', - abnormalRisk: '{0} VMs are in an abnormal state.', - pausedRisk: '{0} VMs are paused.', - memoryRisk: 'VM memory allocation has reached {0}%.', + 'Убедитесь, что /dev/kvm существует, а текущая среда не является контейнером или облачным хостом без поддержки KVM.', + abnormal: 'Неисправно', + resourceOverview: 'Обзор ресурсов', + cpuAllocated: 'Выделено CPU', + memoryAllocated: 'Выделено памяти', + storageUsed: 'Использовано хранилища', + riskReminder: 'Предупреждения о рисках', + noRisk: 'Рисков нет', + runtimeHealth: 'Состояние среды выполнения', + runtimeAbnormal: 'Среда выполнения ВМ работает ненормально', + noDependency: 'Нет данных проверки зависимостей', + storageOverview: 'Обзор хранилища', + totalAllocated: 'Рассчитано по общей конфигурации ВМ', + runningAllocated: 'Выделено работающим ВМ: {0}', + storageAvailable: 'Доступно: {0}', + inProgress: 'Выполняется', + needAttention: 'Требует внимания', + normal: 'Нормально', + environmentRisk: 'Среда выполнения ВМ не готова. Исправьте зависимости или службы виртуализации.', + storageRisk: 'Использование пула хранилища {0} достигло {1}%.', + abnormalRisk: 'ВМ в неисправном состоянии: {0}.', + pausedRisk: 'Приостановлено ВМ: {0}.', + memoryRisk: 'Выделение памяти ВМ достигло {0}%.', cpuLimitHelper: 'Доступно CPU сейчас: {0} ядер', cpuLimitExceeded: 'CPU превышает лимит. Текущий максимум: {0} ядер.', memoryLimitHelper: 'Доступная для выделения память: {0} (хост должен зарезервировать {1} памяти)', @@ -6385,11 +6810,11 @@ const message = { storageLimitExceeded: 'Ёмкость диска превышает лимит. Текущий максимум: {0}.', iso: 'ISO', createFromTemplate: 'Создать из шаблона', - template: 'Template', - templateName: 'Template Name', - convertToTemplate: 'Convert to Template', - sourceVM: 'Source VM', - templateSize: 'Template Size', + template: 'Шаблон', + templateName: 'Имя шаблона', + convertToTemplate: 'Преобразовать в шаблон', + sourceVM: 'Исходная ВМ', + templateSize: 'Размер шаблона', deleteTemplateConfirm: 'Удалить шаблон {0}. Эту операцию нельзя отменить. Продолжить?', orphanClean: 'Очистка неиспользуемых данных', orphanScan: 'Повторить сканирование', @@ -6433,21 +6858,21 @@ const message = { available: 'Доступно', vmCount: 'Связанные ВМ', usedIPs: 'Использованные IP', - monitor: 'Monitor', - monitorNotReady: 'The virtual machine is not running. Monitoring data is unavailable.', - monitorLoadFailed: 'Failed to get VM monitoring data.', - monitorLoadFailedWithReason: 'Failed to get VM monitoring data: {0}', - rename: 'Rename', + monitor: 'Мониторинг', + monitorNotReady: 'Виртуальная машина не запущена. Данные мониторинга недоступны.', + monitorLoadFailed: 'Не удалось получить данные мониторинга ВМ.', + monitorLoadFailedWithReason: 'Не удалось получить данные мониторинга ВМ: {0}', + rename: 'Переименовать', newName: 'Новое имя', - renameHelper: 'Enter a new VM name. The VM must be shut down before renaming.', - renameConfirm: 'Rename virtual machine [{0}] to [{1}]?', - renameRunningHelper: 'Shut down the virtual machine before renaming it.', - cpuUsage: 'CPU Usage', - memoryUsage: 'Memory Usage', - diskIO: 'Disk IO', - networkIO: 'Network IO', - diskReadWrite: 'Disk Read / Write', - networkRxTx: 'Network RX / TX', + renameHelper: 'Введите новое имя ВМ. Перед переименованием ВМ должна быть выключена.', + renameConfirm: 'Переименовать виртуальную машину [{0}] в [{1}]?', + renameRunningHelper: 'Выключите виртуальную машину перед переименованием.', + cpuUsage: 'Использование CPU', + memoryUsage: 'Использование памяти', + diskIO: 'Ввод-вывод диска', + networkIO: 'Сетевой ввод-вывод', + diskReadWrite: 'Чтение / Запись диска', + networkRxTx: 'Приём / Передача по сети', rx: 'RX', tx: 'TX', console: 'Консоль', @@ -6456,16 +6881,18 @@ const message = { consoleConnectFailed: 'Не удалось подключиться к консоли VNC. Проверьте службу прокси консоли.', consoleCredentialsRequired: 'Для консоли VNC требуются учётные данные. Проверьте конфигурацию backend-прокси.', - snapshot: 'Snapshot', - createSnapshot: 'Create Snapshot', - recoverSnapshot: 'Recover Snapshot', + snapshot: 'Снимок', + createSnapshot: 'Создать снимок', + recoverSnapshot: 'Восстановить снимок', snapshotSize: 'Использовано', - currentSnapshot: 'Current', - snapshotEmpty: 'No snapshots', + currentSnapshot: 'Текущий', + snapshotEmpty: 'Нет снимков', snapshotHelper: - 'A snapshot saves the current VM state as a restore point. Subsequent data changes are recorded in a delta file without changing the original disk. Restoring a snapshot returns the VM to that point in time.', + 'Снимок сохраняет текущее состояние ВМ как точку восстановления. Последующие изменения записываются в разностный файл без изменения исходного диска. Восстановление снимка возвращает ВМ к этому состоянию.', + snapshotOperationHelper: + 'Текущий снимок нельзя удалить. Восстановить снимок можно только при выключенной виртуальной машине.', snapshotRecoverConfirm: - 'Recover virtual machine [{1}] to snapshot [{0}]? The VM disk will be restored to the snapshot state.', + 'Восстановить виртуальную машину [{1}] до снимка [{0}]? Диск ВМ будет возвращён к состоянию снимка.', interface: 'Сетевой интерфейс', device: 'Устройство', path: 'Путь', diff --git a/frontend/src/lang/modules/tr.ts b/frontend/src/lang/modules/tr.ts index ecff47aa8..3bd639ee5 100644 --- a/frontend/src/lang/modules/tr.ts +++ b/frontend/src/lang/modules/tr.ts @@ -14,6 +14,7 @@ const message = { next: 'Sonraki', create: 'Oluştur', add: 'Ekle', + select: 'Seç', save: 'Kaydet', set: 'Ayarlar', sync: 'Senkronize Et', @@ -27,7 +28,6 @@ const message = { setDefault: 'Varsayılanları Geri Yükle', restart: 'Yeniden Başlat', conn: 'Bağlan', - disconn: 'Bağlantıyı Kes', clean: 'Temizle', cleanAll: 'Tümünü temizle', selectAll: 'Tümünü seç', @@ -57,6 +57,7 @@ const message = { power: 'Gönder', search: 'Ara', refresh: 'Yenile', + reconnect: 'Yeniden bağlan', get: 'Al', upgrade: 'Yükselt', update: 'Güncelle', @@ -166,6 +167,7 @@ const message = { deleteSuccess: 'Başarıyla silindi', loginSuccess: 'Başarıyla giriş yapıldı', operationSuccess: 'Başarıyla tamamlandı', + operationFailed: 'İşlem başarısız', copySuccess: 'Başarıyla kopyalandı', notSupportOperation: 'Bu işlem desteklenmiyor', requestTimeout: 'İstek zaman aşımına uğradı, lütfen daha sonra tekrar deneyin', @@ -198,7 +200,7 @@ const message = { creatingInfo: 'Oluşturuluyor, bu işlem gerekli değil', installSuccess: 'Yükleme başarılı', uninstallSuccess: 'Kaldırma başarılı', - offlineTips: 'A versão offline não suporta esta operação', + offlineTips: 'Çevrimdışı sürüm bu işlemi desteklemiyor', errImportFormat: 'İçe aktarma verisi veya biçimi anormal, lütfen kontrol edip tekrar deneyin!', importHelper: 'Çakışan veya yinelenen verileri içe aktarırken, içe aktarılan içerik orijinal veritabanı verilerini güncellemek için standart olarak kullanılacaktır.', @@ -210,6 +212,7 @@ const message = { username: 'Kullanıcı adı', password: 'Şifre', passkey: 'Passkey ile giriş', + otherLoginMethods: 'Diğer giriş yöntemleri', welcome: 'Tekrar hoş geldiniz, giriş yapmak için kullanıcı adınızı ve şifrenizi girin!', errorAuthInfo: 'Girdiğiniz kullanıcı adı veya şifre yanlış, lütfen tekrar girin!', errorMfaInfo: 'Yanlış kimlik doğrulama bilgisi, lütfen tekrar deneyin!', @@ -291,6 +294,9 @@ const message = { length128Err: 'Uzunluk 128 karakteri geçemez', maxLength: 'Uzunluk {0} karakteri geçemez', alias: 'İngilizce, rakamlar, - ve _ destekler, uzunluk 1-128, ve -_ ile başlayamaz veya bitiremez.', + vmName: 'İngilizce harfler, sayılar, ".", "-" ve "_" desteklenir; uzunluk 1-64 olmalı ve bir harf veya sayıyla başlamalıdır.', + vmNetwork: + 'İngilizce harfler, sayılar, ".", ":", "-" ve "_" desteklenir; uzunluk 1-64 olmalı ve bir harf veya sayıyla başlamalıdır.', }, res: { paramError: 'İstek başarısız, lütfen daha sonra tekrar deneyin!', @@ -472,7 +478,7 @@ const message = { cpuSteal: 'Çalıntı', cpuTop: 'CPU Kullanımına Göre İlk 5 İşlem', memTop: 'Bellek Kullanımına Göre İlk 5 İşlem', - loadAverage: 'Son 1 dakikadaki yük ortalaması | Son {n} dakikadaki yük ortalaması', + loadAverage: 'Son {0} dakikadaki yük ortalaması', load: 'Yük', mount: 'Bağlama noktası', fileSystem: 'Dosya sistemi', @@ -508,6 +514,7 @@ const message = { deleteBackupHelper: 'Veritabanı yedeklerini aynı anda sil', delete: 'Silme işlemi geri alınamaz, lütfen "', deleteHelper: '" girerek bu veritabanını silin', + deleteUserHelper: '" girerek bu kullanıcıyı silin', userBoundDatabases: 'aşağıdaki veritabanlarına erişebilir:', noMysql: 'Veritabanı hizmeti (MySQL veya MariaDB)', noPostgresql: 'Veritabanı hizmeti PostgreSQL', @@ -558,6 +565,7 @@ const message = { revokeAuthorizationHelper: '{0} kullanıcısının {1} veritabanına erişimi kaldırılsın mı?', supplementPassword: 'Parola ekle', supplementPasswordHelper: 'Yalnızca mevcut parolayı 1Panel içine kaydeder; MySQL parolasını değiştirmez.', + noUserBind: 'Bağlantı yok', pgBindHelper: 'Bu işlem yeni bir kullanıcı oluşturmak ve hedef veritabanına bağlamak için kullanılır. Şu anda veritabanında mevcut olan kullanıcıları seçmek desteklenmiyor.', pgSuperUser: 'Süper Kullanıcı', @@ -1005,9 +1013,6 @@ const message = { failureCount: 'Hata sayısı', lastError: 'Son hata', modelMap: 'Model eşlemesi', - apiKeyKeepEmpty: 'API Key (değiştirmemek için boş bırakın)', - apiKeyOnceHint: 'API Key oluşturulduktan sonra yalnızca bir kez gösterilir. Şimdi kopyalayıp kaydedin.', - apiKeyOnceSave: 'API Key yalnızca bir kez gösterilir. Şimdi kaydedin:', qpsLimit: 'QPS sınırı', tokenLimit: 'Token sınırı', tokenUsed: 'Kullanılan Token', @@ -1149,23 +1154,23 @@ const message = { modelGroupGuide: 'Model grupları AI Ağ Geçidinin sunduğu istek modeli adlarını içerir. Üst modelleri hesap havuzundaki model eşlemesinde yapılandırın. auto sanal bir model adıdır ve model grubuna eklenmez.', modelGroupModelCount: '{0} model', - contentCompliance: 'Content Compliance', - contentAction: 'Action', - actionBlock: 'Block', - actionAuditOnly: 'Audit only', + contentCompliance: 'İçerik Uyumluluğu', + contentAction: 'Eylem', + actionBlock: 'Engelle', + actionAuditOnly: 'Yalnızca denetle', actionDropHistory: 'Geçmişi sil', - severity: 'Severity', - severityHigh: 'High', - severityMedium: 'Medium', - severityLow: 'Low', - sensitiveWord: 'Sensitive word', - sensitiveGroup: 'Sensitive word group', - sensitiveWordCount: 'Words', - normalizedWord: 'Normalized word', - matchedWords: 'Matched words', - matchedGroups: 'Matched groups', - importResult: 'Imported {0}, duplicated {1}, invalid {2}', - auditLogs: 'Audit Logs', + severity: 'Önem Derecesi', + severityHigh: 'Yüksek', + severityMedium: 'Orta', + severityLow: 'Düşük', + sensitiveWord: 'Hassas kelime', + sensitiveGroup: 'Hassas kelime grubu', + sensitiveWordCount: 'Kelimeler', + normalizedWord: 'Normalleştirilmiş kelime', + matchedWords: 'Eşleşen kelimeler', + matchedGroups: 'Eşleşen gruplar', + importResult: 'İçe aktarılan {0}, yinelenen {1}, geçersiz {2}', + auditLogs: 'Denetim Günlükleri', smartRoute: 'Akıllı Yönlendirme', smartRouteGuideTitle: 'Akıllı yönlendirme için istemcide model=auto kullanın', smartRouteGuideReady: @@ -1485,14 +1490,14 @@ const message = { streamableHttpPathHelper: 'Örneğin: /mcp, diğer Sunucularla çakışmaması gerektiğine dikkat edin', npxHelper: 'npx veya ikili dosya ile başlatılan mcp için uygundur', uvxHelper: 'uvx ile başlatılan mcp için uygundur', - protocolVersion: 'Protocol Version', + protocolVersion: 'Protokol Sürümü', protocolVersionHelper: - 'Only used by stateless Streamable HTTP to auto-initialize the downstream stdio MCP Server', + "Yalnızca durum bilgisi tutmayan Streamable HTTP tarafından aşağı akış stdio MCP Server'ı otomatik olarak başlatmak için kullanılır", gatewayArgsHelper: 'Bağımsız değişkenler supergateway komutuna eklenir. 1Panel tarafından yönetilen aktarım, bağlantı noktası, yol ve protokol bağımsız değişkenleri değiştirilemez', - testConnection: 'Test Connection', - connectionSuccess: 'Connection succeeded', - connectionFailed: 'Connection failed', + testConnection: 'Bağlantıyı Test Et', + connectionSuccess: 'Bağlantı başarılı', + connectionFailed: 'Bağlantı başarısız', }, tensorRT: { llm: 'TensorRT LLM', @@ -1567,8 +1572,9 @@ const message = { lastHour: 'Son saat', last10Min: 'Son 10 dakika', cleanLog: 'Log temizle', + cleanLogscope: 'Temizleme türü', downLogHelper1: 'Bu, {0} konteynerinden tüm logları indirecektir. Devam etmek istiyor musunuz?', - downLogHelper2: 'Bu, {0} konteynerinden son {0} logunu indirecektir. Devam etmek istiyor musunuz?', + downLogHelper2: 'Bu, {0} konteynerindeki en son {1} günlük kaydını indirecektir. Devam etmek istiyor musunuz?', cleanLogHelper: 'Bu, konteynerin yeniden başlatılmasını gerektirir ve geri alınamaz. Devam etmek istiyor musunuz?', newName: 'Yeni ad', @@ -1773,7 +1779,8 @@ const message = { dockerStatus: 'Docker Servisi', daemonJsonPathHelper: 'Yapılandırma yolunun docker.servicede belirtilen ile aynı olduğundan emin olun.', mirrors: 'Kayıt defteri aynaları', - mirrorsHelper: '', + mirrorsHelper: + "İmaj işlemlerinde önce kayıt defteri yansıtma URL'lerini kullanın. Kayıt defteri yansıtmalarını devre dışı bırakmak için boş bırakın.", mirrorsHelper2: 'Ayrıntılar için resmi belgelere bakın. ', registries: 'Güvenli olmayan kayıt defterleri', ipv6Helper: @@ -1837,7 +1844,6 @@ const message = { stopHelper: 'Bu işlem mevcut görev yürütmesini zorla durduracaktır. Devam etmek istiyor musunuz?', log: 'Yedekleme logları', logHelper: 'Sistem logunu yedekle', - ogHelper1: '1.1Panel Sistem logu ', logHelper2: '2. Sunucunun SSH giriş logu ', logHelper3: '3. Tüm site logları ', containerCheckBox: 'Konteynerde (konteyner komutunu girmeye gerek yok)', @@ -2302,6 +2308,7 @@ const message = { nodes: 'Düğüm', commands: 'Hızlı Komutlar', opsReport: 'Operasyon Raporu', + ops_report: 'Operasyon Raporu', users: 'Kullanıcı yönetimi', roles: 'Rol', auth: 'Giriş kimlik doğrulaması', @@ -2491,42 +2498,42 @@ const message = { 'Sol tarafta geçmiş sürümünün içeriği, sağ tarafta seçilen dosyanın en son sürümü gösterilir', copyDir: 'Kopyala', shareFile: 'Dosyayı paylaş', - shareExpire: 'Expires in', - shareExpire1h: '1 hour', - shareExpire6h: '6 hours', - shareExpire24h: '24 hours', - shareExpire3d: '3 days', - shareExpire7d: '7 days', - sharePassword: 'Password', - sharePasswordPlaceholder: 'Leave empty for no password', - shareMaxDownloads: 'Max downloads', - shareMaxDownloadsHint: '0 means unlimited', - shareGenerate: 'Create link', - shareRegenerate: 'Share again', - shareClose: 'Close', + shareExpire: 'Geçerlilik süresi', + shareExpire1h: '1 saat', + shareExpire6h: '6 saat', + shareExpire24h: '24 saat', + shareExpire3d: '3 gün', + shareExpire7d: '7 gün', + sharePassword: 'Parola', + sharePasswordPlaceholder: 'Parola kullanmamak için boş bırakın', + shareMaxDownloads: 'En fazla indirme', + shareMaxDownloadsHint: '0 sınırsız anlamına gelir', + shareGenerate: 'Bağlantı oluştur', + shareRegenerate: 'Yeniden paylaş', + shareClose: 'Kapat', shareCancel: 'Paylaşımı iptal et', shareCancelConfirm: 'Bu dosya paylaşımını iptal etmek istediğinize emin misiniz?', - shareDetail: 'Details', - shareCopyLink: 'Copy link', - shareLinkLabel: 'Share link', - shareQrCode: 'QR code', - shareQrDialogTitle: 'Share link QR code', - shareQrDialogHelper: 'Scan this QR code with your mobile device', - shareSaveImage: 'Save image', - shareOpenImage: 'Open image', - shareExtractFile: 'Extract file', - shareDownloadingHint: 'Preparing your file, download will begin shortly.', - shareInvalid: 'Invalid or expired share link', - shareDownloadFailed: 'Download failed, please try again later', - sharePasswordRequired: 'Password', - sharePasswordRequiredInput: 'Please enter the share password', - sharePasswordLengthHint: 'Share password length must be 4-256 characters', - shareDownloadPasswordTip: 'This link is password-protected. Enter the password before downloading.', + shareDetail: 'Ayrıntılar', + shareCopyLink: 'Bağlantıyı kopyala', + shareLinkLabel: 'Paylaşım bağlantısı', + shareQrCode: 'QR kodu', + shareQrDialogTitle: 'Paylaşım bağlantısı QR kodu', + shareQrDialogHelper: 'Bu QR kodunu mobil cihazınızla tarayın', + shareSaveImage: 'Görüntüyü kaydet', + shareOpenImage: 'Görüntüyü aç', + shareExtractFile: 'Dosyayı al', + shareDownloadingHint: 'Dosyanız hazırlanıyor. İndirme kısa süre içinde başlayacak.', + shareInvalid: 'Geçersiz veya süresi dolmuş paylaşım bağlantısı', + shareDownloadFailed: 'İndirme başarısız oldu. Daha sonra tekrar deneyin', + sharePasswordRequired: 'Erişim parolası', + sharePasswordRequiredInput: 'Paylaşım parolasını girin', + sharePasswordLengthHint: 'Paylaşım parolası 4-256 karakter uzunluğunda olmalıdır', + shareDownloadPasswordTip: 'Bu bağlantı parola korumalıdır. İndirmeden önce parolayı girin.', shareRiskAlert: - 'Shared links may carry security risks. Only share with trusted people and avoid exposing sensitive information.', + 'Paylaşılan bağlantılar güvenlik riski taşıyabilir. Yalnızca güvendiğiniz kişilerle paylaşın ve hassas bilgileri açığa çıkarmayın.', sharePasswordSeparate: - 'A password is set. Share it securely. Recipients must add &password=... to the URL or use a client that can pass the password query parameter.', - shareExpiresAt: 'Expires at', + 'Bir parola ayarlandı. Güvenli biçimde paylaşın. Alıcılar URL’ye &password=... eklemeli veya parola sorgu parametresini iletebilen bir istemci kullanmalıdır.', + shareExpiresAt: 'Bitiş zamanı', paste: 'Yapıştır', changeOwner: 'Kullanıcı ve kullanıcı grubunu değiştir', containSub: 'İzin değişikliğini özyinelemeli olarak uygula', @@ -3135,7 +3142,7 @@ const message = { recoverHelper3: 'Sunucu mimarisinin, anlık görüntünün oluşturulduğu sunucu mimarisiyle eşleştiğinden emin olun (Geçerli sunucu mimarisi: {0})', recoverHelper4: - 'Bu işlem yalnızca ana düğümü geri alır. Yükseltilmiş alt düğümler varsa, devam etmeden önce önce bunları geri alın.', + 'Bu işlem yalnızca ana düğümü geri alır. Yükseltilmiş alt düğümler varsa, devam etmeden önce bunları geri alın.', rollback: 'Geri al', rollbackHelper: 'Bu kurtarmayı geri almak, bu kurtarmadan gelen tüm dosyaları değiştirecek ve Docker ile 1Panel servislerinin yeniden başlatılmasını gerektirebilir. Devam etmek istiyor musunuz?', @@ -3280,6 +3287,7 @@ const message = { fileExchange: 'Ticari sürüme yükselterek birden fazla sunucu arasında dosyaları hızlıca aktarabilirsiniz.', app: 'Ticari sürüme yükselterek mobil uygulamada hizmet bilgilerini ve anormallik izlemeyi görüntüleyebilirsiniz.', cluster: 'Ticari sürüme yükselterek MySQL/Postgres/Redis birincil-kopya kümelerini yönetebilirsiniz.', + vllm: 'Ticari sürüme yükselterek vLLM hizmetlerini 1Panel içinde merkezi olarak dağıtabilir, yapılandırabilir, yaşam döngüsünü yönetebilir ve görevleri izleyebilirsiniz.', 'model-downloader': 'Ticari sürüme yükselterek HuggingFace, ModelScope veya uyumlu aynalardan yerel model dosyalarını arayabilir, indirebilir ve yönetebilir; model dizinlerini ve indirme görevlerini merkezi olarak takip edebilirsiniz.', }, @@ -3289,7 +3297,6 @@ const message = { clean: 'Şimdi temizle', reScan: 'Yeniden tara', cleanHelper: 'Seçilen dosya ve dizinler temizlendikten sonra geri alınamaz. Devam etmek istiyor musunuz?', - statusStatusSuggest: '(Temizlik Önerilir)', statusClean: '(Çok temiz)', statusEmpty: 'Çok temiz, temizlik gerekmiyor!', statusWarning: '(Dikkatli İlerleyin)', @@ -3804,16 +3811,16 @@ const message = { strategy: 'Strateji', strategyDown: 'Kapalı', strategyBackup: 'Yedek', - ipHashBackupErr: 'IP 哈希不支持备用节点', + ipHashBackupErr: 'IP hash yedek düğümleri desteklemez', failTimeout: 'Hata zaman aşımı', failTimeoutHelper: 'Sunucu sağlık kontrolleri için zaman penceresi uzunluğu. Bu süre içinde biriken hata sayısı eşiğe ulaştığında, sunucu geçici olarak kaldırılacak ve aynı süre sonunda yeniden denenir. Varsayılan 10 saniye', staticChangePHPHelper: 'Şu anda statik bir web sitesi, PHP web sitesine geçiş yapabilirsiniz', proxyCache: 'Ters Vekil Önbelleği', cacheLimit: 'Önbellek Alanı Sınırı', - shareCahe: 'Önbellek Sayısı Bellek Boyutu', + shareCache: 'Önbellek Sayısı Bellek Boyutu', cacheExpire: 'Önbellek Son Kullanma Süresi', - shareCaheHelper: 'Yaklaşık olarak 1M bellek başına 8000 önbellek nesnesi saklanabilir', + shareCacheHelper: 'Yaklaşık olarak 1M bellek başına 8000 önbellek nesnesi saklanabilir', cacheLimitHelper: 'Sınır aşıldığında eski önbellek otomatik olarak silinir', cacheExpireJHelper: 'Önbellek, son kullanma süresinden sonra kaçırılırsa silinir', realIP: 'Gerçek IP', @@ -3890,7 +3897,7 @@ const message = { max_file_uploads: 'Aynı anda yüklenebilecek maksimum dosya sayısı', default_socket_timeout: 'Soket zaman aşımı', error_reporting: 'Hata seviyesi', - display_errors: 'Ayrıntılı hata bilgilerinin 출력lenip 출력lenmeyeceği', + display_errors: 'Ayrıntılı hata bilgilerinin görüntülenip görüntülenmeyeceği', cgi_fix_pathinfo: 'Pathinfo’nun açılıp açılmayacağı', date_timezone: 'Zaman dilimi', disableFunction: 'Devre dışı bırakma fonksiyonu', @@ -4171,6 +4178,7 @@ const message = { }, runtime: { runtime: 'Çalışma Zamanı', + default: 'Varsayılan', workDir: 'Çalışma dizini', localHelper: 'Yerel ortam kurulumu ve çevrimdışı ortam kullanımı sorunları için lütfen bakın ', versionHelper: 'PHP sürümü, ör. v8.0', @@ -4477,8 +4485,10 @@ const message = { scorePanelHTTPSDisabled: 'Panel HTTPS devre dışı', scoreSSHRootLogin: 'SSH root girişi etkin', scoreSSHPasswordAuth: 'SSH şifre doğrulaması etkin, anahtar doğrulaması devre dışı', + scoreSSLExpired: '{0} sertifikasının süresi doldu', scoreSSLHigh: '{0} sertifikasının {1} günü kaldı', scoreSSLMedium: '{0} sertifikasının {1} günü kaldı', + scoreWebsiteExpired: '{0} web sitesinin süresi doldu', scoreWebsiteExpire: '{0} web sitesinin {1} günü kaldı', scoreWebsiteHTTP: '{0} HTTPS kullanmıyor', scoreWebsiteStopped: '{0} durumu anormal', @@ -4524,6 +4534,7 @@ const message = { panelLogin: 'Panel Girişi', sshLogin: 'SSH Girişi', failedRecord: 'Başarısız Kayıtlar', + expired: 'Süresi doldu', expiredDays: '{0} gün önce süresi doldu', remainingDays: '{0} · {1} gün kaldı', enabled: 'Etkin', @@ -4788,9 +4799,9 @@ const message = { abnormalSites: 'Anormal Siteler', count5xxSource: '5xx isteklere göre sayılır', wafIntercept: 'WAF Engelleme', - highRiskHit: 'Yüksek Riskli Eşleşme', websiteMonitorDisabledOrNoData: 'Web sitesi izleme devre dışı veya izleme verisi yok', wafDisabledOrNoData: 'WAF devre dışı veya engelleme verisi yok', + serviceEnabledButAbnormal: 'Etkin, ancak durumu anormal', noWafData: 'WAF engelleme verisi yok', sourceIP: 'Kaynak IP', hitCount: 'Eşleşme Sayısı', @@ -4851,6 +4862,7 @@ const message = { successRate: 'Başarı Oranı', failedJobs: 'Başarısız Görevler', recentRecoveryPoint: 'Son Kurtarma Noktası', + disabledCronjobTasks: 'Devre dışı zamanlanmış görevler', remoteCoverage: 'Uzak Kapsama', recent7Days: 'Son 7 gün', taskTypeStats: 'Görev Türü İstatistikleri', @@ -4872,6 +4884,7 @@ const message = { cronjobReasonDisabled: '{0} görev devre dışı', cronjobReasonLocalOnlyBackup: '{0} yalnızca yerel yedek görevi', cronjobReasonNormal: 'Görev yürütme ve yedekleme kapsamı normal', + riskLow: 'Düşük Risk', viewFailedRecords: 'Başarısız Görevleri Gör', viewCronjobTasks: 'Zamanlanmış Görevleri Gör', checkBackupTasks: 'Yedek Görevlerini Kontrol Et', @@ -4972,6 +4985,14 @@ const message = { authManage: 'Kimlik doğrulama yönetimi', auth: { providerNavigation: 'Kimlik doğrulama sağlayıcıları', + defaultNode: 'Varsayılan düğüm', + defaultNodePlaceholder: 'Bir düğüm seçin', + defaultNodeHelper: 'Yalnızca yeni kullanıcılar için.', + defaultNodeRequired: 'Geçerli bir varsayılan düğüm seçin.', + nodesLoadFailed: 'Düğümler yüklenemedi. Varsayılan düğümü seçmeden önce yeniden deneyin.', + nodeHandling: 'Düğüm işlemi', + assignDefaultNode: 'Varsayılan düğümü ata: {node}', + keepExistingNode: 'Mevcut düğüm izinlerini koru', providers: { ldap: 'AD/LDAP', passkey: 'Passkey', @@ -4999,7 +5020,416 @@ const message = { planned: 'Planlanan', plannedTitle: '{0} kimlik doğrulama ayarları', plannedDesc: 'Bu kimlik doğrulama sağlayıcısı planlanmıştır ve henüz kullanılamamaktadır.', + oidc: { + accessMode: 'Bağlantı modu', + accessModeDesc: "Kimlik sağlayıcının desteklediği durumlarda standart Discovery'i kullanın.", + actionCreate: 'Kullanıcı oluştur', + actionKeepName: 'Mevcut kullanıcı adını koruyun', + actionPending: 'Sonuç bekleniyor', + actionReject: 'Giriş yapmayı reddet', + actionUpdate: 'Kimlik bilgilerini güncelle', + advanced: 'Gelişmiş ayarlar', + advancedDesc: + 'Sağlayıcı bir uyumluluk seçeneği gerektirmediği sürece güvenli varsayılanları koruyun.', + assignDefaultRole: 'Varsayılan rolü ata: {role}', + authorizationEndpoint: 'Authorization Endpoint', + authorizationEndpointInvalid: 'Geçerli bir Authorization Endpoint girin.', + authorizationFlow: 'Yetkilendirme akışı', + automatic: 'Otomatik', + automaticPolicy: 'Otomatik işleme politikası', + automaticPolicyDesc: 'Bu kurallar arka uç tarafından uygulanır ve yönetici anahtarları değildir.', + basic: 'Temel ayarlar', + basicDesc: 'Sağlayıcı modunu seçin, ardından istemciyi ve geri aramayı yapılandırın.', + browserTest: 'Tarayıcı test girişi', + browserTestConflict: 'Kimlik doğrulandı ancak kullanıcı adı çakışıyor', + browserTestConflictHelper: + 'Eşlenen kullanıcı adı başka bir kimliğe aittir ve talep edilmeyecektir.', + browserTestExpired: 'Tarayıcı testinin süresi doldu', + browserTestExpiredHelper: + 'Yeni bir tarayıcı testi başlatın ve süresi dolmadan yetkilendirmeyi tamamlayın.', + browserTestFailed: 'Tarayıcı testi başarısız oldu', + browserTestFailedHelper: + 'Kimlik önizlemesi tamamlanamadı. Yerelleştirilmiş arka uç hatasını inceleyin.', + browserTestIsolation: + 'Bu işlem gerçek bir yetkilendirme gidiş-dönüşü gerçekleştirir ancak kullanıcı oluşturmaz veya güncellemez, rol atamaz ya da kimliği doğrulanmış bir panel oturumu oluşturmaz.', + browserTestPopupBlocked: + 'Bu site için açılır pencerelere izin verin, ardından tarayıcı testini yeniden başlatın.', + browserTestPopupClosed: 'Yetkilendirme penceresi test tamamlanmadan kapatıldı.', + browserTestSuccess: 'Provider doğrulaması başarılı oldu', + browserTestSuccessHelper: + 'Kimlik eşlemenin önizlemesi, kullanıcıları veya oturumları değiştirmeden yapıldı.', + browserTestTitle: 'OIDC tarayıcı testi girişi', + browserTestWaiting: 'Provider yetkilendirmesi bekleniyor', + browserTestWaitingHelper: + 'Yeni tarayıcı penceresinde oturum açma işlemini tamamlayın. Bu sayfa otomatik olarak güncellenecektir.', + callbackCopied: 'OIDC geri arama URL kopyalandı.', + callbackURL: 'Geri arama URL', + callbackURLHelper: + "Bu URL'yi kimlik sağlayıcıdaki istemcinin izin verilen geri çağırma URL'lerine ekleyin.", + cancelClearSecret: 'Temizlemeyi iptal et', + clearSecret: 'Sırrı temizle', + clearSecretConfirm: 'Client Secret yalnızca kaydettikten sonra kaldırılacaktır. Devam etmek?', + clientAuthMethod: 'İstemci kimlik doğrulama yöntemi', + clientAuthMethodHelper: + 'Kimlik sağlayıcıda bu istemci için yapılandırılan kimlik doğrulama yöntemini seçin.', + clientAuthMethodRequired: 'Bir istemci kimlik doğrulama yöntemi seçin.', + clientID: 'Client ID', + clientIDRequired: "Client ID'i girin.", + clientSecret: 'Client Secret', + clockSkew: 'Token zaman toleransı', + clockSkewHelper: + 'Kimlik sağlayıcı ile 1Panel arasındaki küçük zaman farklarına izin verir. Varsayılan 60 saniyeyi koruyun.', + clockSkewRequired: 'Token zaman toleransını girin.', + compatibilityMode: 'Uyumluluk modu', + compatibilityModeHelper: + 'Yalnızca eksik Discovery veya yeniden yazılmış uç noktalar için kullanın. Temel OIDC doğrulaması etkin kalır.', + configurationFailedHelper: + 'Test başarısız oldu. Sayfa yalnızca yerelleştirilmiş arka uç hatasını görüntüler.', + configurationFailedTag: 'Test başarısız oldu', + configurationHighRiskPassed: + 'Yapılandırma başarılı ancak yüksek riskli uyumluluk seçenekleri içeriyor.', + configurationHighRiskTag: 'Yüksek riskli yapılandırma başarılı oldu', + configurationNotTested: 'Mevcut konfigürasyon test edilmemiştir.', + configurationNotTestedTag: 'Test edilmedi', + configurationPassed: 'Mevcut yapılandırma güvenlik ve yetenek kontrollerini geçti.', + configurationPassedTag: 'Test geçti', + configurationStaleHelper: 'Yapılandırma değiştirildi. Kaydetmeden önce yeniden test edin.', + configurationStaleTag: 'Sonucun süresi doldu', + configurationTestMeta: + 'Test zamanı: {time}; {duration} ms içinde tamamlandı. Ham Provider yanıtları saklanmaz.', + configurationTestResult: 'Yapılandırma testi sonucu', + configurationTestResultDesc: + "Bu, yalnızca Discovery'i ve yeteneklerini kontrol eder; yetkilendirme kodunu değiştirmez veya Client Secret'i kanıtlamaz. Uçtan uca doğrulama için tarayıcı testi girişini kullanın.", + configurationTestSuccess: 'OIDC yapılandırma testi başarılı oldu.', + configurationTesting: 'Mevcut OIDC yapılandırması test ediliyor…', + configurationTestingTag: 'Test', + configureSecret: 'Sırrı yapılandır', + conflictExistingRename: "Bağlı bir subject, dolu olan yeni bir name'i döndürür", + conflictExistingRenameResult: + "Mevcut User.Name'i koruyun ve bağlı kullanıcının oturum açmasına izin verin", + conflictLDAP: 'LDAP kullanıcısı', + conflictLocal: 'Yerel kullanıcı', + conflictNewAvailable: 'Yeni subject ve eşlenen name mevcut', + conflictNewAvailableResult: 'Kurumsal kullanıcı oluşturun ve varsayılan rolü atayın', + conflictNone: 'Çatışma yok', + conflictOIDC: 'Başka bir OIDC kimliği', + conflictOccupied: 'Eşlenen name yerel bir LDAP veya başka bir OIDC kimliğine aittir', + conflictOccupiedResult: 'Yeni kimliği reddet; asla otomatik olarak bağlama veya birleştirme', + conflictType: 'Çatışma türü', + connectionSecurity: 'Bağlantı güvenliği', + connectionSecurityDesc: + 'TLS politikası Discovery, Token, JWKS ve UserInfo istekleri için geçerlidir.', + connectionTest: 'Bağlantı ve konfigürasyon testi', + connectionTestCompatibilityDesc: 'Özel uç noktaları ve protokol güvenlik ilkesini doğrulayın.', + connectionTestStandardDesc: "Uç noktalar ve yetenekler Issuer'ten otomatik olarak keşfedilir.", + connectionTestTab: 'Bağlantı testi', + customCA: 'Özel CA', + customCAHelper: + 'Yalnızca bu kimlik doğrulama kaynağı için geçerlidir ve hiçbir zaman günlüklere yazılmaz.', + customCARequired: 'Özel CA sertifikasını sağlayın.', + defaultRole: 'Varsayılan rol', + defaultRoleHelper: + 'Yalnızca kullanıcı ilk oluşturulduğunda atanır; sonraki oturum açmalar rolü değiştirmez.', + defaultRolePlaceholder: 'Bir rol seçin', + defaultRoleRequired: 'Geçerli bir varsayılan rol seçin.', + disableAfterSave: 'Kaydettikten sonra OIDC devre dışı bırakılacak.', + disableConfirm: + "OIDC'in devre dışı bırakılması, bu kaynağın kullanıcılarının erişimini anında geçersiz kılar. Devam etmek?", + disableDiscardConfirm: + "OIDC'in devre dışı bırakılması acil bir eylemdir: yalnızca oturum açma girişini kapatır ve bu kaynağın kullanıcıları için erişimi anında geçersiz kılar. Client Secret değişiklikleri de dahil olmak üzere bu sayfadaki diğer kaydedilmemiş değişiklikler silinecektir. Devam etmek?", + disableTitle: "OIDC'i devre dışı bırakın", + disabled: 'Devre dışı', + discoveryAllowlist: 'Discovery ∩ güvenlik izin verilenler listesi', + enable: 'Etkinleştir', + enableAfterSave: 'Başarılı bir kaydetme işleminden sonra OIDC etkinleştirilecektir.', + enabled: 'Etkin', + endSessionEndpoint: 'End Session Endpoint', + endSessionEndpointHelper: + 'Gelecekte kullanılmak üzere kaydedildi; Provider tarafından başlatılan oturum kapatma bu sürüme dahil değildir.', + endSessionEndpointInvalid: 'Geçerli bir End Session Endpoint girin.', + endpointDiscoveryPlaceholder: 'Bağlantı testinden sonra gösterilir', + firstLogin: 'İlk giriş', + firstLoginPolicy: + 'Yerel bir kurumsal kullanıcı oluşturun ve yapılandırılmış varsayılan rolü atayın.', + fixedAuthorizationCode: 'Authorization Code Flow', + fixedNoTokenPersistence: "Token'ler, Claims ve verifier hiçbir zaman kalıcı olmaz", + fixedSecurityPolicy: 'Her zaman uygulanır; yapılandırma gerekmez', + fixedStateNonce: 'Bir kerelik state ve nonce', + fixedTokenValidation: 'ID Token imzası ve Claims doğrulaması', + highRiskSaveConfirm: + 'Bu etkinleştirilmiş yapılandırma, yüksek riskli uyumluluk seçeneklerini içerir. Yalıtılmış ortamın bunları gerektirdiğini doğrulayın.', + highRiskTitle: 'Yüksek riskli OIDC yapılandırması', + hs256Compatibility: 'HS256 (uyumluluk)', + hs256KeyHelper: + "HS256 her zaman bu kaynağın Client Secret'ini kullanır ve ayrı bir imzalama anahtarını kabul etmez.", + hs256Warning: + "HS256, ID Token imzaları için paylaşılan bir simetrik sır kullanır. Bunu yalnızca Provider'in asimetrik bir algoritma kullanamadığı durumlarda kullanın.", + identityBindingPolicy: + "Kimlik AuthSourceID + issuer + subject'e sabitlenmiştir. Kullanıcı adının eşleşmesi başka bir hesabın otomatik olarak sahiplenilmesine yol açmaz.", + identityMissing: 'Kimlik etkin değil', + issuer: 'Issuer URL', + issuerHelper: 'ID Token iss değeri ve Discovery issuer bu değerle tam olarak eşleşmelidir.', + issuerInvalid: 'Sorgu veya parça olmadan geçerli bir HTTP veya HTTPS Issuer URL girin.', + issuerRequired: "Issuer URL'i girin.", + jwksRotation: 'Otomatik JWKS dönüşü', + jwksURI: 'JWKS URI', + jwksURIHelper: 'Anahtar kaynağı JWKS olduğunda asimetrik imzalama için gereklidir.', + jwksURIInvalid: 'Seçilen imzalama anahtarı kaynağı için geçerli bir JWKS URI girin.', + keepExistingRole: 'Mevcut rolleri ve yerel izinleri koruyun', + localSecurityData: 'Yerel güvenlik verileri', + localSecurityDataPolicy: + "Hiçbir zaman rollerin, MFA, API Keys, Passkeys'in veya yerel izinlerin üzerine yazmayın.", + localCredentialsManaged: + 'Kullanıcı adı ve yerel parola OIDC tarafından yönetilir ve burada düzenlenemez. Roller, izinler, MFA, API Keys ve Passkeys yerel olarak yönetilmeye devam eder.', + localUserFields: 'Yerel kullanıcı alanları', + localUserFieldsDesc: "İlk sürüm yalnızca User.Name'i eşler ve bir JSON eşleme ifadesi kullanmaz.", + loginWith: '{provider} ile giriş yap', + manualEndpoints: 'Özel uç noktalar', + manualEndpointsDesc: + 'Yalnızca Discovery eksik olduğunda veya bir yukarı akış ağ geçidi uç noktaları yeniden yazdığında kullanın.', + mappingResult: 'Eşleme sonucu', + mode: 'Bağlantı modu', + modeRequired: 'Bir bağlantı modu seçin.', + nameClaim: "Kullanıcı adı Claim'i", + nameClaimHelper: 'Kullanıcı adını içeren alanı girin (ör. preferred_username).', + nameClaimRequired: "Kullanıcı adı Claim'ini girin.", + nameConflict: 'Ad çakışması politikası', + panelURL: '1Panel halka açık URL', + panelURLHTTPWarning: + 'HTTP yetkilendirme yanıtını korumaz. Bunu yalnızca Provider tarafından kabul edilen yalıtılmış bir özel ortamda kullanın.', + panelURLHelper: + "Kullanıcıların 1Panel'e eriştiği adresi girin. Geri çağırma URL'sini oluşturmak için kullanılır.", + panelURLInvalid: + 'Yalnızca şema, ana bilgisayar ve isteğe bağlı bağlantı noktasını içeren bir kaynak girin.', + panelURLRequired: "1Panel genel URL'i girin.", + pkceDisabled: 'Devre dışı (yalnızca uyumluluk)', + pkceDisabledWarning: + "PKCE'in devre dışı bırakılması, yetkilendirme kodu müdahalesine karşı korumayı azaltır.", + pkceHelper: "S256'i tercih edin. plain sınama yöntemi hiçbir zaman sunulmaz.", + pkceS256: 'S256 (önerilir)', + plannedHandling: 'Planlı kullanım', + privateNetworkIdP: "Özel ağ IdP'si", + privateNetworkIdPHelper: + 'Açıkça özel adreslere izin verir; meta veriler, geridöngü, yerel bağlantı, yönlendirmeler ve DNS yeniden bağlama engellenmeye devam eder.', + privateNetworkWarning: 'Bu kimlik doğrulama kaynağı için özel ağ erişimi etkinleştirildi.', + protocolCompatibility: 'Protokol uyumluluğu', + protocolCompatibilityDesc: 'ID Token imza doğrulaması hiçbir zaman devre dışı bırakılamaz.', + providerAndClient: 'Provider ve istemci', + providerAndClientDesc: + 'Client Secret yalnızca değiştirilebilir veya silinebilir ve sayfa tarafından asla geri döndürülmez.', + providerCapabilities: 'Provider yetenekleri', + recentTestSuccess: 'Son test başarılı oldu: {0}', + recommended: 'Tavsiye edilen', + rejectPlain: 'plain reddedildi', + replaceSecret: 'Sırrı değiştir', + requestAndClaims: 'İstekler ve özellikler', + requestAndClaimsDesc: + 'Yetkilendirme kapsamlarını, kullanıcı bilgisi tamamlamayı ve istek parametrelerini yapılandırın.', + requestTimeout: 'İstek zaman aşımı', + requestTimeoutRequired: 'İstek zaman aşımını girin.', + restore: 'Geri yükle', + restored: 'Son kaydedilen OIDC ayarları geri yüklendi.', + result: 'Sonuç', + rolesLoadFailed: 'Roller yüklenemedi. Varsayılan rolü seçmeden önce yeniden deneyin.', + roleHandling: 'Rol yönetimi', + scenario: 'Senaryo', + scopes: 'Yetkilendirme kapsamları', + scopesHelper: 'openid içermelidir. Birden fazla kapsamı boşluklarla ayırın.', + scopesRequired: "Scopes, openid'i içermelidir.", + seconds: 'saniye', + secretClearHelper: + "Temizledikten sonra, OIDC'in yeniden etkinleştirilebilmesi için yeni bir Client Secret gereklidir.", + secretConfigured: 'Yapılandırılmış', + secretNotConfigured: 'Yapılandırılmadı', + secretPlaceholder: 'Yeni bir Client Secret girin', + secretReplaceHelper: + "Kaydettiğinizde yeni gizli anahtar mevcut değerin yerini alır. OIDC Provider'daki Client Secret değerini de güncelleyin.", + secretRequiredHelper: "OIDC'i etkinleştirmeden önce bir Client Secret'i yapılandırın.", + secretRequiredToEnable: "OIDC'i etkinleştirmeden önce bir Client Secret'i yapılandırın.", + secretSavedHelper: 'Şifrelenmiş olarak saklanır. Mevcut sırrı korumak için boş bırakın.', + secretWaiting: 'Giriş bekleniyor', + secretWillClear: 'Temizlenecek', + secretWillReplace: 'Değiştirilecek', + signingAlgorithm: 'ID Token imzalama algoritması', + signingAlgorithmHelper: + 'Yalnızca arka uç güvenliği izin verilenler listesindeki algoritmalar kullanılabilir.', + signingKey: 'İmza anahtarı', + signingKeyClientSecret: 'Client Secret (yalnızca HS256)', + signingKeyJWKS: 'Otomatik rotasyonlu JWKS URI', + signingKeySource: 'İmza anahtarı kaynağı', + signingKeySourceHelper: + "JWKS'i tercih edin. Statik açık anahtar otomatik olarak rotasyona tabi tutulamaz.", + signingKeyStatic: 'Statik JWK veya PEM açık anahtarı', + standardDiscovery: 'Standart OIDC Discovery', + standardDiscoveryDesc: '1Panel uç noktaları ve yetenekleri keşfeder ve ham belgeyi saklamaz.', + standardMode: 'Standart mod', + standardModeHelper: "Issuer'in uç noktalarını, imzalama yeteneklerini ve PKCE desteğini keşfedin.", + standardProtocolPolicy: 'Standart protokol politikası', + standardProtocolPolicyDesc: + 'İmzalama yetenekleri otomatik olarak müzakere edilir; buraya herhangi bir imzalama anahtarı girilmez.', + staticSigningKey: 'Statik imzalama açık anahtarı', + staticSigningKeyHelper: + 'Yalnızca açık anahtar materyali kabul edilir. Provider anahtarı değiştiğinde manuel olarak güncelleyin.', + staticSigningKeyPlaceholder: 'JWK, JWKS JSON veya PEM açık anahtarını yapıştırın', + staticSigningKeyRequired: 'Statik imzalama açık anahtarını sağlayın.', + staticSigningKeyWarning: + 'Statik imzalama anahtarı otomatik olarak yenilenemez; Provider anahtar rotasyonu yapmadan önce güncelleyin.', + settingLoadFailed: 'OIDC ayarları yüklenemedi', + settingLoadFailedHelper: + 'Geçerli ayarların üzerine boş bir varsayılan yapılandırmanın kaydedilmesini önlemek için form kilitlendi. Bağlantı kurtarıldıktan sonra yeniden deneyin.', + subsequentLogin: 'Sonraki giriş', + subsequentLoginPolicy: + "subject ile bağlamayı bulun ve yalnızca yeni ad kullanılabilir olduğunda User.Name'i güncelleyin.", + testBeforeBrowserTest: + 'Tarayıcı oturum açma testine başlamadan önce mevcut yapılandırmayı test edin.', + testBeforeEnable: 'Yapılandırma değişikliklerini kaydetmeden önce mevcut yapılandırmayı test edin.', + testConfiguration: 'Yapılandırmayı test et', + testDiscovery: 'Discovery testi', + tlsCustomCA: 'HTTPS · Özel CA sertifikası', + tlsPrivateHTTP: 'HTTP · Yalnızca özel ağ (tehlikeli)', + tlsPrivateHTTPWarning: + 'HTTP aktarım şifrelemesi sağlamaz ve açıkça izin verilen özel hedeflerle sınırlıdır.', + tlsSkipVerify: 'HTTPS · Sertifika doğrulamasını atla (tehlikeli)', + tlsSystem: 'HTTPS · Sistem sertifikası doğrulaması (önerilir)', + tokenEndpoint: 'Token Endpoint', + tokenEndpointInvalid: 'Geçerli bir Token Endpoint girin.', + transportSecurity: 'Taşıma güvenliği', + transportSecurityHelper: + "HTTPS'i tercih edin. Özel HTTP ayrıca açık private-network erişimi gerektirir.", + unsavedChanges: 'Kaydedilmemiş OIDC değişiklikleri var.', + usedClaim: 'Claim kullanılmış', + userInfoEndpoint: 'UserInfo Endpoint', + userInfoEndpointHelper: + 'Kullanıcı adı alanı eksikse sistem bu endpoint üzerinden tamamlar. Tamamlama istemiyorsanız boş bırakın.', + userInfoEndpointInvalid: 'Geçerli bir UserInfo Endpoint girin.', + userMapping: 'Kullanıcı ayarları', + userMappingDesc: + 'OIDC kullanıcı adı eşlemesini ve ilk oturum açmada kullanıcı oluşturmak için kullanılacak varsayılan düğüm ile rolü ayarlayın.', + }, + saml2: { + actionCreate: 'Kullanıcı oluştur', + actionPending: 'Sonuç bekleniyor', + actionReject: 'Giriş yapmayı reddet', + actionReuse: 'Bağlı kullanıcıyı kullan', + assignDefaultRole: 'Varsayılan rolü ata: {role}', + basic: 'Temel ayarlar', + basicDesc: 'Çoğu standart SAML2 kimlik sağlayıcısı için gereken ortak seçenekleri yapılandırın.', + browserTest: 'Oturum açmayı test et', + browserTestConflict: 'Kimlik doğrulandı ancak kullanıcı adı çakışıyor', + browserTestConflictHelper: + 'Eşlenen kullanıcı adı başka bir kimliğe aittir ve talep edilmeyecektir.', + browserTestExpired: 'Tarayıcı testinin süresi doldu', + browserTestExpiredHelper: + 'Yeni bir tarayıcı testi başlatın ve süresi dolmadan yetkilendirmeyi tamamlayın.', + browserTestFailed: 'Tarayıcı testi başarısız oldu', + browserTestFailedHelper: + 'Kimlik önizlemesi tamamlanamadı. Yerelleştirilmiş arka uç hatasını inceleyin.', + browserTestIsolation: + 'Bu işlem gerçek bir yetkilendirme gidiş-dönüşü gerçekleştirir ancak kullanıcı oluşturmaz veya güncellemez, rol atamaz ya da kimliği doğrulanmış bir panel oturumu oluşturmaz.', + browserTestPopupBlocked: + 'Bu site için açılır pencerelere izin verin, ardından tarayıcı testini yeniden başlatın.', + browserTestPopupClosed: 'Yetkilendirme penceresi test tamamlanmadan kapatıldı.', + browserTestSuccess: 'Provider doğrulaması başarılı oldu', + browserTestSuccessHelper: + 'Kimlik eşlemenin önizlemesi, kullanıcıları veya oturumları değiştirmeden yapıldı.', + browserTestTitle: 'SAML2 tarayıcı testi girişi', + browserTestWaiting: 'Provider yetkilendirmesi bekleniyor', + browserTestWaitingHelper: + 'Yeni tarayıcı penceresinde oturum açma işlemini tamamlayın. Bu sayfa otomatik olarak güncellenecektir.', + certificateFileInvalid: 'Geçerli bir PEM, CRT veya CER sertifika dosyası seçin.', + configured: 'Yapılandırıldı', + configurationFailedHelper: + 'Test başarısız oldu. Sayfa yalnızca yerelleştirilmiş arka uç hatasını görüntüler.', + configurationNotTested: 'Mevcut konfigürasyon test edilmemiştir.', + configurationPassed: 'Mevcut yapılandırma güvenlik ve yetenek kontrollerini geçti.', + configurationStaleHelper: + 'Kimlik doğrulamaya duyarlı ayarlar değiştirildi. Mevcut taslağı tekrar test edin.', + configurationTestSuccess: 'SAML2 yapılandırma testi başarılı oldu.', + configurationTesting: 'Mevcut SAML2 yapılandırması test ediliyor…', + conflictLDAP: 'LDAP kullanıcısı', + conflictLocal: 'Yerel kullanıcı', + conflictNone: 'Çatışma yok', + conflictOIDC: 'Başka bir OIDC kimliği', + conflictSAML2: 'Başka bir SAML2 kimliği', + conflictType: 'Çatışma türü', + credentialFileReadFailed: 'Kimlik bilgisi dosyası okunamadı.', + credentialFileTooLarge: 'Kimlik bilgisi dosyaları 256 KiB boyutunu aşmamalıdır.', + credentialsRequired: 'SP özel anahtarını ve sertifikasını yapılandırın.', + defaultRole: 'Yeni kullanıcı rolü', + defaultRoleHelper: + 'Yalnızca ilk oluşturmada atanır; sonraki oturum açmalar yerel rolleri, MFA ve izinleri korur.', + defaultRolePlaceholder: 'Bir rol seçin', + defaultRoleRequired: 'Geçerli bir varsayılan rol seçin.', + disableConfirm: + 'SAML2 devre dışı bırakıldığında yeni oturum açmalar hemen reddedilir ve kullanıcı oturumları geçersiz kılınır. Devam edilsin mi?', + disableDiscardConfirm: + 'SAML2 devre dışı bırakıldığında bu sayfadaki diğer kaydedilmemiş değişiklikler atılır ve kullanıcı oturumları hemen geçersiz kılınır. Devam edilsin mi?', + disableTitle: 'SAML2’yi devre dışı bırak', + disabled: 'Devre dışı', + enable: 'Etkinleştir', + enabled: 'Etkin', + idpMetadata: 'IdP meta verileri', + idpMetadataDesc: 'Bir URL girin veya XML yapıştırın. İkisi de varsa URL önceliklidir.', + keepExistingRole: 'Mevcut rolleri ve yerel izinleri koruyun', + loginWith: '{provider} ile oturum aç', + mappingResult: 'Eşleme sonucu', + metadataRequired: 'IdP Metadata URL veya XML girin.', + metadataURLHelper: 'Arka uç, test ve kaydetme sırasında meta verileri indirip doğrular.', + metadataURLInvalid: 'Kimlik bilgisi veya parça içermeyen geçerli bir HTTPS meta veri URL’si girin.', + metadataURLRecommended: 'Meta veri URL’si (önerilen)', + metadataXML: 'XML meta verileri', + metadataXMLHelper: 'IdP erişilebilir bir meta veri URL’si sunmuyorsa bunu kullanın.', + metadataXMLInvalid: 'Geçerli bir EntityDescriptor meta veri XML’i girin.', + metadataXMLPlaceholder: '... içeriğini yapıştırın', + nameAttribute: 'Kullanıcı adı özniteliği', + nameAttributeHelper: + 'Bu özniteliği doğrulanmış SAML Assertion içinden okur ve 1Panel kullanıcı adına eşler.', + nameAttributePlaceholder: 'Örneğin: uid, username veya account', + nameAttributeRequired: 'Kullanıcı adı özniteliğini girin.', + notConfigured: 'Yapılandırılmadı', + or: 'veya', + pageDesc: 'IdP Metadata ile kurumsal SSO bağlantısını ortak ayarlarla tek sayfada yapılandırın.', + plannedHandling: 'Planlı kullanım', + privateKeyFileInvalid: 'Geçerli bir PEM özel anahtar dosyası seçin.', + recentTestSuccess: 'Son test başarılı oldu: {0}', + restore: 'Geri yükle', + restored: 'Son kaydedilen SAML2 ayarları geri yüklendi.', + roleHandling: 'Rol yönetimi', + rolesLoadFailed: 'Roller yüklenemedi. Varsayılan rolü seçmeden önce yeniden deneyin.', + selectFile: 'Dosya seç', + serviceStatus: 'Hizmet durumu', + serviceStatusDesc: 'SAML2 etkinleştirilmeden önce mevcut yapılandırma testi geçmelidir.', + settingLoadFailed: 'SAML2 ayarları yüklenemedi', + settingLoadFailedHelper: + 'Geçerli ayarların üzerine boş bir varsayılan yapılandırmanın kaydedilmesini önlemek için form kilitlendi. Bağlantı kurtarıldıktan sonra yeniden deneyin.', + spCertificate: 'SP sertifikası', + spCertificateHelper: + 'IdP’nin oturum açma ve kapatma isteklerini doğrulayabilmesi için SP meta verilerinde yayımlanır.', + spCredentials: 'SP özel anahtarı ve sertifikası', + spCredentialsDesc: + 'Oturum açma ve kapatma mesajlarını imzalamak için kullanılır. İmza ve doğrulama ilkesi arka uç tarafından sabitlenir.', + spPrivateKey: 'SP özel anahtarı', + spPrivateKeyHelper: + 'AuthnRequest ve oturum kapatma mesajlarını imzalamak için kullanılır. Saklanırken şifrelenir ve hiçbir zaman gösterilmez.', + syncLogout: 'Eşzamanlı oturum kapatma', + syncLogoutHelper: + "1Panel'den veya kimlik sağlayıcıdan çıkış yapmak diğer taraftaki oturumu da kapatır.", + testBeforeBrowserTest: + 'Tarayıcı oturum açma testine başlamadan önce mevcut yapılandırmayı test edin.', + testBeforeEnable: + 'Hassas değişiklikleri etkinleştirmeden veya kaydetmeden önce mevcut yapılandırmayı test edin.', + testConfiguration: 'Yapılandırmayı test et', + unsavedChanges: 'Kaydedilmemiş SAML2 değişiklikleri var.', + usedAttribute: 'Kullanıcı adı eşlemesi', + usersAndRoles: 'Kullanıcılar ve roller', + usersAndRolesDesc: + 'Panel kullanıcı adı eşlemesini ve ilk oturum açmada kullanıcı oluşturmak için kullanılacak varsayılan düğüm ile rolü ayarlayın.', + }, ldap: { + basic: 'Temel ayarlar', + loginTitle: 'LDAP ile giriş', + loginWith: 'LDAP ile giriş yap', + backToLocalLogin: 'Panel girişine dön', enable: 'Etkinleştir', enabled: 'Etkin', disabled: 'Devre dışı', @@ -5221,6 +5651,7 @@ const message = { deleteConfirm: 'Bu dışa aktarma kaydı ve dosyası silinsin mi?', }, waf: { + WAF: 'WAF', name: 'WAF', blackWhite: 'Kara ve Beyaz Liste', globalSetting: 'Genel Ayarlar', @@ -5941,6 +6372,8 @@ const message = { offlineHelper: 'Düğüm çevrimdışı bir ortamda olduğunda kullanılır', appUpgrade: 'Uygulama Yükseltme', appUpgradeHelper: 'Yükseltilmesi gereken {0} uygulama var', + dashboardSetting: 'Genel Bakış Ayarları', + keepOneDashboardComponent: 'En az bir genel bakış bölümü bırakın', }, customApp: { name: 'Özel Uygulama Deposu', @@ -6075,7 +6508,7 @@ const message = { success: 'Uyarı Başarılı', pushing: 'Gönderiliyor...', error: 'Uyarı Başarısız', - cleanLog: 'Zamanlanmış görev yürütmesi {0} hatası', + cleanLog: 'Günlükleri temizle', cleanAlertLogs: 'Uyarı Günlüklerini Temizle', daily: 'Günlük Uyarı Sayısı: {0}', cumulative: 'Toplam Uyarı Sayısı: {0}', @@ -6083,7 +6516,7 @@ const message = { taskName: 'Görev Adı', cronJobType: 'Görev Türü', clamPath: 'Tarama Dizini', - cronjob: 'Zamanlanmış Görev', + cronjob: 'Zamanlanmış görev yürütmesi {0} başarısız oldu', app: 'Yedekleme Uygulaması', web: 'Yedekleme Web Sitesi', database: 'Yedekleme Veritabanı', @@ -6339,35 +6772,35 @@ const message = { cpu: 'CPU', memory: 'Bellek', disk: 'Disk', - overview: 'Overview', - kvmUnavailable: 'No available KVM hardware virtualization capability was detected.', - kvmCheckCpu: 'Confirm that the host CPU supports Intel VT-x or AMD-V virtualization.', - kvmCheckBios: 'Enable virtualization options in BIOS/UEFI.', - kvmCheckModule: 'Confirm that the kvm, kvm_intel, or kvm_amd kernel module is loaded correctly.', + overview: 'Genel bakış', + kvmUnavailable: 'Kullanılabilir KVM donanım sanallaştırma yeteneği algılanmadı.', + kvmCheckCpu: 'Ana makine CPU’sunun Intel VT-x veya AMD-V sanallaştırmasını desteklediğini doğrulayın.', + kvmCheckBios: 'BIOS/UEFI içindeki sanallaştırma seçeneklerini etkinleştirin.', + kvmCheckModule: 'kvm, kvm_intel veya kvm_amd çekirdek modülünün doğru yüklendiğini doğrulayın.', kvmCheckDevice: - 'Confirm that /dev/kvm exists and the current environment is not a container or cloud host without KVM support.', - abnormal: 'Abnormal', - resourceOverview: 'Resource Overview', - cpuAllocated: 'CPU Allocated', - memoryAllocated: 'Memory Allocated', - storageUsed: 'Storage Used', - riskReminder: 'Risk Reminders', - noRisk: 'No risks', - runtimeHealth: 'Runtime Health', - runtimeAbnormal: 'VM runtime is abnormal', - noDependency: 'No dependency check data', - storageOverview: 'Storage Overview', - totalAllocated: 'Calculated by total VM configuration', - runningAllocated: 'Running allocation: {0}', - storageAvailable: 'Available: {0}', - inProgress: 'In progress', - needAttention: 'Needs attention', + '/dev/kvm dosyasının bulunduğunu ve mevcut ortamın KVM desteği olmayan bir konteyner ya da bulut ana makinesi olmadığını doğrulayın.', + abnormal: 'Anormal', + resourceOverview: 'Kaynak genel bakışı', + cpuAllocated: 'Ayrılan CPU', + memoryAllocated: 'Ayrılan bellek', + storageUsed: 'Kullanılan depolama', + riskReminder: 'Risk uyarıları', + noRisk: 'Risk yok', + runtimeHealth: 'Çalışma zamanı sağlığı', + runtimeAbnormal: 'VM çalışma zamanı anormal', + noDependency: 'Bağımlılık denetimi verisi yok', + storageOverview: 'Depolama genel bakışı', + totalAllocated: 'Toplam VM yapılandırmasına göre hesaplanır', + runningAllocated: 'Çalışanlara ayrılan: {0}', + storageAvailable: 'Kullanılabilir: {0}', + inProgress: 'Devam ediyor', + needAttention: 'İlgilenilmesi gerekiyor', normal: 'Normal', - environmentRisk: 'The VM runtime is not ready. Fix dependencies or virtualization services.', - storageRisk: 'Storage pool {0} usage has reached {1}%.', - abnormalRisk: '{0} VMs are in an abnormal state.', - pausedRisk: '{0} VMs are paused.', - memoryRisk: 'VM memory allocation has reached {0}%.', + environmentRisk: 'VM çalışma zamanı hazır değil. Bağımlılıkları veya sanallaştırma hizmetlerini düzeltin.', + storageRisk: '{0} depolama havuzunun kullanımı %{1} düzeyine ulaştı.', + abnormalRisk: '{0} VM anormal durumda.', + pausedRisk: '{0} VM duraklatıldı.', + memoryRisk: 'VM bellek ayırma oranı %{0} düzeyine ulaştı.', cpuLimitHelper: 'Şu anda kullanılabilir CPU: {0} çekirdek', cpuLimitExceeded: 'CPU sınırı aşıyor. Şu anki maksimum kullanılabilir: {0} çekirdek.', memoryLimitHelper: 'Şu anda ayrılabilir bellek: {0} (ana makine {1} bellek ayırmalıdır)', @@ -6376,11 +6809,11 @@ const message = { storageLimitExceeded: 'Disk kapasitesi sınırı aşıyor. Şu anki maksimum kullanılabilir: {0}.', iso: 'ISO', createFromTemplate: 'Şablondan oluştur', - template: 'Template', - templateName: 'Template Name', - convertToTemplate: 'Convert to Template', - sourceVM: 'Source VM', - templateSize: 'Template Size', + template: 'Şablon', + templateName: 'Şablon adı', + convertToTemplate: 'Şablona dönüştür', + sourceVM: 'Kaynak VM', + templateSize: 'Şablon boyutu', deleteTemplateConfirm: '{0} şablonu silinsin. Bu işlem geri alınamaz. Devam edilsin mi?', orphanClean: 'Sahipsiz veri temizliği', orphanScan: 'Yeniden tara', @@ -6424,21 +6857,21 @@ const message = { available: 'Kullanılabilir', vmCount: 'Bağlı VMler', usedIPs: 'Kullanılan IPler', - monitor: 'Monitor', - monitorNotReady: 'The virtual machine is not running. Monitoring data is unavailable.', - monitorLoadFailed: 'Failed to get VM monitoring data.', - monitorLoadFailedWithReason: 'Failed to get VM monitoring data: {0}', - rename: 'Rename', + monitor: 'İzleme', + monitorNotReady: 'Sanal makine çalışmıyor. İzleme verileri kullanılamıyor.', + monitorLoadFailed: 'VM izleme verileri alınamadı.', + monitorLoadFailedWithReason: 'VM izleme verileri alınamadı: {0}', + rename: 'Yeniden adlandır', newName: 'Yeni ad', - renameHelper: 'Enter a new VM name. The VM must be shut down before renaming.', - renameConfirm: 'Rename virtual machine [{0}] to [{1}]?', - renameRunningHelper: 'Shut down the virtual machine before renaming it.', - cpuUsage: 'CPU Usage', - memoryUsage: 'Memory Usage', - diskIO: 'Disk IO', - networkIO: 'Network IO', - diskReadWrite: 'Disk Read / Write', - networkRxTx: 'Network RX / TX', + renameHelper: 'Yeni bir VM adı girin. Yeniden adlandırmadan önce VM kapatılmalıdır.', + renameConfirm: '[{0}] sanal makinesini [{1}] olarak yeniden adlandırmak istiyor musunuz?', + renameRunningHelper: 'Yeniden adlandırmadan önce sanal makineyi kapatın.', + cpuUsage: 'CPU kullanımı', + memoryUsage: 'Bellek kullanımı', + diskIO: 'Disk G/Ç', + networkIO: 'Ağ G/Ç', + diskReadWrite: 'Disk okuma / yazma', + networkRxTx: 'Ağ RX / TX', rx: 'RX', tx: 'TX', console: 'Konsol', @@ -6447,16 +6880,18 @@ const message = { consoleConnectFailed: 'VNC konsoluna bağlanılamadı. Konsol proxy hizmetini kontrol edin.', consoleCredentialsRequired: 'VNC konsolu kimlik bilgileri gerektiriyor. Backend proxy yapılandırmasını kontrol edin.', - snapshot: 'Snapshot', - createSnapshot: 'Create Snapshot', - recoverSnapshot: 'Recover Snapshot', + snapshot: 'Anlık görüntü', + createSnapshot: 'Anlık görüntü oluştur', + recoverSnapshot: 'Anlık görüntüyü geri yükle', snapshotSize: 'Kullanım', - currentSnapshot: 'Current', - snapshotEmpty: 'No snapshots', + currentSnapshot: 'Geçerli', + snapshotEmpty: 'Anlık görüntü yok', snapshotHelper: - 'A snapshot saves the current VM state as a restore point. Subsequent data changes are recorded in a delta file without changing the original disk. Restoring a snapshot returns the VM to that point in time.', + 'Anlık görüntü, geçerli VM durumunu geri yükleme noktası olarak kaydeder. Sonraki veri değişiklikleri özgün diski değiştirmeden bir fark dosyasına kaydedilir. Anlık görüntünün geri yüklenmesi VM’yi bu duruma döndürür.', + snapshotOperationHelper: + 'Geçerli anlık görüntü silinemez. Anlık görüntüler yalnızca sanal makine kapalıyken geri yüklenebilir.', snapshotRecoverConfirm: - 'Recover virtual machine [{1}] to snapshot [{0}]? The VM disk will be restored to the snapshot state.', + '[{1}] sanal makinesini [{0}] anlık görüntüsüne geri yüklemek istiyor musunuz? VM diski anlık görüntü durumuna döndürülecektir.', interface: 'Ağ Arayüzü', device: 'Aygıt', path: 'Yol', @@ -6485,12 +6920,12 @@ const message = { dir: 'Yerel Dizin', }, cluster: { - cluster: 'Высокая доступность приложений', - name: 'Имя кластера', - addCluster: 'Добавить кластер', - installNode: 'Установить узел', - master: 'Главный узел', - slave: 'Подчиненный узел', + cluster: 'Uygulama yüksek kullanılabilirliği', + name: 'Küme adı', + addCluster: 'Küme ekle', + installNode: 'Düğüm kur', + master: 'Ana düğüm', + slave: 'İkincil düğüm', replicaStatus: 'Ana-Çalışan Durumu', unhealthyDeleteError: 'Yükleme düğümü durumu anormal, lütfen düğüm listesini kontrol edin ve tekrar deneyin!', diff --git a/frontend/src/lang/modules/zh-Hant.ts b/frontend/src/lang/modules/zh-Hant.ts index 9f1452fae..5caa3ef5c 100644 --- a/frontend/src/lang/modules/zh-Hant.ts +++ b/frontend/src/lang/modules/zh-Hant.ts @@ -14,6 +14,7 @@ const message = { next: '下一步', create: '建立', add: '新增', + select: '選擇', save: '儲存', set: '設定', sync: '同步', @@ -57,6 +58,7 @@ const message = { power: '提交', search: '搜尋', refresh: '重新整理', + reconnect: '重新連線', get: '取得', upgrade: '升級', update: '更新', @@ -118,6 +120,9 @@ const message = { card: '卡片', table: '表格', status: '狀態', + statusSuccess: '成功', + statusFailed: '失敗', + statusWaiting: '等待中...', records: '任務輸出', group: '分組', default: '預設', @@ -162,6 +167,7 @@ const message = { deleteSuccess: '刪除成功', loginSuccess: '登入成功', operationSuccess: '操作成功', + operationFailed: '操作失敗', copySuccess: '複製成功', notSupportOperation: '不支援此操作', requestTimeout: '請求逾時,請稍後重試', @@ -203,6 +209,7 @@ const message = { username: '使用者名稱', password: '密碼', passkey: '通行金鑰登入', + otherLoginMethods: '其他方式登入', welcome: '歡迎回來,請輸入帳號密碼', errorAuthInfo: '您輸入的使用者名稱或密碼不正確,請重新輸入', errorMfaInfo: '錯誤的驗證資訊,請重試', @@ -271,8 +278,10 @@ const message = { length128Err: '長度不能超過128位', maxLength: '長度不能超過 {0} 位', alias: '支援英文、數字、-和_,長度1-128,並且不能以-、_開頭或結尾', + vmName: '支援英文字母、數字、「.」、「-」和「_」;長度為 1-64;必須以字母或數字開頭。', + vmNetwork: '支援英文字母、數字、「.」、「:」、「-」和「_」;長度為 1-64;必須以字母或數字開頭。', duplicate: '不能重複', - selectHelper: '請選擇', + selectHelper: '請選擇正確的 {0} 檔案', ipErr: '請輸入正確的 IP 位址', }, res: { @@ -382,6 +391,7 @@ const message = { ssh: 'SSH 設定', firewall: '防火牆', ssl: '憑證', + security: '安全', database: '資料庫', aiTools: 'AI', mcp: 'MCP', @@ -490,6 +500,7 @@ const message = { deleteBackupHelper: '同時刪除資料庫備份', delete: '刪除操作無法回滾,請輸入 "', deleteHelper: '" 刪除此資料庫', + deleteUserHelper: '" 刪除此使用者', userBoundDatabases: '使用者已取得以下資料庫的存取授權:', noMysql: '資料庫服務 (MySQL 或 MariaDB)', noPostgresql: '資料庫服務 PostgreSQL', @@ -535,6 +546,7 @@ const message = { revokeAuthorizationHelper: '確定撤銷使用者 {0} 對資料庫 {1} 的存取授權嗎?', supplementPassword: '補充密碼', supplementPasswordHelper: '僅將現有密碼儲存到 1Panel,不會修改 MySQL 使用者密碼。', + noUserBind: '未綁定', pgBindHelper: '此操作用於建立新使用者並將其綁定到目標資料庫,暫不支援選擇已存在於資料庫中的使用者。', pgSuperUser: '超級使用者', loadFromRemoteHelper: '此操作將同步伺服器上的資料庫、使用者及授權資訊到 1Panel,是否繼續?', @@ -941,9 +953,6 @@ const message = { failureCount: '失敗次數', lastError: '最近錯誤', modelMap: '模型映射', - apiKeyKeepEmpty: 'API Key(留空不改)', - apiKeyOnceHint: 'API Key 僅建立時顯示一次,請及時複製保存。', - apiKeyOnceSave: 'API Key 只顯示一次,請立即保存:', qpsLimit: 'QPS 限制', tokenLimit: 'Token 限制', tokenUsed: '已用 Token', @@ -1475,6 +1484,7 @@ const message = { lastHour: '最近 1 小時', last10Min: '最近 10 分鐘', cleanLog: '清空日誌', + cleanLogscope: '清理類型', downLogHelper1: '即將下載 {0} 容器所有日誌,是否繼續?', downLogHelper2: '即將下載 {0} 容器最近 {1} 條日誌,是否繼續?', cleanLogHelper: '清空日誌需要重新啟動容器,該操作無法回滾,是否繼續?', @@ -1700,7 +1710,7 @@ const message = { ifPause: '製作過程中是否暫停容器', ifMakeImageWithContainer: '是否根據此容器製作新映像?', finishTime: '上一次停止時間', - exportHelper: '即將匯出 {0} 條編排範本,是否繼續?', + exportHelper: '將選取的映像匯出為一個 tar 檔案。', }, cronjob: { importHelper: @@ -1728,6 +1738,9 @@ const message = { website: '備份網站', rulesHelper: '支援多個排除規則,使用英文逗號 , 分隔,例:*.log,*.sql', lastRecordTime: '上次執行情況', + all: '全部', + failedRecord: '失敗記錄', + successRecord: '成功記錄', database: '備份資料庫', backupArgs: '備份參數', backupArgsHelper: '未列出的備份參數可手動輸入並選擇,例:輸入 --no-data 後選擇下拉列表中的第一個選項', @@ -1916,6 +1929,7 @@ const message = { fold: '全部收縮', batchInput: '批次輸入', quickCommand: '快速指令', + quickCmd: '快速指令', noSuchCommand: '匯入的CSV檔案中未能發現快速指令資料,請檢查後重試', quickCommandHelper: '常用命令列表,用於在終端介面底部快速選擇', groupDeleteHelper: '移除組後,組內所有連接將遷移到 default 組內,是否繼續?', @@ -2152,13 +2166,10 @@ const message = { taskRunning: '執行中', }, file: { + name: '名稱', fileDirNum: '共 {0} 個目錄,{1} 個檔案,', currentDir: '當前目錄', dir: '資料夾', - upload: '上傳', - download: '下載', - uploadFile: '@:file.upload@:file.file', - uploadDirectory: '@:file.upload@:file.dir', fileName: '檔案名', search: '在當前目錄下尋找', mode: '權限', @@ -2622,6 +2633,17 @@ const message = { restartLater: '稍後手動重新啟動', systemIPWarning: '當前節點尚未設定預設存取地址,請前往面板設定進行設定', systemIPWarning1: '當前伺服器地址為 {0},無法快速跳轉', + syncTime: '伺服器時間', + timeZone: '時區', + timeZoneChangeHelper: '修改時區需要重新啟動服務,是否繼續?', + timeZoneHelper: '時區修改依賴系統 timedatectl 服務,重新啟動 1Panel 服務後生效。', + timeZoneCN: '北京', + timeZoneAM: '洛杉磯', + timeZoneNY: '紐約', + ntpALi: '阿里雲', + ntpGoogle: 'Google', + syncSite: 'NTP 伺服器', + syncSiteHelper: '該操作將使用 {0} 作為來源同步系統時間,是否繼續?', changePassword: '密碼修改', oldPassword: '原密碼', newPassword: '新密碼', @@ -2954,6 +2976,7 @@ const message = { lostHelper: '許可證已達到最大重試次數,請手動點選同步按鈕,以確保商業版功能正常使用,詳情:', exceptionalHelper: '許可證同步驗證異常,請手動點選同步按鈕,以確保商業版功能正常使用,詳情:', quickUpdate: '快速更新', + import: '匯入', power: '授權', unbindHelper: '解除綁定後將清除該節點所有商業版相關設定,是否繼續?', importLicense: '匯入許可證', @@ -3075,6 +3098,10 @@ const message = { backupdate: '備份時間', versionSelect: '請選擇版本', operatorHelper: '將對選中應用進行 {0} 操作,是否繼續?', + startOperatorHelper: '即將啟動應用,是否繼續?', + stopOperatorHelper: '即將停止應用,是否繼續?', + restartOperatorHelper: '即將重新啟動應用,是否繼續?', + reloadOperatorHelper: '即將重新載入應用,是否繼續?', checkInstalledWarn: '未偵測到 {0} ,請進入應用商店點選安裝', limitHelper: '該應用已安裝,不支援重複安裝', deleteHelper: '{0}已經關聯以下資源,請檢查後重試', @@ -3484,9 +3511,9 @@ const message = { staticChangePHPHelper: '目前為靜態網站,可切換為 PHP 網站', proxyCache: '反向代理快取', cacheLimit: '快取空間限制', - shareCahe: '快取計數記憶體大小', + shareCache: '快取計數記憶體大小', cacheExpire: '快取過期時間', - shareCaheHelper: '每1M記憶體可以儲存約8000個快取物件', + shareCacheHelper: '每1M記憶體可以儲存約8000個快取物件', cacheLimitHelper: '超過限制會自動刪除舊的快取', cacheExpireJHelper: '超出時間快取未命中將會被刪除', realIP: '真實 IP', @@ -3740,6 +3767,7 @@ const message = { portFormatError: '請輸入正確的埠資訊', portHelper1: '多個埠,如:8080,8081', portHelper2: '範圍埠,如:8080-8089', + changeStrategyHelper: '即將把 [{1}] 的 {0} 策略修改為 [{2}],設定後 {0} 將依 [{2}] 策略對外存取,是否繼續?', strategy: '策略', accept: '允許', drop: '拒絕', @@ -3803,6 +3831,7 @@ const message = { }, runtime: { runtime: '執行環境', + default: '預設', workDir: '工作目錄', localHelper: '本機環境安裝及離線環境使用相關問題,可參考 ', versionHelper: 'PHP的版本,例 v8.0', @@ -4023,7 +4052,6 @@ const message = { }, expiresEnterpriseAlert: '溫馨提醒:您的企業版許可證將在 {0} 天後到期,屆時所有企業版功能將無法繼續使用。', expiresProAlert: '溫馨提醒:您的專業版許可證將在 {0} 天後到期,屆時所有專業版功能將無法繼續使用。', - name: '商業版', menu: '進階功能', upage: 'AI 建站', proAlert: '升級商業版以使用此功能', @@ -4130,7 +4158,6 @@ const message = { panelLogin: '面板登入', sshLogin: 'SSH 登入', failedRecord: '失敗記錄', - successRecord: '成功記錄', expired: '已到期', expiredDays: '已過期 {0} 天', remainingDays: '{0} · 剩餘 {1} 天', @@ -4569,6 +4596,14 @@ const message = { authManage: '認證管理', auth: { providerNavigation: '認證類型', + defaultNode: '預設節點', + defaultNodePlaceholder: '請選擇節點', + defaultNodeHelper: '僅用於新使用者。', + defaultNodeRequired: '請選擇有效的預設節點。', + nodesLoadFailed: '節點清單載入失敗,請重試後再選擇預設節點。', + nodeHandling: '節點處理', + assignDefaultNode: '分配預設節點:{node}', + keepExistingNode: '保留已有節點權限', providers: { ldap: 'AD/LDAP', passkey: 'Passkey', @@ -4596,7 +4631,348 @@ const message = { planned: '待接入', plannedTitle: '{0} 認證設定', plannedDesc: '該認證方式正在規劃中,暫不可用。', + oidc: { + accessMode: '存取方式', + accessModeDesc: '身分提供者支援 Discovery 時優先使用標準模式。', + actionCreate: '建立使用者', + actionKeepName: '保留目前名稱', + actionPending: '等待結果', + actionReject: '拒絕登入', + actionUpdate: '更新身分資訊', + advanced: '進階設定', + advancedDesc: '預設值適用於標準 Provider;只有不相容時才調整。', + assignDefaultRole: '指派預設角色:{role}', + authorizationEndpoint: '授權端點', + authorizationEndpointInvalid: '請輸入有效的授權端點位址。', + authorizationFlow: '授權流程', + automatic: '自動', + automaticPolicy: '自動處理策略', + automaticPolicyDesc: '以下規則由後端固定執行,不作為管理員開關。', + basic: '基礎設定', + basicDesc: '先選擇 Provider 模式,再設定客戶端和回呼位址。', + browserTest: '瀏覽器測試登入', + browserTestConflict: '身分驗證成功,但使用者名稱衝突', + browserTestConflictHelper: '對映名稱屬於其他身分,不會自動認領。', + browserTestExpired: '瀏覽器測試已過期', + browserTestExpiredHelper: '請重新開始測試,並在有效期限內完成授權。', + browserTestFailed: '瀏覽器測試失敗', + browserTestFailedHelper: '無法完成身分預覽,請檢視後端傳回的在地化錯誤。', + browserTestIsolation: '執行真實授權往返,但不會建立或更新使用者、指派角色或產生正式 Session。', + browserTestPopupBlocked: '請允許目前站點開啟彈跳窗,然後重新測試。', + browserTestPopupClosed: '授權視窗在測試完成前被關閉。', + browserTestSuccess: 'Provider 驗證成功', + browserTestSuccessHelper: '已完成身分對映預覽,沒有修改使用者或 Session。', + browserTestTitle: 'OIDC 瀏覽器測試登入', + browserTestWaiting: '等待 Provider 授權', + browserTestWaitingHelper: '請在新視窗完成登入,本頁面會自動更新。', + callbackCopied: 'OIDC 回呼位址已複製。', + callbackURL: '回呼位址', + callbackURLHelper: '請將此位址加入身分提供方客戶端的允許回呼清單。', + cancelClearSecret: '取消清除', + clearSecret: '清除金鑰', + clearSecretConfirm: '客戶端金鑰只會在儲存後刪除,是否繼續?', + clientAuthMethod: '客戶端認證方式', + clientAuthMethodHelper: '請選擇身分提供方為該客戶端設定的認證方式。', + clientAuthMethodRequired: '請選擇客戶端認證方式。', + clientID: '客戶端 ID', + clientIDRequired: '請輸入客戶端 ID。', + clientSecret: '客戶端金鑰', + clockSkew: '權杖時間偏差', + clockSkewHelper: '允許身分提供者與面板存在少量時間偏差,建議保持 60 秒。', + clockSkewRequired: '請輸入權杖時間偏差。', + compatibilityMode: '相容模式', + compatibilityModeHelper: '僅用於 Discovery 不完整或端點被改寫的 Provider,核心 OIDC 驗證不會關閉。', + configurationFailedHelper: '測試失敗,頁面只顯示後端在地化錯誤。', + configurationFailedTag: '測試失敗', + configurationHighRiskPassed: '設定測試通過,但包含高風險相容項。', + configurationHighRiskTag: '高風險設定通過', + configurationNotTested: '目前設定尚未測試。', + configurationNotTestedTag: '尚未測試', + configurationPassed: '目前設定已通過安全性和能力檢查。', + configurationPassedTag: '測試通過', + configurationStaleHelper: '設定已修改,請重新測試後儲存。', + configurationStaleTag: '結果已過期', + configurationTestMeta: '測試時間 {time},耗時 {duration} ms;不儲存 Provider 原始回應。', + configurationTestResult: '設定測試結果', + configurationTestResultDesc: + '此處只檢查自動發現結果與身分提供方能力,不交換授權碼,也無法證明客戶端金鑰正確;請使用「瀏覽器測試登入」完成端對端驗證。', + configurationTestSuccess: 'OIDC 設定測試成功。', + configurationTesting: '正在測試目前 OIDC 設定…', + configurationTestingTag: '正在測試', + configureSecret: '設定金鑰', + conflictExistingRename: '已有 subject 回傳的新 name 已被佔用', + conflictExistingRenameResult: '保留原 User.Name,並允許已繫結使用者繼續登入', + conflictLDAP: 'LDAP 使用者', + conflictLocal: '本機使用者', + conflictNewAvailable: '新 subject,對映後的 name 未佔用', + conflictNewAvailableResult: '建立本機企業使用者並指派預設角色', + conflictNone: '無衝突', + conflictOIDC: '其他 OIDC 身分', + conflictOccupied: '對映 name 已被本機、LDAP 或其他 OIDC 身分佔用', + conflictOccupiedResult: '拒絕新身分,不自動繫結或合併', + conflictType: '衝突型別', + connectionSecurity: '連線安全', + connectionSecurityDesc: '預設驗證憑證,私有 IdP 位址由系統自動識別。', + connectionTest: '連線與設定測試', + connectionTestCompatibilityDesc: '驗證自訂端點和協定安全性策略。', + connectionTestStandardDesc: '根據簽發者位址自動發現端點和能力。', + connectionTestTab: '連線測試', + customCA: '自訂 CA', + customCAHelper: '僅作用於目前認證來源,且不會寫入日誌。', + customCARequired: '請提供自訂 CA 憑證。', + defaultRole: '預設角色', + defaultRoleHelper: '僅首次建立使用者時指派,後續登入不修改角色。', + defaultRolePlaceholder: '請選擇角色', + defaultRoleRequired: '請選擇有效的預設角色。', + disableAfterSave: '儲存後將停用 OIDC。', + disableConfirm: '停用 OIDC 會立即使該認證來源使用者的存取失效,是否繼續?', + disableDiscardConfirm: + '停用 OIDC 屬於故障兜底操作:只關閉登入入口,並立即使此認證來源使用者的存取失效。本頁其他未儲存修改(包括客戶端金鑰修改)將被丟棄。是否繼續?', + disableTitle: '停用 OIDC', + disabled: '未啟用', + discoveryAllowlist: 'Discovery ∩ 安全白名單', + enable: '是否啟用', + enableAfterSave: '儲存成功後啟用 OIDC。', + enabled: '已啟用', + endSessionEndpoint: '會話登出端點', + endSessionEndpointHelper: '首期只儲存,不執行身分提供方發起的單點登出。', + endSessionEndpointInvalid: '請輸入有效的會話登出端點位址。', + endpointDiscoveryPlaceholder: '測試連線後顯示', + firstLogin: '首次登入', + firstLoginPolicy: '建立本機企業使用者,並指派設定的預設角色。', + fixedAuthorizationCode: 'Authorization Code Flow', + fixedNoTokenPersistence: '不持久化 Token、Claims 和 verifier', + fixedSecurityPolicy: '系統固定執行,無需設定', + fixedStateNonce: '一次性 state 與 nonce', + fixedTokenValidation: 'ID Token 簽章與 Claims 驗證', + highRiskSaveConfirm: '目前啟用設定包含高風險相容項,請確認隔離環境確實需要這些設定。', + highRiskTitle: '高風險 OIDC 設定', + hs256Compatibility: 'HS256(相容模式)', + hs256KeyHelper: 'HS256 固定使用目前認證來源的客戶端金鑰,不接受另一份簽章金鑰。', + hs256Warning: 'HS256 使用共享對稱金鑰驗證 ID Token;僅在 Provider 無法使用非對稱演算法時啟用。', + identityBindingPolicy: '身分主鍵固定為 AuthSourceID + issuer + subject,同名不會認領其他帳號。', + identityMissing: '身分已失效', + issuer: '簽發者位址', + issuerHelper: '用於 OIDC 自動發現,回傳的 issuer 必須與該位址一致。', + issuerInvalid: '請輸入不含查詢參數和片段的有效 HTTP 或 HTTPS 簽發者位址。', + issuerRequired: '請輸入簽發者位址。', + jwksRotation: 'JWKS 自動輪替', + jwksURI: 'JWKS 位址', + jwksURIHelper: '使用非對稱簽章且金鑰來源為 JWKS 時必填。', + jwksURIInvalid: '請為目前簽章金鑰來源填寫有效的 JWKS 位址。', + keepExistingRole: '保留已有角色和本機權限', + localSecurityData: '本機安全資料', + localSecurityDataPolicy: '不覆寫角色、MFA、API Key、Passkey 和本機權限。', + localCredentialsManaged: + '使用者名稱和本機密碼由 OIDC 身分管理,無法在此修改;角色、權限、MFA、API Key 與 Passkey 仍由本機管理。', + localUserFields: '本機使用者欄位', + localUserFieldsDesc: '首期只對映 User.Name,不使用 JSON 對映表示式。', + loginWith: '使用 {provider} 登入', + manualEndpoints: '自訂端點', + manualEndpointsDesc: '僅用於自動發現不完整或上游閘道改寫端點的身分提供方。', + mappingResult: '對映結果', + mode: '接入模式', + modeRequired: '請選擇接入模式。', + nameClaim: '使用者名稱 Claim', + nameClaimHelper: '填寫身分提供方傳回使用者名稱的欄位,如 preferred_username。', + nameClaimRequired: '請輸入使用者名稱 Claim。', + nameConflict: '同名衝突策略', + panelURL: '面板對外位址', + panelURLHTTPWarning: 'HTTP 不保護授權回應,僅用於 Provider 接受的隔離私有環境。', + panelURLHelper: '填寫使用者實際存取面板的位址,用於產生回呼位址。', + panelURLInvalid: '請輸入只包含協定、主機和選用連線埠的對外位址。', + panelURLRequired: '請輸入面板對外位址。', + pkceDisabled: '不使用 PKCE(僅相容模式)', + pkceDisabledWarning: '關閉 PKCE 會降低授權碼流程的抗截獲能力。', + pkceHelper: '優先使用 S256,永不提供 plain。', + pkceS256: 'S256(建議)', + plannedHandling: '預計處理', + privateNetworkIdP: '私有網路 IdP', + privateNetworkIdPHelper: + '明確允許私有位址;元資料、迴路、連結本機、異常重新導向和 DNS 重新繫結仍會阻止。', + privateNetworkWarning: '目前認證來源已允許存取私有網路。', + protocolCompatibility: '協定相容', + protocolCompatibilityDesc: 'ID Token 簽章驗證始終無法關閉。', + providerAndClient: '身分提供方與客戶端', + providerAndClientDesc: '客戶端金鑰只允許替換或清除,頁面不會回顯。', + providerCapabilities: 'Provider 能力', + recentTestSuccess: '最近測試成功:{0}', + recommended: '推薦', + rejectPlain: '拒絕 plain', + replaceSecret: '更換金鑰', + requestAndClaims: '請求與屬性', + requestAndClaimsDesc: '設定授權範圍、使用者資訊補充和請求參數。', + requestTimeout: '請求逾時', + requestTimeoutRequired: '請輸入請求逾時時間。', + restore: '還原', + restored: '已還原到上次儲存的 OIDC 設定。', + result: '處理結果', + rolesLoadFailed: '角色清單載入失敗,請重試後再選擇預設角色。', + roleHandling: '角色處理', + scenario: '場景', + scopes: '授權範圍', + scopesHelper: '必須包含 openid,多個範圍請使用空格分隔。', + scopesRequired: 'Scopes 必須包含 openid。', + seconds: '秒', + secretClearHelper: '清除後,重新啟用 OIDC 前必須設定新的客戶端金鑰。', + secretConfigured: '已設定', + secretNotConfigured: '未設定', + secretPlaceholder: '輸入新的客戶端金鑰', + secretReplaceHelper: '新金鑰會在儲存時取代原值,請同步更新身分提供方中的客戶端金鑰。', + secretRequiredHelper: '啟用 OIDC 前需要設定客戶端金鑰。', + secretRequiredToEnable: '請先設定客戶端金鑰,再啟用 OIDC。', + secretSavedHelper: '已加密儲存,留空則繼續使用目前金鑰。', + secretWaiting: '等待輸入', + secretWillClear: '儲存後清除', + secretWillReplace: '待替換', + signingAlgorithm: 'ID Token 簽章演算法', + signingAlgorithmHelper: '只能選擇後端安全白名單中的演算法。', + signingKey: '簽章金鑰', + signingKeyClientSecret: '客戶端金鑰(僅 HS256)', + signingKeyJWKS: 'JWKS URI 自動取得與輪替', + signingKeySource: '簽章金鑰來源', + signingKeySourceHelper: '優先使用 JWKS;靜態公鑰無法自動輪替。', + signingKeyStatic: '靜態 JWK 或 PEM 公鑰', + standardDiscovery: '標準模式(自動發現)', + standardDiscoveryDesc: '面板自動發現端點和能力,不儲存自動發現原文。', + standardMode: '標準模式', + standardModeHelper: '根據 Issuer 自動發現端點、簽章能力和 PKCE 支援。', + standardProtocolPolicy: '標準協定策略', + standardProtocolPolicyDesc: '自動協商簽章能力,不需要填寫簽章演算法和金鑰。', + staticSigningKey: '靜態簽章公鑰', + staticSigningKeyHelper: '只接受公鑰材料;Provider 換 Key 後需要手動更新。', + staticSigningKeyPlaceholder: '貼上 JWK、JWKS JSON 或 PEM 公鑰', + staticSigningKeyRequired: '請提供靜態簽章公鑰。', + staticSigningKeyWarning: '靜態簽章公鑰無法自動輪替;Provider 換 Key 前必須手動更新。', + settingLoadFailed: 'OIDC 設定載入失敗', + settingLoadFailedHelper: '為避免以空白預設值覆寫已有設定,目前表單已鎖定。請在連線恢復後重試。', + subsequentLogin: '後續登入', + subsequentLoginPolicy: '按 subject 找到繫結,僅在新名稱可用時更新 User.Name。', + testBeforeBrowserTest: '請先測試目前設定,再進行瀏覽器測試登入。', + testBeforeEnable: '儲存設定變更前,請先測試目前設定。', + testConfiguration: '測試設定', + testDiscovery: '測試連線', + tlsCustomCA: 'HTTPS · 自訂 CA 憑證', + tlsPrivateHTTP: 'HTTP · 僅私人網路(危險)', + tlsPrivateHTTPWarning: 'HTTP 不提供傳輸加密,只允許明確放行的私有目標。', + tlsSkipVerify: '略過 TLS 憑證驗證', + tlsSystem: 'HTTPS · 系統憑證驗證(建議)', + tokenEndpoint: '權杖端點', + tokenEndpointInvalid: '請輸入有效的權杖端點位址。', + transportSecurity: '傳輸安全', + transportSecurityHelper: '優先使用 HTTPS;私有 HTTP 還需要明確允許私有網路。', + unsavedChanges: 'OIDC 設定有尚未儲存的變更。', + usedClaim: '使用 Claim', + userInfoEndpoint: '使用者資訊端點', + userInfoEndpointHelper: '使用者名稱欄位缺少時,系統將從此端點補充;留空則不補充。', + userInfoEndpointInvalid: '請輸入有效的使用者資訊端點位址。', + userMapping: '使用者設定', + userMappingDesc: '設定 OIDC 使用者名稱映射,以及首次登入建立使用者時使用的預設節點和角色。', + }, + saml2: { + actionCreate: '建立使用者', + actionPending: '等待結果', + actionReject: '拒絕登入', + actionReuse: '使用已綁定使用者', + assignDefaultRole: '分配新使用者角色:{role}', + basic: '基礎設定', + basicDesc: '設定大多數標準 SAML2 身分提供者所需的常用選項。', + browserTest: '測試登入', + browserTestConflict: '身分驗證成功,但使用者名稱衝突', + browserTestConflictHelper: '映射後的使用者名稱屬於其他身分,不會自動關聯。', + browserTestExpired: '瀏覽器測試已過期', + browserTestExpiredHelper: '請重新開始測試,並在有效期內完成登入。', + browserTestFailed: '瀏覽器測試失敗', + browserTestFailedHelper: '無法完成身分預覽,請查看後端傳回的本地化錯誤。', + browserTestIsolation: '執行真實 SAML2 往返,但不會建立使用者、分配角色或產生正式工作階段。', + browserTestPopupBlocked: '請允許目前網站開啟彈出視窗,然後重新測試。', + browserTestPopupClosed: '登入視窗在測試完成前已關閉。', + browserTestSuccess: 'SAML2 身分驗證成功', + browserTestSuccessHelper: '身分映射預覽已完成,沒有修改使用者或工作階段。', + browserTestTitle: 'SAML2 測試登入', + browserTestWaiting: '等待 IdP 登入', + browserTestWaitingHelper: '請在新視窗完成登入,本頁會自動更新。', + certificateFileInvalid: '請選擇有效的 PEM、CRT 或 CER 憑證檔案。', + configured: '已設定', + configurationFailedHelper: '測試失敗,頁面只顯示後端本地化錯誤。', + configurationNotTested: '目前設定尚未測試。', + configurationPassed: '目前設定已通過驗證。', + configurationStaleHelper: '影響驗證的設定已修改,請重新測試目前草稿。', + configurationTestSuccess: 'SAML2 設定測試成功。', + configurationTesting: '正在測試目前 SAML2 設定…', + conflictLDAP: 'LDAP 使用者', + conflictLocal: '本機使用者', + conflictNone: '無衝突', + conflictOIDC: 'OIDC 身分', + conflictSAML2: '其他 SAML2 身分', + conflictType: '衝突類型', + credentialFileReadFailed: '無法讀取憑證檔案。', + credentialFileTooLarge: '憑證檔案不能超過 256 KiB。', + credentialsRequired: '請同時設定 SP 私鑰和 SP 憑證。', + defaultRole: '新使用者角色', + defaultRoleHelper: '僅在首次建立時設定;後續登入保留本機角色、MFA 和權限。', + defaultRolePlaceholder: '請選擇角色', + defaultRoleRequired: '請選擇有效的新使用者角色。', + disableConfirm: '停用 SAML2 會立即拒絕新登入並使其使用者工作階段失效,是否繼續?', + disableDiscardConfirm: + '停用 SAML2 會捨棄本頁其他未儲存修改,並立即使其使用者工作階段失效,是否繼續?', + disableTitle: '停用 SAML2', + disabled: '未啟用', + enable: '是否啟用', + enabled: '已啟用', + idpMetadata: 'IdP 元資料', + idpMetadataDesc: '填寫 URL 或貼上 XML,擇一即可;同時填寫時優先讀取 URL。', + keepExistingRole: '保留現有角色和本機權限', + loginWith: '使用 {provider} 登入', + mappingResult: '映射結果', + metadataRequired: '請填寫 IdP 元資料 URL 或 XML。', + metadataURLHelper: '測試和儲存時由後端讀取並驗證元資料。', + metadataURLInvalid: '請輸入不含憑證和片段的有效 HTTPS 元資料 URL。', + metadataURLRecommended: '元資料 URL(建議)', + metadataXML: '元資料 XML', + metadataXMLHelper: '適用於身分提供者(IdP)沒有可存取的元資料 URL 的情況。', + metadataXMLInvalid: '請輸入包含有效 EntityDescriptor 的元資料 XML。', + metadataXMLPlaceholder: '貼上 ...', + nameAttribute: '使用者名稱屬性', + nameAttributeHelper: '從已驗證的 SAML 斷言中讀取該屬性,並映射為面板使用者名稱。', + nameAttributePlaceholder: '例如 uid、username 或 account', + nameAttributeRequired: '請填寫使用者名稱屬性。', + notConfigured: '未設定', + or: '或', + pageDesc: '透過 IdP 元資料接入企業單一登入,常用設定可在一頁完成。', + plannedHandling: '預計處理', + privateKeyFileInvalid: '請選擇有效的 PEM 私鑰檔案。', + recentTestSuccess: '最近測試成功:{0}', + restore: '還原', + restored: '已還原至上次儲存的 SAML2 設定。', + roleHandling: '角色處理', + rolesLoadFailed: '角色清單載入失敗,請重試後再選擇新使用者角色。', + selectFile: '選擇檔案', + serviceStatus: '服務狀態', + serviceStatusDesc: '首次啟用前需要先通過目前設定測試。', + settingLoadFailed: 'SAML2 設定載入失敗', + settingLoadFailedHelper: '為避免以空白預設值覆寫現有設定,目前表單已鎖定。請在連線恢復後重試。', + spCertificate: 'SP 憑證', + spCertificateHelper: '透過 SP 元資料提供給身分提供者(IdP),用於驗證登入和登出請求。', + spCredentials: 'SP 私鑰與憑證', + spCredentialsDesc: '用於簽署登入和登出訊息;簽署與安全驗證策略由後端固定處理。', + spPrivateKey: 'SP 私鑰', + spPrivateKeyHelper: '用於簽署 SAML 登入請求和登出訊息,加密儲存且不會回顯。', + syncLogout: '同步登出', + syncLogoutHelper: '從面板或身分提供者任一方登出時,也會同步登出另一方。', + testBeforeBrowserTest: '請先測試目前設定,再執行瀏覽器測試登入。', + testBeforeEnable: '啟用 SAML2 或儲存驗證敏感變更前,請先測試目前設定。', + testConfiguration: '測試設定', + unsavedChanges: 'SAML2 設定有未儲存的變更。', + usedAttribute: '使用者名稱映射', + usersAndRoles: '使用者與角色', + usersAndRolesDesc: '設定面板使用者名稱映射,以及首次登入建立使用者時使用的預設節點和角色。', + }, ldap: { + basic: '基礎設定', + loginTitle: 'LDAP 登入', + loginWith: '使用 LDAP 登入', + backToLocalLogin: '返回面板登入', enable: '是否啟用', enabled: '已啟用', disabled: '未啟用', @@ -4610,13 +4986,13 @@ const message = { bindPassword: '密碼', passwordSaved: '留空則保留已儲存的密碼', userSearch: '使用者搜尋', - userSearchDesc: '設定使用者搜尋基準與過濾器,並映射到 1Panel 使用者名稱欄位。', + userSearchDesc: '設定使用者搜尋基準與過濾器,並映射到面板使用者名稱欄位。', userFilter: '使用者篩選器', userFilterTooltip: '按使用者名稱查詢時替換 %(user)s,全量讀取時替換為 *。', userFilterHelper: '搜尋和認證時會對使用者名稱執行 LDAP filter escaping。', attributeMap: '映射屬性', - attributeMapTooltip: '1Panel 使用者名稱欄位(name)到 LDAP 屬性的 JSON 映射。', - attributeMapHelper: '填寫映射到 1Panel 使用者名稱欄位(name)的 LDAP 屬性。', + attributeMapTooltip: '面板使用者名稱欄位(name)到 LDAP 屬性的 JSON 映射。', + attributeMapHelper: '填寫映射到面板使用者名稱欄位(name)的 LDAP 屬性。', advanced: '進階設定', advancedDesc: '設定 TLS 和 LDAP 查詢分頁。', strictSync: '嚴格同步', @@ -4654,7 +5030,7 @@ const message = { searchPageSizeRequired: '請輸入 LDAP 查詢分頁大小。', sync: { title: '定時同步', - description: '定期讀取 LDAP 全量使用者,並維護 1Panel 中的 LDAP 使用者。', + description: '定期讀取 LDAP 全量使用者,並維護面板中的 LDAP 使用者。', enable: '是否啟用', enableHelper: '關閉後不再自動執行,仍可手動立即同步。', schedule: '執行週期', @@ -4712,8 +5088,7 @@ const message = { action: '處理動作', }, testLoginTitle: '測試 AD/LDAP 登入', - testLoginDesc: - '使用 AD/LDAP 使用者憑證執行 bind 驗證,僅測試認證能力,不建立 1Panel 登入工作階段。', + testLoginDesc: '使用 AD/LDAP 使用者憑證執行 bind 驗證,僅測試認證能力,不建立面板登入工作階段。', ldapUsername: 'LDAP 使用者名稱', usernameRequired: '請輸入 LDAP 使用者名稱。', startTest: '開始測試', @@ -4791,6 +5166,7 @@ const message = { deleteConfirm: '確認刪除此匯出記錄及檔案?', }, waf: { + WAF: 'WAF', name: 'WAF', blackWhite: '黑白名單', globalSetting: '全域設定', @@ -5145,7 +5521,6 @@ const message = { duckduckgo: 'DuckDuckGo', yandex: 'Yandex', gptbot: 'GPTBot', - exceptUri: '排除 Uri', top100Helper: '顯示 Top 100 的資料', logSaveDay: '日誌儲存天數', cros: 'Chrome OS', @@ -5349,6 +5724,12 @@ const message = { nodeUpgradePackageHostConfirm: '即將選擇伺服器檔案:{0},是否繼續?', nodeUpgradePackageCleanHelper: '即將清理所有低版本升級包,是否繼續?', nodeUpgradeOfflinePackageHelper: '離線環境中,異構節點需先上傳對應更新包後再更新。', + healthCheck: '健康檢查', + healthCheckFrequency: '檢查頻率', + healthCheckFrequencyHelper: '定期檢查後端節點健康狀態,輸入 0 可停用檢查。', + healthCheckFrequencyLimit: '檢查頻率不能超過一天,且必須為非負整數。', + loadFailedNodeResources: '載入失敗節點資源', + loadFailedNodeResourcesHelper: '開啟節點列表時,同時載入失敗節點的資源資訊。', nodeUnhealthy: '節點狀態異常', deletedNode: '已刪除節點 {0} 暫不支援升級操作', nodeUnhealthyHelper: '偵測到該節點狀態異常,請在 [節點管理] 中檢查後重試', @@ -5428,6 +5809,8 @@ const message = { offlineHelper: '當節點處於離線環境時使用', appUpgrade: '應用程式升級', appUpgradeHelper: '有 {0} 個應用程式需要升級', + dashboardSetting: '概覽設定', + keepOneDashboardComponent: '至少保留一個概覽區塊', }, customApp: { name: '自訂應用倉庫', @@ -5596,7 +5979,7 @@ const message = { alertSmsHelper: '簡訊額度:總量{0}條,已使用{1}條', goBuy: '去購買', phone: '手機號碼', - phoneHelper: '請請填寫真實的手機號碼,以免不能正常接收告警資訊', + phoneHelper: '請填寫真實的手機號碼,以免不能正常接收告警資訊', dailyAlertNum: '每日告警次數', dailyAlertNumHelper: '每日告警通知的總次數,最多通知 100 次', timeRange: '時間範圍', @@ -5926,6 +6309,7 @@ const message = { snapshotEmpty: '暫無快照', snapshotHelper: '快照會將虛擬機目前狀態儲存為還原點,後續資料變更會記錄在差異檔案中,不會影響原始磁碟。還原快照時,虛擬機會回到該時間點狀態。', + snapshotOperationHelper: '目前快照無法刪除;僅能在虛擬機關機時還原快照。', snapshotRecoverConfirm: '確認將虛擬機 [{1}] 恢復到快照 [{0}]?恢復後虛擬機磁碟會回到該快照狀態。', interface: '網路介面', device: '裝置', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index 67b327b08..de862dd98 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -107,19 +107,28 @@ const message = { search: { timeStart: '开始时间', timeEnd: '结束时间', + timeRange: '至', + dateStart: '开始日期', + dateEnd: '结束日期', date: '日期', }, table: { all: '所有', + total: '共 {0} 条', name: '名称', type: '类型', card: '卡片', table: '表格', status: '状态', + statusSuccess: '成功', + statusFailed: '失败', + statusWaiting: '等待中...', + records: '记录', group: '分组', default: '默认', createdAt: '创建时间', creator: '创建人', + publishedAt: '发布时间', date: '时间', updatedAt: '更新时间', updater: '更新人', @@ -130,7 +139,10 @@ const message = { user: '用户', title: '标题', port: '端口', + forward: '转发', protocol: '协议', + tableSetting: '表格设置', + refreshRate: '刷新频率', noRefresh: '不刷新', selectColumn: '选择列', local: '本地', @@ -155,6 +167,7 @@ const message = { deleteSuccess: '删除成功', loginSuccess: '登录成功', operationSuccess: '操作成功', + operationFailed: '操作失败', copySuccess: '复制成功', notSupportOperation: '不支持的当前操作', requestTimeout: '请求超时,请稍后重试', @@ -195,13 +208,17 @@ const message = { login: { username: '用户名', password: '密码', + welcome: '欢迎回来,请使用用户名和密码登录。', errorAuthInfo: '您输入的用户名或密码不正确,请重新输入!', errorMfaInfo: '错误的验证信息,请重试!', captchaHelper: '验证码', errorCaptcha: '验证码错误!', + codeInput: '请输入 6 位 MFA 验证码', mfaTitle: 'MFA 认证', mfaCode: 'MFA 验证码', + title: 'Linux 服务器运维管理面板', passkey: '使用通行密钥', + otherLoginMethods: '其他方式登录', passkeyFailed: '通行密钥登录失败,请重试', passkeyNotSupported: '当前浏览器或环境不支持通行密钥', passkeyToPassword: '无法使用通行密钥? 使用账号密码登录', @@ -231,6 +248,7 @@ const message = { volumeName: '支持英文、数字、.-和_,长度2-30', supervisorName: '支持非特殊字符开头,英文、数字、-和_,长度1-128', complexityPassword: '支持长度为 8-30 位且包含字母、数字、特殊字符中至少两项的密码组合', + commonPassword: '长度必须大于 6 位', linuxName: '长度1-128,名称不能含有{0}等符号', email: '请输入正确的邮箱', number: '请输入正确的数字', @@ -239,8 +257,10 @@ const message = { host: '请输入正确的 IP 或域名', hostHelper: '支持输入 ip 或域名', port: '请输入正确的端口,1-65535', + selectHelper: '请选择正确的 {0} 文件', domain: '域名格式错误', databaseName: '支持英文、数字、_,长度1-30', + ipErr: '请输入正确的 IP 地址', numberRange: '数字范围: {0} - {1}', paramName: '支持英文、数字、.-和_,长度2-64', paramComplexity: '支持英文、数字、{0},长度6-128,特殊字符不能在首尾', @@ -372,6 +392,7 @@ const message = { firewall: '防火墙', filter: '过滤器', ssl: '证书', + security: '安全', database: '数据库', aiTools: 'AI', mcp: 'MCP', @@ -396,6 +417,7 @@ const message = { template: '模板', }, home: { + recommend: '推荐', dir: '目录', alias: '别名', quickDir: '快捷目录', @@ -455,6 +477,7 @@ const message = { shard: '共享', available: '可用', percent: '使用率', + goInstall: '去安装', networkCard: '网卡', disk: '磁盘', @@ -469,10 +492,13 @@ const message = { hide: '收起', closeLeft: '关闭左侧', closeRight: '关闭右侧', + closeCurrent: '关闭当前', closeOther: '关闭其它', closeAll: '关闭所有', }, - header: {}, + header: { + logout: '退出登录', + }, database: { manage: '管理', deleteBackupHelper: '同时删除数据库备份', @@ -1472,6 +1498,7 @@ const message = { lastHour: '最近 1 小时', last10Min: '最近 10 分钟', cleanLog: '清空日志', + cleanLogscope: '清理类型', downLogHelper1: '即将下载 {0} 容器所有日志,是否继续?', downLogHelper2: '即将下载 {0} 容器最近 {1} 条日志,是否继续?', cleanLogHelper: '清空日志需要重启容器,该操作无法回滚,是否继续?', @@ -1648,7 +1675,7 @@ const message = { composeDirectory: '编排目录', template: '模版', composeTemplate: '编排模版', - exportHelper: '即将导出 {0} 条编排模版,是否继续?', + exportHelper: '将选中的镜像导出为一个 tar 文件。', content: '内容', contentEmpty: '编排内容不能为空,请输入后重试!', containerNumber: '容器数量', @@ -1738,6 +1765,9 @@ const message = { website: '备份网站', rulesHelper: '支持多个排除规则,使用英文逗号 , 分隔,例如:*.log,*.sql', lastRecordTime: '上次执行情况', + all: '全部', + failedRecord: '失败记录', + successRecord: '成功记录', database: '备份数据库', backupArgs: '备份参数', backupArgsHelper: '未列出的备份参数可手动输入并选择,如: 输入 --no-data 后选择下拉列表中的第一个', @@ -1846,6 +1876,7 @@ const message = { cleanLogscope: '清理类型', }, monitor: { + globalFilter: '全局筛选', enableMonitor: '监控状态', storeDays: '保存天数', defaultNetwork: '默认网卡', @@ -1858,6 +1889,7 @@ const message = { avgLoad: '平均负载', loadDetail: '负载详情', resourceUsage: '资源使用率', + networkCard: '网卡', read: '读取', write: '写入', readWriteCount: '读写次数', @@ -1869,6 +1901,7 @@ const message = { lastHalfYear: '近半年', memory: '内存', percent: '占比', + cache: '缓存', disk: '磁盘', network: '网络', up: '上行', @@ -1922,12 +1955,16 @@ const message = { createConn: '新建连接', noHost: '暂无主机', groupChange: '切换分组', + expand: '全部展开', + fold: '全部收起', batchInput: '批量输入', quickCommand: '快速命令', noSuchCommand: '导入的 csv 文件中未能发现快速命令数据,请检查后重试!', quickCommandHelper: '常用命令列表,用于在终端界面底部快速选择', + groupDeleteHelper: '移除分组后,分组内所有连接将迁移到 default 分组,是否继续?', quickCommandBatchHelper: '每行一条快速命令,以 名称---命令 格式,例如:查看磁盘---df -h', command: '命令', + quickCmd: '快速命令', addHost: '添加主机', localhost: '本地服务器', ip: '主机地址', @@ -1968,11 +2005,15 @@ const message = { toolboxHelper: '部分安装和使用问题,可参考', }, swap: { + swap: 'Swap 分区', swapHelper1: 'Swap 的大小应该是物理内存的 1 到 2 倍,可根据具体情况进行调整;', swapHelper2: '在创建 Swap 文件之前,请确保系统硬盘有足够的可用空间,Swap 文件的大小将占用相应的磁盘空间;', swapHelper3: 'Swap 可以帮助缓解内存压力,但仅是一个备选项,过多依赖可能导致系统性能下降,建议优先考虑增加内存或优化应用程序内存使用;', swapHelper4: '建议定期监控 Swap 的使用情况,以确保系统正常运行。', + swapDeleteHelper: + '该操作将移除 Swap 分区 {0}。出于系统安全考虑,不会自动删除对应文件,如需删除请手动处理!', + saveHelper: '请先保存当前设置!', saveSwap: '保存当前配置将调整 Swap 分区 {0} 大小到 {1},是否继续?', swapMin: '分区大小最小值为 40 KB,请修改后重试!', swapMax: '分区大小最大值为 {0},请修改后重试!', @@ -1984,6 +2025,7 @@ const message = { dnsHelper1: '当存在多个 DNS 时,需换行显示,例:\n114.114.114.114\n8.8.8.8', hostsHelper: '主机名解析', hosts: '域名', + hostAlert: '已隐藏注释记录,点击“全部配置”按钮可查看或设置', toolbox: '快速设置', hostname: '主机名', passwd: '系统密码', @@ -2155,6 +2197,7 @@ const message = { taskRunning: '执行中', }, file: { + name: '名称', fileDirNum: '共 {0} 个目录,{1} 个文件,', currentDir: '当前目录', dir: '文件夹', @@ -2563,6 +2606,10 @@ const message = { cn: '中国大陆', intl: '全球', regionHelper: '该操作可能影响后续资源下载与访问,是否继续?', + regionHelper1: '系统安装包', + regionHelper2: '应用商店和脚本库', + regionHelper3: '用户手册及相关文档', + regionHelper4: '该操作可能影响后续下载与访问,请谨慎操作。', regionTip: '运行区域影响系统更新源以及安装包下载地址。', docSourceTip: '文档来源决定文档与更新日志的跳转语言。', languageHelper: '默认跟随浏览器语言,设置后只对当前浏览器生效,更换浏览器后需要重新设置', @@ -2617,6 +2664,17 @@ const message = { restartLater: '稍后手动重启', systemIPWarning: '当前节点尚未配置默认访问地址,请前往面板设置进行设置!', systemIPWarning1: '当前服务器地址设置为 {0},无法快速跳转!', + syncTime: '服务器时间', + timeZone: '时区', + timeZoneChangeHelper: '修改时区需要重启服务,是否继续?', + timeZoneHelper: '时区修改依赖系统 timedatectl 服务,重启 1Panel 服务后生效。', + timeZoneCN: '北京', + timeZoneAM: '洛杉矶', + timeZoneNY: '纽约', + ntpALi: '阿里云', + ntpGoogle: 'Google', + syncSite: 'NTP 服务器', + syncSiteHelper: '该操作将使用 {0} 作为源同步系统时间,是否继续?', changePassword: '密码修改', oldPassword: '原密码', newPassword: '新密码', @@ -2723,6 +2781,10 @@ const message = { stepPanelData: '系统数据', stepBackupData: '备份数据', stepOtherData: '其他数据', + operationLog: '保留操作日志', + loginLog: '保留访问日志', + systemLog: '保留系统日志', + taskLog: '保留任务日志', monitorData: '监控数据', dockerConf: 'Docker 配置', selectAllImage: '备份所有应用镜像', @@ -2950,6 +3012,8 @@ const message = { lostHelper: '许可证已达到最大重试次数,请手动点击同步按钮,以确保商业版功能正常使用,详情:', exceptionalHelper: '许可证同步验证异常,请手动点击同步按钮,以确保商业版功能正常使用,详情:', quickUpdate: '快速更新', + import: '导入', + power: '授权', unbindHelper: '解除绑定后将清除该节点所有商业版相关设置,是否继续?', importLicense: '导入许可证', securityWarningTitle: '请勿使用破解版或来源不明的许可证!', @@ -3002,6 +3066,7 @@ const message = { scan: '开始扫描', scanHelper: '轻松梳理 1Panel 运行期间积累的垃圾文件', clean: '立即清理', + reScan: '重新扫描', cleanHelper: '已勾选文件及目录清理后无法回滚,是否继续?', statusSuggest: '( 建议清理 )', statusClean: '( 很干净 )', @@ -3011,6 +3076,7 @@ const message = { lastCleanHelper: '清理文件及目录:{0} 个, 总计清理:{1}', cleanSuccessful: '清理成功!', currentCleanHelper: '本次清理文件及目录:{0} 个, 总计清理:{1}', + suggest: '(建议)', totalScan: '待清理垃圾文件共计: ', selectScan: '已选中垃圾文件共计: ', @@ -3041,6 +3107,7 @@ const message = { systemLog: '日志文件', systemLogHelper: '系统日志、任务日志、网站日志文件', dockerLog: '容器操作日志文件', + taskLog: '计划任务执行日志文件', shell: 'Shell 脚本计划任务', containerShell: '容器内执行 Shell 脚本计划任务', curl: 'CURL 计划任务', @@ -3072,6 +3139,10 @@ const message = { backupdate: '备份时间', versionSelect: '请选择版本', operatorHelper: '将对选中应用进行 {0} 操作,是否继续?', + startOperatorHelper: '即将启动应用,是否继续?', + stopOperatorHelper: '即将停止应用,是否继续?', + restartOperatorHelper: '即将重启应用,是否继续?', + reloadOperatorHelper: '即将重载应用,是否继续?', checkInstalledWarn: '未检测到 {0} ,请进入应用商店点击安装!', limitHelper: '该应用已安装,不支持重复安装', deleteHelper: '{0}已经关联以下资源,请检查后重试!', @@ -3483,9 +3554,9 @@ const message = { staticChangePHPHelper: '当前为静态网站,可以切换为 PHP 网站', proxyCache: '反代缓存', cacheLimit: '缓存空间限制', - shareCahe: '缓存计数内存大小', + shareCache: '缓存计数内存大小', cacheExpire: '缓存过期时间', - shareCaheHelper: '每1M内存可以存储约8000个缓存对象', + shareCacheHelper: '每1M内存可以存储约8000个缓存对象', cacheLimitHelper: '超过限制会自动删除旧的缓存', cacheExpireJHelper: '超出时间缓存未命中将会被删除', realIP: '真实 IP', @@ -3557,6 +3628,8 @@ const message = { default_socket_timeout: 'Socket超时时间', error_reporting: '错误级别', display_errors: '是否输出详细错误信息', + cgi_fix_pathinfo: '是否开启 pathinfo', + date_timezone: '时区', disableFunction: '禁用函数', disableFunctionHelper: '输入要禁用的函数,例如exec,多个请用,分割', uploadMaxSize: '上传限制', @@ -3564,6 +3637,7 @@ const message = { extensions: '扩展模版', extension: '扩展', extensionsHelper: '多个扩展请用,分割', + extensionHelper: '多个扩展请使用英文逗号分隔', toExtensionsList: '查看扩展列表', containerConfig: '容器配置', containerConfigHelper: '环境变量等信息可以在创建完成之后在配置-容器配置中修改', @@ -3741,6 +3815,7 @@ const message = { portFormatError: '请输入正确的端口信息!', portHelper1: '多个端口,如:8080,8081', portHelper2: '范围端口,如:8080-8089', + changeStrategyHelper: '即将把 [{1}] 的 {0} 策略修改为 [{2}],设置后 {0} 将按 [{2}] 策略对外访问,是否继续?', strategy: '策略', accept: '允许', drop: '拒绝', @@ -3778,6 +3853,7 @@ const message = { initHelper: '检测到 {0} 未初始化,请点击顶部状态栏的初始化按钮进行配置!', bindHelper: '绑定 仅当状态为绑定时,防火墙规则才能生效,是否确认?', unbindHelper: '解绑 解除绑定时,已添加的所有防火墙规则将失效,请谨慎操作,是否确认?', + whiteList: '白名单', portWhiteList: '端口白名单', portWhiteListAlter: '防火墙初始化或启动时,将自动放行白名单端口', portWhiteListHelper: '支持指定协议(如 80/tcp、443/udp),未指定时默认使用 TCP。', @@ -3802,6 +3878,7 @@ const message = { }, runtime: { runtime: '运行环境', + default: '默认', workDir: '工作目录', localHelper: '本地环境安装及离线环境使用相关问题,可参考 ', versionHelper: 'PHP的版本,例 v8.0', @@ -4046,7 +4123,9 @@ const message = { deleteConfirm: '确认删除此导出记录及文件?', }, waf: { + WAF: 'WAF', name: 'WAF', + resource: '资源', blackWhite: '黑白名单', globalSetting: '全局设置', websiteSetting: '网站设置', @@ -4328,6 +4407,10 @@ const message = { ip: '独立 IP', spider: '蜘蛛', visitors: '访客趋势', + today: '今天', + last7days: '最近 7 天', + last30days: '最近 30 天', + all: '全部', uvMap: '访客地图 (30日)', qps: '实时请求数(1分钟)', flowSec: '实时流量(1分钟)', @@ -4459,25 +4542,31 @@ const message = { }, setting: { setting: '界面设置', + title: '面板描述', + titleHelper: '将显示在用户登录页面(例如:Linux 服务器运维管理面板,建议 8-15 个字符)', logo: 'Logo (不带文字)', logoHelper: '将会显示在菜单收缩时管理页面左上方 (建议图片大小为: 82px*82px)', logoWithText: 'Logo (带文字)', logoWithTextHelper: '将会显示在菜单展开时管理页面左上方 (建议图片大小为: 185px*55px)', favicon: '网站图标', faviconHelper: '网站图标 (建议图片大小为: 16px*16px)', + setDefault: '恢复默认', setHelper: '即将保存当前界面设置内容,是否继续?', setDefaultHelper: '即将恢复所有界面设置到初始状态,是否继续?', logoGroup: 'Logo', + imageGroup: '图片', loginImage: '图片', loginImageHelper: '将会显示在登录页面(建议图片大小为: 500*416px)', loginBgType: '背景类型', loginBgImage: '背景图片', loginBgImageHelper: '将会显示在登录页面背景图片(建议图片大小为: 1920*1080px)', loginBgColor: '背景颜色', + loginBgColorHelper: '将在登录页面显示为背景颜色', image: '图片', bgColor: '背景色', loginGroup: '登录页', loginBtnLinkColor: '按钮/链接颜色', + loginBtnLinkColorHelper: '将在登录页面显示为按钮和链接颜色', }, helper: { wafTitle1: '拦截地图', @@ -5233,6 +5322,14 @@ const message = { authManage: '认证管理', auth: { providerNavigation: '认证类型', + defaultNode: '默认节点', + defaultNodePlaceholder: '请选择节点', + defaultNodeHelper: '仅用于新用户。', + defaultNodeRequired: '请选择有效的默认节点。', + nodesLoadFailed: '节点列表加载失败,请重试后再选择默认节点。', + nodeHandling: '节点处理', + assignDefaultNode: '分配默认节点:{node}', + keepExistingNode: '保留已有节点权限', providers: { ldap: 'AD/LDAP', passkey: 'Passkey', @@ -5260,7 +5357,347 @@ const message = { planned: '待接入', plannedTitle: '{0} 认证设置', plannedDesc: '该认证方式正在规划中,暂不可用。', + oidc: { + accessMode: '接入方式', + accessModeDesc: '身份提供方支持 Discovery 时优先使用标准模式。', + actionCreate: '创建用户', + actionKeepName: '保留当前名称', + actionPending: '等待结果', + actionReject: '拒绝登录', + actionUpdate: '更新身份信息', + advanced: '高级设置', + advancedDesc: '默认值适用于标准 Provider;只有不兼容时才调整。', + assignDefaultRole: '分配默认角色:{role}', + authorizationEndpoint: '授权端点', + authorizationEndpointInvalid: '请输入有效的授权端点地址。', + authorizationFlow: '授权流程', + automatic: '自动', + automaticPolicy: '自动处理策略', + automaticPolicyDesc: '以下规则由后端固定执行,不作为管理员开关。', + basic: '基础配置', + basicDesc: '先选择 Provider 模式,再配置客户端和回调地址。', + browserTest: '测试登录', + browserTestConflict: '身份验证成功,但用户名冲突', + browserTestConflictHelper: '映射名称属于其他身份,不会自动认领。', + browserTestExpired: '浏览器测试已过期', + browserTestExpiredHelper: '请重新开始测试,并在有效期内完成授权。', + browserTestFailed: '浏览器测试失败', + browserTestFailedHelper: '无法完成身份预览,请查看后端返回的本地化错误。', + browserTestIsolation: '执行真实授权往返,但不会创建或更新用户、分配角色或生成正式 Session。', + browserTestPopupBlocked: '请允许当前站点打开弹窗,然后重新测试。', + browserTestPopupClosed: '授权窗口在测试完成前被关闭。', + browserTestSuccess: 'Provider 验证成功', + browserTestSuccessHelper: '已完成身份映射预览,没有修改用户或 Session。', + browserTestTitle: 'OIDC 浏览器测试登录', + browserTestWaiting: '等待 Provider 授权', + browserTestWaitingHelper: '请在新窗口完成登录,本页面会自动更新。', + callbackCopied: 'OIDC 回调地址已复制。', + callbackURL: '回调地址', + callbackURLHelper: '请将此地址添加到身份提供方客户端的允许回调列表。', + cancelClearSecret: '取消清除', + clearSecret: '清除密钥', + clearSecretConfirm: '客户端密钥只会在保存后删除,是否继续?', + clientAuthMethod: '客户端认证方式', + clientAuthMethodHelper: '请选择身份提供方为该客户端配置的认证方式。', + clientAuthMethodRequired: '请选择客户端认证方式。', + clientID: '客户端 ID', + clientIDRequired: '请输入客户端 ID。', + clientSecret: '客户端密钥', + clockSkew: '令牌时间偏差', + clockSkewHelper: '允许身份提供方与面板存在少量时间偏差,建议保持 60 秒。', + clockSkewRequired: '请输入令牌时间偏差。', + compatibilityMode: '兼容模式', + compatibilityModeHelper: '仅用于 Discovery 不完整或端点被改写的 Provider,核心 OIDC 校验不会关闭。', + configurationFailedHelper: '测试失败,页面只显示后端本地化错误。', + configurationFailedTag: '测试失败', + configurationHighRiskPassed: '配置测试通过,但包含高风险兼容项。', + configurationHighRiskTag: '高风险配置通过', + configurationNotTested: '当前配置尚未测试。', + configurationNotTestedTag: '尚未测试', + configurationPassed: '当前配置已通过安全和能力检查。', + configurationPassedTag: '测试通过', + configurationStaleHelper: '配置已修改,请重新测试保存。', + configurationStaleTag: '结果已过期', + configurationTestMeta: '测试时间 {time},耗时 {duration} ms;不保存 Provider 原始响应。', + configurationTestResult: '配置测试结果', + configurationTestResultDesc: + '这里只检查自动发现结果与身份提供方能力,不交换授权码,也不能证明客户端密钥正确;请使用“浏览器测试登录”完成端到端验证。', + configurationTestSuccess: 'OIDC 配置测试成功。', + configurationTesting: '正在测试当前 OIDC 配置…', + configurationTestingTag: '正在测试', + configureSecret: '配置密钥', + conflictExistingRename: '已有 subject 返回的新 name 已被占用', + conflictExistingRenameResult: '保留原 User.Name,并允许已绑定用户继续登录', + conflictLDAP: 'LDAP 用户', + conflictLocal: '本地用户', + conflictNewAvailable: '新 subject,映射后的 name 未占用', + conflictNewAvailableResult: '创建本地企业用户并分配默认角色', + conflictNone: '无冲突', + conflictOIDC: '其他 OIDC 身份', + conflictOccupied: '映射 name 已被本地、LDAP 或其他 OIDC 身份占用', + conflictOccupiedResult: '拒绝新身份,不自动绑定或合并', + conflictType: '冲突类型', + connectionSecurity: '连接安全', + connectionSecurityDesc: '默认校验证书,私有 IdP 地址由系统自动识别。', + connectionTest: '连接与配置测试', + connectionTestCompatibilityDesc: '验证自定义端点和协议安全策略。', + connectionTestStandardDesc: '根据签发者地址自动发现端点和能力。', + connectionTestTab: '连接测试', + customCA: '自定义 CA', + customCAHelper: '仅作用于当前认证源,且不会写入日志。', + customCARequired: '请提供自定义 CA 证书。', + defaultRole: '默认角色', + defaultRoleHelper: '仅首次创建用户时分配,后续登录不修改角色。', + defaultRolePlaceholder: '请选择角色', + defaultRoleRequired: '请选择有效的默认角色。', + disableAfterSave: '保存后将停用 OIDC。', + disableConfirm: '停用 OIDC 会立即使该认证源用户的访问失效,是否继续?', + disableDiscardConfirm: + '停用 OIDC 属于故障兜底操作:只关闭登录入口,并立即使该认证源用户的访问失效。本页其他未保存修改(包括客户端密钥修改)将被丢弃。是否继续?', + disableTitle: '停用 OIDC', + disabled: '未启用', + discoveryAllowlist: 'Discovery ∩ 安全白名单', + enable: '是否开启', + enableAfterSave: '保存成功后启用 OIDC。', + enabled: '已启用', + endSessionEndpoint: '会话注销端点', + endSessionEndpointHelper: '首期只保存,不执行身份提供方发起的单点登出。', + endSessionEndpointInvalid: '请输入有效的会话注销端点地址。', + endpointDiscoveryPlaceholder: '测试连接后显示', + firstLogin: '首次登录', + firstLoginPolicy: '创建本地企业用户,并分配配置的默认角色。', + fixedAuthorizationCode: 'Authorization Code Flow', + fixedNoTokenPersistence: '不持久化 Token、Claims 和 verifier', + fixedSecurityPolicy: '系统固定执行,无需配置', + fixedStateNonce: '一次性 state 与 nonce', + fixedTokenValidation: 'ID Token 签名与 Claims 校验', + highRiskSaveConfirm: '当前启用配置包含高风险兼容项,请确认隔离环境确实需要这些设置。', + highRiskTitle: '高风险 OIDC 配置', + hs256Compatibility: 'HS256(兼容模式)', + hs256KeyHelper: 'HS256 固定使用当前认证源的客户端密钥,不接受另一份签名密钥。', + hs256Warning: 'HS256 使用共享对称密钥验证 ID Token;仅在 Provider 无法使用非对称算法时启用。', + identityBindingPolicy: '身份主键固定为 AuthSourceID + issuer + subject,同名不会认领其他账号。', + identityMissing: '身份已失效', + issuer: '签发者地址', + issuerHelper: '用于 OIDC 自动发现,返回的 issuer 必须与该地址一致。', + issuerInvalid: '请输入不含查询参数和片段的有效 HTTP 或 HTTPS 签发者地址。', + issuerRequired: '请输入签发者地址。', + jwksRotation: 'JWKS 自动轮换', + jwksURI: 'JWKS 地址', + jwksURIHelper: '使用非对称签名且密钥来源为 JWKS 时必填。', + jwksURIInvalid: '请为当前签名密钥来源填写有效的 JWKS 地址。', + keepExistingRole: '保留已有角色和本地权限', + localSecurityData: '本地安全数据', + localSecurityDataPolicy: '不覆盖角色、MFA、API Key、Passkey 和本地权限。', + localCredentialsManaged: + '用户名和本地密码由 OIDC 身份管理,不能在此修改;角色、权限、MFA、API Key 与 Passkey 仍由本地管理。', + localUserFields: '本地用户字段', + localUserFieldsDesc: '首期只映射 User.Name,不使用 JSON 映射表达式。', + loginWith: '使用 {provider} 登录', + manualEndpoints: '自定义端点', + manualEndpointsDesc: '仅用于自动发现不完整或上游网关改写端点的身份提供方。', + mappingResult: '映射结果', + mode: '接入模式', + modeRequired: '请选择接入模式。', + nameClaim: '用户名 Claim', + nameClaimHelper: '填写身份提供方返回用户名的字段,如 preferred_username。', + nameClaimRequired: '请输入用户名 Claim。', + nameConflict: '同名冲突策略', + panelURL: '面板对外地址', + panelURLHTTPWarning: 'HTTP 不保护授权响应,仅用于 Provider 接受的隔离私有环境。', + panelURLHelper: '填写用户实际访问面板的地址,用于生成回调地址。', + panelURLInvalid: '请输入只包含协议、主机和可选端口的对外地址。', + panelURLRequired: '请输入面板对外地址。', + pkceDisabled: '不使用 PKCE(仅兼容模式)', + pkceDisabledWarning: '关闭 PKCE 会降低授权码流程的抗截获能力。', + pkceHelper: '优先使用 S256,永不提供 plain。', + pkceS256: 'S256(推荐)', + plannedHandling: '预计处理', + privateNetworkIdP: '私有网络 IdP', + privateNetworkIdPHelper: + '显式允许私有地址;元数据、回环、链路本地、异常重定向和 DNS 重绑定仍会阻止。', + privateNetworkWarning: '当前认证源已允许访问私有网络。', + protocolCompatibility: '协议兼容', + protocolCompatibilityDesc: 'ID Token 签名校验始终不能关闭。', + providerAndClient: '身份提供方与客户端', + providerAndClientDesc: '客户端密钥只允许替换或清除,页面不会回显。', + providerCapabilities: 'Provider 能力', + recentTestSuccess: '最近测试成功:{0}', + recommended: '推荐', + rejectPlain: '拒绝 plain', + replaceSecret: '更换密钥', + requestAndClaims: '请求与属性', + requestAndClaimsDesc: '配置授权范围、用户信息补充和请求参数。', + requestTimeout: '请求超时', + requestTimeoutRequired: '请输入请求超时时间。', + restore: '还原', + restored: '已还原到上次保存的 OIDC 配置。', + result: '处理结果', + rolesLoadFailed: '角色列表加载失败,请重试后再选择默认角色。', + roleHandling: '角色处理', + scenario: '场景', + scopes: '授权范围', + scopesHelper: '必须包含 openid,多个范围使用空格分隔。', + scopesRequired: 'Scopes 必须包含 openid。', + seconds: '秒', + secretClearHelper: '清除后,重新启用 OIDC 前必须配置新的客户端密钥。', + secretConfigured: '已配置', + secretNotConfigured: '未配置', + secretPlaceholder: '输入新的客户端密钥', + secretReplaceHelper: '新密钥将在保存时替换原值,请同时更新身份提供方中的客户端密钥。', + secretRequiredHelper: '启用 OIDC 前需要配置客户端密钥。', + secretRequiredToEnable: '请先配置客户端密钥,再启用 OIDC。', + secretSavedHelper: '已加密保存,留空则继续使用当前密钥。', + secretWaiting: '等待输入', + secretWillClear: '保存后清除', + secretWillReplace: '待替换', + signingAlgorithm: 'ID Token 签名算法', + signingAlgorithmHelper: '只能选择后端安全白名单中的算法。', + signingKey: '签名密钥', + signingKeyClientSecret: '客户端密钥(仅 HS256)', + signingKeyJWKS: 'JWKS URI 自动获取和轮换', + signingKeySource: '签名密钥来源', + signingKeySourceHelper: '优先使用 JWKS;静态公钥无法自动轮换。', + signingKeyStatic: '静态 JWK 或 PEM 公钥', + standardDiscovery: '标准模式(自动发现)', + standardDiscoveryDesc: '面板自动发现端点和能力,不保存自动发现原文。', + standardMode: '标准模式', + standardModeHelper: '根据 Issuer 自动发现端点、签名能力和 PKCE 支持。', + standardProtocolPolicy: '标准协议策略', + standardProtocolPolicyDesc: '自动协商签名能力,不需要填写签名算法和 Key。', + staticSigningKey: '静态签名公钥', + staticSigningKeyHelper: '只接受公钥材料;Provider 换 Key 后需要手动更新。', + staticSigningKeyPlaceholder: '粘贴 JWK、JWKS JSON 或 PEM 公钥', + staticSigningKeyRequired: '请提供静态签名公钥。', + staticSigningKeyWarning: '静态签名公钥无法自动轮换;Provider 换 Key 前必须手动更新。', + settingLoadFailed: 'OIDC 配置加载失败', + settingLoadFailedHelper: '为避免用空白默认值覆盖已有配置,当前表单已锁定。请在连接恢复后重试。', + subsequentLogin: '后续登录', + subsequentLoginPolicy: '按 subject 找到绑定,仅在新名称可用时更新 User.Name。', + testBeforeBrowserTest: '请先测试当前配置,再进行浏览器测试登录。', + testBeforeEnable: '保存变更配置前,请先测试当前配置。', + testConfiguration: '测试连接', + testDiscovery: '测试连接', + tlsCustomCA: 'HTTPS · 自定义 CA 证书', + tlsPrivateHTTP: 'HTTP · 仅私有网络(危险)', + tlsPrivateHTTPWarning: 'HTTP 不提供传输加密,只允许显式放行的私有目标。', + tlsSkipVerify: '跳过 TLS 证书校验', + tlsSystem: 'HTTPS · 系统证书校验(推荐)', + tokenEndpoint: '令牌端点', + tokenEndpointInvalid: '请输入有效的令牌端点地址。', + transportSecurity: '传输安全', + transportSecurityHelper: '优先使用 HTTPS;私有 HTTP 还需要显式允许私有网络。', + unsavedChanges: 'OIDC 配置有未保存的更改。', + usedClaim: '使用 Claim', + userInfoEndpoint: '用户信息端点', + userInfoEndpointHelper: '用户名字段缺失时,系统将从该端点补充;留空则不补充。', + userInfoEndpointInvalid: '请输入有效的用户信息端点地址。', + userMapping: '用户配置', + userMappingDesc: '设置 OIDC 用户名映射,以及首次登录创建用户时使用的默认节点和角色。', + }, + saml2: { + actionCreate: '创建用户', + actionPending: '等待结果', + actionReject: '拒绝登录', + actionReuse: '使用已绑定用户', + assignDefaultRole: '分配新用户角色:{role}', + basic: '基础配置', + basicDesc: '配置大多数标准 SAML2 身份提供商所需的常用选项。', + browserTest: '测试登录', + browserTestConflict: '身份验证成功,但用户名冲突', + browserTestConflictHelper: '映射后的用户名属于其他身份,不会自动关联。', + browserTestExpired: '浏览器测试已过期', + browserTestExpiredHelper: '请重新开始测试,并在有效期内完成登录。', + browserTestFailed: '浏览器测试失败', + browserTestFailedHelper: '无法完成身份预览,请查看后端返回的本地化错误。', + browserTestIsolation: '执行真实 SAML2 往返,但不会创建用户、分配角色或生成正式会话。', + browserTestPopupBlocked: '请允许当前站点打开弹窗,然后重新测试。', + browserTestPopupClosed: '登录窗口在测试完成前被关闭。', + browserTestSuccess: 'SAML2 身份验证成功', + browserTestSuccessHelper: '身份映射预览已完成,没有修改用户或会话。', + browserTestTitle: 'SAML2 测试登录', + browserTestWaiting: '等待 IdP 登录', + browserTestWaitingHelper: '请在新窗口完成登录,本页面会自动更新。', + certificateFileInvalid: '请选择有效的 PEM、CRT 或 CER 证书文件。', + configured: '已配置', + configurationFailedHelper: '测试失败,页面只显示后端本地化错误。', + configurationNotTested: '当前配置尚未测试。', + configurationPassed: '当前配置已通过校验。', + configurationStaleHelper: '影响认证的配置已经修改,请重新测试当前草稿。', + configurationTestSuccess: 'SAML2 配置测试成功。', + configurationTesting: '正在测试当前 SAML2 配置…', + conflictLDAP: 'LDAP 用户', + conflictLocal: '本地用户', + conflictNone: '无冲突', + conflictOIDC: 'OIDC 身份', + conflictSAML2: '其他 SAML2 身份', + conflictType: '冲突类型', + credentialFileReadFailed: '无法读取凭据文件。', + credentialFileTooLarge: '凭据文件不能超过 256 KiB。', + credentialsRequired: '请同时配置 SP 私钥和 SP 证书。', + defaultRole: '新用户角色', + defaultRoleHelper: '仅首次创建时设置;后续登录保留本地角色、MFA 和权限。', + defaultRolePlaceholder: '请选择角色', + defaultRoleRequired: '请选择有效的新用户角色。', + disableConfirm: '停用 SAML2 会立即拒绝新登录并使其用户会话失效,是否继续?', + disableDiscardConfirm: '停用 SAML2 会丢弃本页其他未保存修改,并立即使其用户会话失效,是否继续?', + disableTitle: '停用 SAML2', + disabled: '未启用', + enable: '是否开启', + enabled: '已启用', + idpMetadata: 'IdP 元数据', + idpMetadataDesc: '填写 URL 或粘贴 XML,二选一即可;同时填写时优先读取 URL。', + keepExistingRole: '保留已有角色和本地权限', + loginWith: '使用 {provider} 登录', + mappingResult: '映射结果', + metadataRequired: '请填写 IdP 元数据 URL 或 XML。', + metadataURLHelper: '测试和保存时由后端读取并校验元数据。', + metadataURLInvalid: '请输入不含凭据和片段的有效 HTTPS 元数据 URL。', + metadataURLRecommended: '元数据 URL(推荐)', + metadataXML: '元数据 XML', + metadataXMLHelper: '适用于身份提供商(IdP)没有可访问的元数据 URL 的场景。', + metadataXMLInvalid: '请输入包含有效 EntityDescriptor 的元数据 XML。', + metadataXMLPlaceholder: '粘贴 ...', + nameAttribute: '用户名属性', + nameAttributeHelper: '从已验证的 SAML 断言中读取该属性,并映射为面板用户名。', + nameAttributePlaceholder: '例如 uid、username 或 account', + nameAttributeRequired: '请填写用户名属性。', + notConfigured: '未配置', + or: '或', + pageDesc: '通过 IdP 元数据接入企业单点登录,常用配置在一个页面完成。', + plannedHandling: '预计处理', + privateKeyFileInvalid: '请选择有效的 PEM 私钥文件。', + recentTestSuccess: '最近测试成功:{0}', + restore: '还原', + restored: '已还原到上次保存的 SAML2 配置。', + roleHandling: '角色处理', + rolesLoadFailed: '角色列表加载失败,请重试后再选择新用户角色。', + selectFile: '选择文件', + serviceStatus: '服务状态', + serviceStatusDesc: '首次启用前需要先通过当前配置测试。', + settingLoadFailed: 'SAML2 配置加载失败', + settingLoadFailedHelper: '为避免用空白默认值覆盖已有配置,当前表单已锁定。请在连接恢复后重试。', + spCertificate: 'SP 证书', + spCertificateHelper: '通过 SP 元数据提供给身份提供商(IdP),用于验证登录和注销请求。', + spCredentials: 'SP 私钥与证书', + spCredentialsDesc: '用于签名登录和注销消息;具体签名与安全校验策略由后端固定处理。', + spPrivateKey: 'SP 私钥', + spPrivateKeyHelper: '用于签名 SAML 登录请求和注销消息,加密保存且不会回显。', + syncLogout: '同步注销', + syncLogoutHelper: '用户退出面板时同时退出身份提供商;从身份提供商注销时也会同步退出面板。', + testBeforeBrowserTest: '请先测试当前配置,再进行浏览器测试登录。', + testBeforeEnable: '启用 SAML2 或保存认证敏感变更前,请先测试当前配置。', + testConfiguration: '测试配置', + unsavedChanges: 'SAML2 配置有未保存的更改。', + usedAttribute: '用户名映射', + usersAndRoles: '用户与角色', + usersAndRolesDesc: '设置面板用户名映射,以及首次登录创建用户时使用的默认节点和角色。', + }, ldap: { + basic: '基础配置', + loginTitle: 'LDAP 登录', + loginWith: '使用 LDAP 登录', + backToLocalLogin: '返回面板登录', enable: '是否开启', enabled: '已启用', disabled: '未启用', @@ -5274,13 +5711,13 @@ const message = { bindPassword: '密码', passwordSaved: '留空则保留已保存的密码', userSearch: '用户搜索', - userSearchDesc: '配置用户搜索基准与过滤器,并映射到 1Panel 用户名字段。', + userSearchDesc: '配置用户搜索基准与过滤器,并映射到面板用户名字段。', userFilter: '用户过滤器', userFilterTooltip: '按用户名查询时替换 %(user)s,全量读取时替换为 *。', userFilterHelper: '搜索和认证时会对用户名执行 LDAP filter escaping。', attributeMap: '映射属性', - attributeMapTooltip: '1Panel 用户名字段(name)到 LDAP 属性的 JSON 映射。', - attributeMapHelper: '填写映射到 1Panel 用户名字段(name)的 LDAP 属性。', + attributeMapTooltip: '面板用户名字段(name)到 LDAP 属性的 JSON 映射。', + attributeMapHelper: '填写映射到面板用户名字段(name)的 LDAP 属性。', advanced: '高级设置', advancedDesc: '配置 TLS 和 LDAP 查询分页。', strictSync: '严格同步', @@ -5318,7 +5755,7 @@ const message = { searchPageSizeRequired: '请输入 LDAP 查询分页大小。', sync: { title: '定时同步', - description: '定期读取 LDAP 全量用户,并维护 1Panel 中的 LDAP 用户。', + description: '定期读取 LDAP 全量用户,并维护面板中的 LDAP 用户。', enable: '是否启用', enableHelper: '关闭后不再自动执行,仍可手动立即同步。', schedule: '执行周期', @@ -5376,7 +5813,7 @@ const message = { action: '处理动作', }, testLoginTitle: '测试 AD/LDAP 登录', - testLoginDesc: '使用 AD/LDAP 用户凭据执行 bind 验证,仅测试认证能力,不创建 1Panel 登录会话。', + testLoginDesc: '使用 AD/LDAP 用户凭据执行 bind 验证,仅测试认证能力,不创建面板登录会话。', ldapUsername: 'LDAP 用户名', usernameRequired: '请输入 LDAP 用户名。', startTest: '开始测试', @@ -5444,7 +5881,11 @@ const message = { '用于自定义镜像前缀,自动修改 Compose 文件中的镜像字段。\n 例如,当镜像前缀设置为 1panel/custom 时,MaxKB 的镜像将变更为 1panel/custom/maxkb:v1.10.0。', closeHelper: '是否取消使用自定义仓库', appStoreUrlHelper: '仅支持 .tar.gz 格式', + postNode: '同步至子节点', + postNodeHelper: '将自定义应用仓库包同步到子节点安装目录下的 tmp/customApp/apps.tar.gz', + nodes: '节点', selectNode: '选择节点', + selectNodeError: '请选择节点', licenseHelper: '商业版支持自定义应用仓库功能', databaseHelper: '应用关联数据库,请选择目标节点数据库', nodeHelper: '不能选择当前节点', @@ -5478,6 +5919,7 @@ const message = { memory: '面板服务器内存过高告警', load: '面板服务器负载过高告警', disk: '面板服务器磁盘过高告警', + website: '网站', certificate: '证书', remainingDays: '剩余天数', sendCount: '告警次数', @@ -5598,6 +6040,9 @@ const message = { timeRange: '时间范围', sendTimeRange: '可发送时间范围', sendTimeRangeHelper: '可推送{0}时间范围', + to: '至', + startTime: '开始时间', + endTime: '结束时间', defaultPhone: '默认使用与许可证绑定的账户手机号', noticeAlert: '通知告警', resourceAlert: '资源告警', @@ -5674,6 +6119,7 @@ const message = { classicBlue: '经典蓝', freshGreen: '清新绿', customColor: '自定义主题色', + setDefault: '恢复默认', setDefaultHelper: '即将恢复主题配色到初始状态,是否继续?', setHelper: '即将保存当前选定的主题配色,是否继续?', }, @@ -5925,6 +6371,7 @@ const message = { snapshotEmpty: '暂无快照', snapshotHelper: '快照会保存虚拟机当前状态作为还原点,后续数据变化会记录在差分文件中,不影响原始磁盘。恢复快照时,虚拟机会回到该时间点状态。', + snapshotOperationHelper: '当前快照无法删除;仅可在虚拟机关机时恢复快照。', snapshotRecoverConfirm: '确认将虚拟机 [{1}] 恢复到快照 [{0}]?恢复后虚拟机磁盘会回到该快照状态。', interface: '网络接口', device: '设备', diff --git a/frontend/src/layout/components/Sidebar/components/Collapse.vue b/frontend/src/layout/components/Sidebar/components/Collapse.vue index cd487ab2e..e228fb586 100644 --- a/frontend/src/layout/components/Sidebar/components/Collapse.vue +++ b/frontend/src/layout/components/Sidebar/components/Collapse.vue @@ -101,6 +101,7 @@ import { getAgentSettingInfo } from '@/api/modules/setting'; import { computed, onMounted, ref } from 'vue'; import bus from '@/global/bus'; import { logOutApi } from '@/api/modules/auth'; +import { submitSAML2Navigation } from '@/utils/saml2'; import router from '@/routers'; import { loadProductProFromDB } from '@/utils/xpack'; import { routerToNameWithQuery } from '@/utils/router'; @@ -277,9 +278,15 @@ const logout = () => { type: 'warning', }) .then(async () => { - await logOutApi(); + const res = await logOutApi(); globalStore.setLogStatus(false); globalStore.clearAuthInfo(); + if (res.data?.saml2Navigation) { + try { + submitSAML2Navigation(res.data.saml2Navigation); + return; + } catch {} + } router.push({ name: 'entrance', params: { code: entrance.value } }); MsgSuccess(i18n.global.t('commons.msg.operationSuccess')); }) diff --git a/frontend/src/layout/components/Sidebar/components/user-info/index.vue b/frontend/src/layout/components/Sidebar/components/user-info/index.vue index ff842b9a3..9af63cc11 100644 --- a/frontend/src/layout/components/Sidebar/components/user-info/index.vue +++ b/frontend/src/layout/components/Sidebar/components/user-info/index.vue @@ -26,7 +26,7 @@ /> ; + }; + +const validateNavigationURL = (value: string) => { + const url = new URL(value, window.location.origin); + if (!['http:', 'https:'].includes(url.protocol)) { + throw new Error('Unsupported SAML2 navigation protocol'); + } + return url.toString(); +}; + +export const submitSAML2Navigation = (navigation: SAML2Navigation, targetWindow: Window = window) => { + if (navigation.binding === 'redirect' && navigation.redirectURL) { + targetWindow.location.assign(validateNavigationURL(navigation.redirectURL)); + return; + } + if (navigation.binding !== 'post' || !navigation.postURL || !navigation.fields) { + throw new Error('Invalid SAML2 navigation response'); + } + + const form = targetWindow.document.createElement('form'); + form.method = 'POST'; + form.action = validateNavigationURL(navigation.postURL); + form.style.display = 'none'; + + Object.entries(navigation.fields || {}).forEach(([name, value]) => { + const input = targetWindow.document.createElement('input'); + input.type = 'hidden'; + input.name = name; + input.value = value; + form.appendChild(input); + }); + + targetWindow.document.body.appendChild(form); + form.submit(); + form.remove(); +}; diff --git a/frontend/src/views/container/container/inspect/index.vue b/frontend/src/views/container/container/inspect/index.vue index f079e4be5..01e61649a 100644 --- a/frontend/src/views/container/container/inspect/index.vue +++ b/frontend/src/views/container/container/inspect/index.vue @@ -72,7 +72,7 @@ - + diff --git a/frontend/src/views/container/template/import/index.vue b/frontend/src/views/container/template/import/index.vue index 199528a33..f624231d7 100644 --- a/frontend/src/views/container/template/import/index.vue +++ b/frontend/src/views/container/template/import/index.vue @@ -136,14 +136,14 @@ const fileOnChange = (_uploadFile: UploadFile, uploadFiles: UploadFiles) => { const parsed = JSON.parse(content); if (!Array.isArray(parsed)) { - MsgError(i18n.global.t('commons.msg.errJsonImportFormat')); + MsgError(i18n.global.t('commons.msg.errImportFormat')); loading.value = false; return; } for (const item of parsed) { if (!checkDataFormat(item)) { - MsgError(i18n.global.t('commons.msg.errJsonImportFormat')); + MsgError(i18n.global.t('commons.msg.errImportFormat')); loading.value = false; return; } diff --git a/frontend/src/views/log/operation/index.vue b/frontend/src/views/log/operation/index.vue index 8c1e161d2..6389bd868 100644 --- a/frontend/src/views/log/operation/index.vue +++ b/frontend/src/views/log/operation/index.vue @@ -277,8 +277,8 @@ const exactReplacements: Record = { OpsReportAutoExport: 'xpack.opsReport.page.autoExport', ComplexityVerification: 'setting.complexity', MFAStatus: 'setting.mfa', - MonitorStatus: 'setting.enableMonitor', - MonitorStoreDays: 'setting.monitor', + MonitorStatus: 'monitor.enableMonitor', + MonitorStoreDays: 'monitor.storeDays', ApiInterfaceStatus: 'setting.apiInterface', ComponentSize: 'setting.componentSize', Region: 'setting.region', diff --git a/frontend/src/views/login/components/login-form.vue b/frontend/src/views/login/components/login-form.vue index 5110a6cfd..5d16638da 100644 --- a/frontend/src/views/login/components/login-form.vue +++ b/frontend/src/views/login/components/login-form.vue @@ -76,6 +76,55 @@ {{ $t('commons.login.passkey') }} + {{ $t('commons.login.passkeyToPassword') }} @@ -101,7 +150,24 @@
-
{{ $t('commons.button.login') }}
+
+
+ {{ + loginSource === 'ldap' + ? $t('xpack.user.auth.ldap.loginTitle') + : $t('commons.button.login') + }} +
+ +
@@ -194,6 +260,55 @@ {{ $t('commons.button.login') }} + {{ $t('commons.login.username') }}:demo {{ $t('commons.login.password') }}:1panel @@ -242,7 +357,7 @@