diff --git a/apps/web/src/components/settings-sidebar/index.vue b/apps/web/src/components/settings-sidebar/index.vue
index 696445cf6..03409f4ff 100644
--- a/apps/web/src/components/settings-sidebar/index.vue
+++ b/apps/web/src/components/settings-sidebar/index.vue
@@ -14,13 +14,13 @@
class="p-0 border-0"
>
diff --git a/apps/web/src/i18n/locales/en.json b/apps/web/src/i18n/locales/en.json
index 38b2e7622..c9feea72b 100644
--- a/apps/web/src/i18n/locales/en.json
+++ b/apps/web/src/i18n/locales/en.json
@@ -13,7 +13,13 @@
"operation": "Actions",
"enable": "Enable",
"optional": "optional",
+ "allOptional": "all optional",
+ "placeholderPrefix": "e.g. {example}",
"advanced": "Advanced",
+ "primary": "Primary",
+ "format": "Format",
+ "dangerZone": "Danger Zone",
+ "viewAll": "View All",
"import": "Import",
"export": "Export",
"copy": "Copy",
@@ -27,12 +33,18 @@
"batchDeleteConfirm": "Delete {count} selected item(s)?",
"batchExport": "Batch export",
"cancelSelection": "Cancel selection",
+ "updatedAt": "Updated",
+ "actions": "Actions",
+ "enabled": "Enabled",
+ "disabled": "Disabled",
"name": "Name",
"namePlaceholder": "Enter name",
"type": "Type",
"typePlaceholder": "Select type",
"refresh": "Refresh",
"status": "Status",
+ "active": "Active",
+ "inactive": "Inactive",
"loadFailed": "Failed to load",
"saveFailed": "Failed to save",
"createdAt": "Created at",
@@ -772,15 +784,105 @@
"callbackUrl": "Callback URL",
"callbackUrlHint": "Set this as the callback/redirect URL in your OAuth App settings.",
"callbackMissingParams": "Missing authorization code or state parameter"
- }
+ },
+ "servers": "Servers",
+ "addNew": "New Server",
+ "searchServers": "Search servers...",
+ "unnamedServer": "Unnamed Server",
+ "untitled": "Untitled",
+ "unsavedChangesTitle": "Unsaved Changes",
+ "verifyingCancel": "Cancel",
+ "discardDraftConfirm": "Are you sure you want to discard this draft?",
+ "discard": "Discard",
+ "invalidConfig": "Invalid configuration",
+ "handshakeError": "Connection failed",
+ "viewRawLog": "View raw log",
+ "identity": "Identity",
+ "placeholders": {
+ "name": "e.g. Weather API",
+ "url": "https://...",
+ "envKey": "Key",
+ "envValue": "Value",
+ "headerKey": "Header",
+ "headerValue": "Value"
+ },
+ "transportType": "Transport",
+ "payload": "Payload",
+ "endpointUrl": "Endpoint URL",
+ "streamProtocol": "Protocol",
+ "protocol": {
+ "http": "HTTP",
+ "sse": "SSE"
+ },
+ "advancedSettings": "Advanced Settings",
+ "advancedSettingsHint": "Environment variables, headers, and OAuth.",
+ "expand": "Expand",
+ "collapse": "Collapse",
+ "envVars": "Environment Variables",
+ "httpHeaders": "HTTP Headers",
+ "notConfigured": "Not configured",
+ "discoveredTools": "Discovered Tools",
+ "noToolsExposed": "No tools exposed by this server.",
+ "more": "more",
+ "dangerZoneHint": "Permanently remove this server.",
+ "importSandbox": "Import Configuration",
+ "pathCopied": "Path copied to clipboard",
+ "blindImport": "Import",
+ "allTools": "All Tools",
+ "searchTools": "Search tools...",
+ "noDescription": "No description available.",
+ "noToolsMatch": "No tools match your search.",
+ "diagnosticLog": "Diagnostic Log",
+ "noLog": "No diagnostic information available.",
+ "copyLog": "Copy Log",
+ "editValue": "Edit {value}",
+ "editLongTextHint": "Enter or edit your long configuration value here.",
+ "enterContent": "Enter content here...",
+ "unsavedChangesDesc": "You have unsaved changes. Do you want to discard them?",
+ "keepEditing": "Keep Editing",
+ "discardAndSwitch": "Discard & Switch"
},
"home": {
"title": "Home"
},
"bots": {
"toolApproval": {
+ "posture": {
+ "title": "Security Posture",
+ "hardened": "Hardened",
+ "description": "Approval policies are actively enforcing execution boundaries."
+ },
+ "metrics": {
+ "activeRules": "Active rules",
+ "totalDefined": "Total defined",
+ "blockedCount": "Blocks",
+ "sessionTrust": "Session trust"
+ },
+ "recentActivity": "Recent Activity",
+ "trust": "Trust",
+ "actions": {
+ "trustCall": "Trust call",
+ "trustDir": "Trust directory"
+ },
+ "noActivity": "No recent activity.",
+ "warnings": {
+ "disabled": "Tool approval is currently disabled.",
+ "breachRisk": "Resetting will clear all custom security rules."
+ },
+ "restoreSecurity": "Enable Tool Approval",
+ "examples": "Examples",
+ "status": {
+ "active": "Active",
+ "implicitDeny": "Implicit Deny",
+ "sealed": "Sealed"
+ },
+ "dangerZone": "Danger Zone",
+ "dangerZoneDesc": "Manage core security policies.",
+ "resetDefaults": "Reset to Defaults",
+ "confirmReset": "Are you sure you want to reset all tool approval rules to their default state?",
+ "resetWarningExtra": "Custom bypass and review rules will be lost.",
"title": "Tool Call Approval",
- "intro": "Require human approval before the bot writes, edits files, or runs commands inside its container. Configure rules per sensitive tool below — bypass templates skip approval automatically, must-review templates always trigger approval.",
+ "intro": "Require approval before the bot modifies files or runs commands. Configure rules for each tool below. Bypass patterns auto-approve; must-review patterns force approval.",
"tools": {
"write": "Create new files inside the container",
"edit": "Modify existing files inside the container",
@@ -802,7 +904,7 @@
"title": "Bots",
"searchPlaceholder": "Search bots…",
"createBot": "New Bot",
- "createBotWaitHint": "Creating a bot may need to pull the base image on first use. Please wait a moment after submission.",
+ "createBotWaitHint": "First-time creation may pull base images and take a moment.",
"createBotSuccess": "Bot created successfully.",
"steps": {
"basicInfo": "Basic Info",
@@ -827,7 +929,7 @@
},
"localWorkspacePath": "Local workspace folder",
"localWorkspacePathPlaceholder": "Choose a folder on this computer",
- "localWorkspaceWarning": "Local workspaces can access host files and commands with the server user's permissions.",
+ "localWorkspaceWarning": "Local workspaces run directly on the host using the server's permissions, giving them full access to local files and commands.",
"editBot": "Edit Bot",
"deleteConfirm": "Are you sure you want to delete this bot?",
"renameSuccess": "Bot name updated",
@@ -844,9 +946,9 @@
"timezoneInherited": "Inherited from user/system",
"timezoneInheritedHint": "Leave empty to inherit the user's timezone, or fall back to the system timezone.",
"aclPreset": "Security Policy",
- "aclPresetDescription": "Choose a common ACL starting point during creation. You can fine-tune it later in Access Control.",
- "aclPresetHint": "Recommendation: use Private Only for personal assistants, Group Only or Group and Thread for community bots, and Allow All when you want the broadest default.",
- "aclPresetHelp": "This initializes the bot ACL default effect and preset rules at creation time. You can still edit them later in Access Control.",
+ "aclPresetDescription": "Start with a standard ACL preset. You can tweak it later in Access Control.",
+ "aclPresetHint": "Tip: use 'Private Only' for personal bots, 'Group Only' or 'Group and Thread' for community bots, and 'Allow All' to stay completely open.",
+ "aclPresetHelp": "This sets up your default ACL effect and initial rules. You can adjust them anytime from the Access Control page.",
"aclPresets": {
"allowAll": {
"title": "Allow All",
@@ -891,6 +993,22 @@
"deleteFailed": "Delete failed"
},
"checks": {
+ "lastSync": "Last synced",
+ "statusTitle": "Health Checks",
+ "status": {
+ "issue": "Needs attention",
+ "stable": "Healthy",
+ "ok": "OK",
+ "warn": "WARN",
+ "error": "ERROR",
+ "unknown": "UNKNOWN"
+ },
+ "vitalityTitle": "Vitality",
+ "vitalityUnit": "events",
+ "diagnosticTitle": "Diagnostics",
+ "diagnosticSubtitle": "Real-time system diagnostics.",
+ "expandAll": "Expand all",
+ "collapse": "Collapse",
"title": "Runtime Checks",
"subtitle": "View current health status and issue details.",
"ok": "No issues",
@@ -914,15 +1032,10 @@
"containerTask": "Container task",
"containerDataPath": "Container data path",
"botDelete": "Bot deletion"
- },
- "status": {
- "ok": "OK",
- "warn": "WARN",
- "error": "ERROR",
- "unknown": "UNKNOWN"
}
},
"tabs": {
+ "overviewSubtitle": "System vitality and quick insights.",
"overview": "Overview",
"general": "General",
"desktop": "Desktop",
@@ -944,17 +1057,26 @@
"settings": "Settings"
},
"desktop": {
+ "title": "Desktop Environment",
+ "subtitle": "Manage virtual display and interaction sessions.",
+ "groupInfrastructure": "Infrastructure",
+ "groupEnvironment": "Environment",
+ "groupApplication": "Application",
"runtimeTitle": "Runtime",
"runtimeButton": "Runtime",
- "liveTitle": "Desktop 1",
- "liveDescription": "Primary live workspace desktop.",
- "previewTitle": "Other desktops",
- "previewDescription": "Connected sessions appear here as screenshots.",
- "previewEmpty": "Waiting for screenshot",
+ "liveTitle": "Primary Display",
+ "liveDescription": "Live preview of the workspace desktop.",
+ "previewTitle": "Active Sessions",
+ "previewDescription": "Screenshots of other connected sessions.",
+ "previewEmpty": "No preview",
"sessionsTitle": "Sessions",
- "summaryDisabled": "Desktop is disabled",
- "summaryReady": "Desktop is ready",
- "summaryPreparing": "Desktop runtime will be prepared when a window opens",
+ "summaryDisabled": "Disabled",
+ "summaryReady": "Running",
+ "summaryPreparing": "Preparing environment...",
+ "statusReady": "Ready",
+ "statusNotReady": "Not Ready",
+ "statusRunning": "Running",
+ "statusStopped": "Stopped",
"enabled": "Enabled",
"runtime": "Runtime",
"vnc": "VNC",
@@ -965,11 +1087,14 @@
"session": "Session",
"state": "State",
"codec": "Codec",
- "createdAt": "Created",
+ "createdAt": "Started",
"actions": "Actions",
- "noSessions": "No other desktop sessions",
- "closeSession": "Close session",
- "closeFailed": "Failed to close desktop session",
+ "noSessions": "No active sessions",
+ "closeSession": "Terminate",
+ "closeSessionConfirm": "Terminate session?",
+ "closeFailed": "Failed to terminate session",
+ "desktopEnabledSuccess": "Desktop environment enabled",
+ "desktopDisabledSuccess": "Desktop environment disabled",
"unknown": "Unknown"
},
"terminal": {
@@ -1041,32 +1166,32 @@
"sentAt": "Sent"
},
"container": {
- "title": "Container Management",
- "subtitle": "Manage the runtime container attached to this bot.",
- "botNotReady": "This bot is in lifecycle transition. Container actions are temporarily disabled.",
- "empty": "No container found for this bot. Create one to enable runtime tooling.",
- "legacyWarning": "This container uses an older architecture and needs to be recreated for full compatibility. Your data will be preserved automatically.",
- "legacyRecreate": "Recreate Container",
- "legacyRecreateSuccess": "Container recreated successfully",
- "createHint": "The container is created from the current image. If you explicitly enable restore, preserved data will be restored after creation.",
+ "title": "Container",
+ "subtitle": "Manage the runtime environment for this bot.",
+ "botNotReady": "Bot lifecycle transition in progress. Container actions disabled.",
+ "empty": "No container found. Create one to enable runtime tools.",
+ "legacyWarning": "Old architecture detected. Recreate for full compatibility (data preserved automatically).",
+ "legacyRecreate": "Recreate",
+ "legacyRecreateSuccess": "Container recreated",
+ "createHint": "Container created from current image. Enable restore to recover preserved data.",
"createRestoreDataLabel": "Restore preserved data after creation",
- "createRestoreDataDescription": "If a previously exported backup or legacy bind-mounted data exists, it will be restored into `/data` after the container is created.",
+ "createRestoreDataDescription": "Existing backups or legacy data will be restored into `/data` automatically.",
"createImageLabel": "Base image",
- "createImageDescription": "Docker image to use as the container base (e.g. debian:bookworm-slim, alpine:latest, ubuntu:24.04). Leave empty for the default.",
+ "createImageDescription": "Docker image for the container base (e.g. debian:bookworm-slim). Leave empty for default.",
"createAdvancedTitle": "Advanced options",
- "createAdvancedDescription": "Configure optional GPU access and raw CDI device mappings for this container.",
+ "createAdvancedDescription": "Configure GPU access and raw CDI device mappings.",
"createGpuLabel": "Enable GPU",
"createGpuDescription": "Attach host GPU access to the new container.",
"createGpuDevicesLabel": "CDI devices",
- "createGpuDevicesDescription": "Enter one CDI device per line or separate them with commas, for example `nvidia.com/gpu=0` or `amd.com/gpu=0`. Turning GPU off explicitly clears the saved GPU preference.",
+ "createGpuDevicesDescription": "Enter one CDI device per line or use commas. Turning GPU off clears saved preferences.",
"createGpuDevicesPlaceholder": "nvidia.com/gpu=0\namd.com/gpu=0",
- "gpuDevicesRequired": "At least one CDI device is required when GPU is enabled.",
+ "gpuDevicesRequired": "At least one CDI device is required for GPU.",
"cdiDevicesEmpty": "No GPU attached",
- "gpuRecreateHint": "Changing GPU settings requires recreating the container. A simple start or stop will not change the devices already attached.",
- "deleteConfirm": "Are you sure you want to permanently delete this container? Unpreserved data cannot be recovered.",
- "deletePreserveConfirm": "Are you sure you want to export `/data` and then delete this container?",
- "restoreConfirm": "Are you sure you want to restore preserved data into this container's `/data`?",
- "rollbackConfirm": "Are you sure you want to roll back to this snapshot version?",
+ "gpuRecreateHint": "GPU changes require recreation. A simple start/stop will not update devices.",
+ "deleteConfirm": "Delete this container permanently? Unpreserved data cannot be recovered.",
+ "deletePreserveConfirm": "Export `/data` and then delete this container?",
+ "restoreConfirm": "Restore preserved data into `/data`?",
+ "rollbackConfirm": "Roll back to this snapshot version?",
"taskRunning": "Running",
"taskStopped": "Stopped",
"taskCompleted": "Completed",
@@ -1075,7 +1200,7 @@
"statusStopped": "Stopped",
"statusExited": "Exited",
"statusUnknown": "Unknown",
- "loadFailed": "Failed to load container information",
+ "loadFailed": "Failed to load container info",
"actionFailed": "Container action failed",
"createSuccess": "Container created",
"createRestoreSuccess": "Container created and data restored",
@@ -1086,25 +1211,28 @@
"snapshotSuccess": "Snapshot created",
"exportSuccess": "Data exported",
"importSuccess": "Data imported",
- "restoreSuccess": "Preserved data restored",
+ "restoreSuccess": "Data restored",
"rollbackSuccess": "Snapshot rolled back",
"pullingImage": "Pulling image...",
"creatingContainer": "Creating container...",
- "preservingData": "Backing up data, this may take a while for large volumes...",
- "restoringData": "Restoring data, this may take a while for large volumes...",
- "snapshotEmpty": "No snapshots found",
+ "preservingData": "Backing up data...",
+ "restoringData": "Migrating data...",
+ "lifecycleTitle": "Lifecycle",
+ "snapshotTitle": "Snapshots",
+ "snapshotSubtitle": "Capture and rollback container states.",
+ "snapshotEmpty": "No snapshots",
"snapshotLoadFailed": "Failed to load snapshots",
- "snapshotNamePlaceholder": "Snapshot display name (optional)",
- "snapshotNameHint": "This field is only for the user-visible display name. The internal snapshot name is generated automatically.",
- "metricsTitle": "Resource Status",
- "metricsSubtitle": "View CPU, memory, and storage usage for the container's entire filesystem.",
- "metricsLoadFailed": "Failed to load container resource status",
- "metricsUnsupported": "The current container backend does not support resource monitoring.",
- "metricsUnavailable": "No resource metrics available.",
- "metricsStopped": "The container task is not running; CPU and memory metrics are unavailable. Storage information will still be shown if available.",
- "metricsPath": "Scope",
- "metricsUnlimited": "No memory limit configured",
- "currentSample": "Current sample",
+ "snapshotNamePlaceholder": "Display name (optional)",
+ "snapshotNameHint": "User-visible display name; system generates internal name.",
+ "metricsTitle": "Resources",
+ "metricsSubtitle": "CPU, memory, and storage usage.",
+ "metricsLoadFailed": "Failed to load metrics",
+ "metricsUnsupported": "Resource monitoring not supported by backend.",
+ "metricsUnavailable": "No metrics available.",
+ "metricsStopped": "Container not running; viewing storage only.",
+ "metricsPath": "Path",
+ "metricsUnlimited": "No limit",
+ "currentSample": "Current",
"sampledAt": "Sampled at",
"metricsLabels": {
"cpu": "CPU",
@@ -1112,53 +1240,68 @@
"storage": "Storage"
},
"dataTitle": "Data Operations",
- "dataSubtitle": "Independently manage import, export, and restore for the container `/data` directory.",
+ "dataSubtitle": "Manage import, export, and restore for `/data`.",
"deleteTitle": "Delete Container",
- "deleteSubtitle": "Before deletion, explicitly choose whether `/data` should be preserved to avoid accidental data loss.",
- "preservedDataAvailable": "Preserved data is available and can be restored into the current container.",
+ "deleteSubtitle": "Confirm whether to preserve `/data` before deletion.",
+ "deleteZoneDesc": "Deleting this container cannot be undone. Proceed with caution.",
+ "preservedDataAvailable": "Preserved data available for restoration.",
"preservedDataAvailableShort": "Available",
"preservedDataEmpty": "None",
"sourceManual": "Manual",
- "sourcePreExec": "Auto before execution",
- "sourceRollback": "Generated by rollback",
+ "sourcePreExec": "Auto pre-exec",
+ "sourceRollback": "Rollback",
"fields": {
- "id": "Container ID",
- "status": "Container Status",
+ "id": "ID",
+ "status": "Status",
"task": "Task",
"namespace": "Namespace",
"image": "Image",
"cdiDevices": "CDI Devices",
"hostPath": "Host Path",
- "containerPath": "Container Path",
+ "containerPath": "Path",
"preservedData": "Preserved Data",
- "createdAt": "Created At",
- "updatedAt": "Updated At"
+ "createdAt": "Created",
+ "updatedAt": "Updated"
},
"snapshotColumns": {
"name": "Name",
"version": "Version",
"source": "Source",
"parent": "Parent",
- "createdAt": "Created At",
+ "createdAt": "Created",
"actions": "Actions"
},
"actions": {
- "create": "Create Container",
+ "create": "Create",
"start": "Start",
"stop": "Stop",
- "delete": "Delete Permanently",
- "deletePreserve": "Delete and Preserve Data",
- "snapshot": "Create Snapshot",
- "exportData": "Export Data",
- "importData": "Import Data",
- "restoreData": "Restore Preserved Data",
+ "delete": "Delete",
+ "deletePreserve": "Preserve & Delete",
+ "snapshot": "Create",
+ "exportData": "Export",
+ "importData": "Import",
+ "restoreData": "Restore",
"rollback": "Rollback"
}
},
"settings": {
+ "blocks": {
+ "context": "Context & Memory",
+ "contextDescription": "Configure how this bot remembers and processes information.",
+ "global": "Global Settings",
+ "globalDescription": "Core preferences for this bot.",
+ "interaction": "Interaction",
+ "interactionDescription": "Configure how the bot engages in conversations.",
+ "multimedia": "Multimedia",
+ "multimediaDescription": "Configure voice and image generation models."
+ },
+ "hideMemoryDetails": "Hide details",
+ "showMemoryDetails": "Show details",
+ "chatLanguage": "Language",
+ "chatLanguagePlaceholder": "e.g., English, zh-CN",
"chatModel": "Chat Model",
"titleModel": "Title Model",
- "titleModelDescription": "Select a small model to auto-generate session titles. Leave empty to disable.",
+ "titleModelDescription": "Pick a lightweight model to automatically title conversations. Leave empty to disable.",
"titleModelPlaceholder": "Disabled (no auto title)",
"searchProvider": "Web Search",
"searchProviderPlaceholder": "Select web search",
@@ -1166,11 +1309,11 @@
"memoryProviderPlaceholder": "Select memory provider (disabled if empty)",
"memoryModePreview": "Selected built-in mode: {mode}",
"sparseStatusTitle": "Sparse Retrieval Status",
- "sparseStatusHint": "Markdown files remain the only source of truth. Manual sync rebuilds Qdrant from entries under /data/memory.",
+ "sparseStatusHint": "Markdown files are the source of truth. Syncing rebuilds the Qdrant index from /data/memory.",
"denseStatusTitle": "Dense Retrieval Status",
- "denseStatusHint": "Markdown files remain the only source of truth. Manual sync rebuilds the dense Qdrant index from entries under /data/memory.",
+ "denseStatusHint": "Markdown files are the source of truth. Syncing rebuilds the dense Qdrant index from /data/memory.",
"mem0StatusTitle": "Mem0 Sync Status",
- "mem0StatusHint": "Markdown files remain the only source of truth. Manual sync rebuilds managed Mem0 memories from entries under /data/memory.",
+ "mem0StatusHint": "Markdown files are the source of truth. Syncing rebuilds Mem0 memories from /data/memory.",
"indexedMemoryStatusPendingSave": "Save the selected memory provider before viewing indexed memory status or running a sync.",
"memorySyncAction": "Manual Sync",
"memorySyncSuccess": "Sync completed: {fsCount} source entries, {restoredCount} restored, {storageCount} indexed.",
@@ -1211,20 +1354,22 @@
"compactionDescription": "Automatically summarize older messages when context gets too large",
"compactionThreshold": "Compaction Threshold (input tokens)",
"compactionRatio": "Compaction Ratio (%)",
- "compactionRatioDescription": "Percentage of older messages to compact. The remaining recent messages are kept intact.",
+ "compactionRatioDescription": "The percentage of older messages to summarize. Recent messages are kept intact.",
"compactionModel": "Compaction Model",
"compactionModelDescription": "Select a model for summarization. Defaults to the bot's chat model if not set.",
"compactionModelPlaceholder": "Use chat model (default)",
"showToolCallsInIM": "Show Tool Calls in IM",
- "showToolCallsInIMDescription": "Surface tool execution status (running / completed / failed) as a single message in IM channels. Off by default.",
+ "showToolCallsInIMDescription": "Show live tool execution status (running / complete / failed) directly in the chat. Disabled by default.",
"displayEnabled": "Enable Workspace Display",
- "displayEnabledDescription": "Start Xvnc when the container starts. Save and restart the workspace container for this to take effect.",
+ "displayEnabledDescription": "Launch Xvnc alongside the container. Restart the workspace for this to take effect.",
"desktopEnabled": "Desktop",
- "desktopEnabledDescription": "Enable the workspace VNC desktop. If runtime packages are missing, Memoh will prepare Debian/Ubuntu or Alpine workspaces when the desktop is opened.",
+ "desktopEnabledDescription": "Enable the VNC desktop. Memoh will automatically provision Debian/Ubuntu or Alpine workspaces if missing.",
"toolApproval": "Tool Call Approval",
"toolApprovalDescription": "Require human approval for sensitive write, edit, and exec tool calls, with bypass templates for safe paths or commands.",
"toolApprovalBypass": "Bypass",
"toolApprovalMustReview": "Must review",
+ "botStatusTitle": "Bot Status",
+ "botStatusSubtitle": "Current workspace container and base network info.",
"networkPageTitle": "Network",
"networkPageSubtitle": "Workspace network status and SD-WAN settings.",
"networkStatusEmpty": "No status fields to display.",
@@ -1233,6 +1378,7 @@
"overlayProviderFieldLabel": "Connection type",
"overlayProviderPlaceholder": "Select a solution (turn off to skip SD-WAN)",
"overlayProviderRequired": "Choose a connection type before enabling.",
+ "overlayPrimaryConfigTitle": "Primary Configuration",
"networkStatusPendingSaveTitle": "Pending Save",
"networkStatusPendingSave": "Network settings changed. Save before checking the current status.",
"networkWorkspaceStateLabel": "State",
@@ -1260,7 +1406,7 @@
"networkStatusExitNode": "Exit Node",
"networkNeedsLoginDescription": "Authentication required. Open the link below to log in to your SD-WAN provider.",
"networkOpenLoginPage": "Open Login Page",
- "networkNeedsLoginHint": "After completing login in your browser, return here and refresh the status.",
+ "networkNeedsLoginHint": "Once logged in via your browser, return here to refresh.",
"networkLogout": "Log Out",
"networkLogoutSuccess": "Logged out successfully.",
"networkLogoutFailed": "Logout failed.",
@@ -1282,6 +1428,8 @@
"searchModel": "Search models…",
"noModel": "No models available",
"saveSuccess": "Settings saved",
+ "saveOnly": "Save without Enabling",
+ "saveAndEnable": "Save and Enable",
"save": "Save Settings",
"dangerZone": "Danger Zone",
"deleteBotDescription": "Deleting this bot cannot be undone. Proceed with caution.",
@@ -1299,46 +1447,46 @@
"blacklistModeDescription": "Allow everyone by default, then block the entries on the blacklist.",
"blacklistModeHint": "Default is allow. New entries are added to the blacklist.",
"whitelistMode": "Whitelist Mode",
- "whitelistModeDescription": "Block everyone by default, then allow only the entries on the whitelist.",
+ "whitelistModeDescription": "Block everyone except those you explicitly allow.",
"whitelistModeHint": "Default is deny. New entries are added to the whitelist.",
"blacklistTitle": "Blacklist",
- "blacklistDescription": "Entries on this list are blocked.",
+ "blacklistDescription": "Anyone on this list is blocked.",
"whitelistTitle": "Whitelist",
- "whitelistDescription": "Only entries on this list are allowed.",
+ "whitelistDescription": "Only people on this list get through.",
"addBlacklistEntry": "Add to Blacklist",
"addWhitelistEntry": "Add to Whitelist",
- "blacklistEmpty": "Blacklist is empty",
- "blacklistEmptyDescription": "No additional blocks. Messages not matched by other rules are allowed.",
- "whitelistEmpty": "Whitelist is empty",
- "whitelistEmptyDescription": "No allowed entries yet. Messages not matched by other rules are blocked.",
+ "blacklistEmpty": "Blacklist Is Empty",
+ "blacklistEmptyDescription": "No blocks active. Anyone not matched by other rules is allowed.",
+ "whitelistEmpty": "Whitelist Is Empty",
+ "whitelistEmptyDescription": "No allowed entries yet. Anyone not matched by other rules is blocked.",
"blacklistPreview": "Add {target} to the blacklist.",
"whitelistPreview": "Add {target} to the whitelist.",
- "platformQuestion": "Which platform does this entry apply to?",
- "userQuestion": "Which user does this entry apply to?",
- "allPlatforms": "All platforms",
- "allUsers": "All users",
+ "platformQuestion": "Which Platform Is This For?",
+ "userQuestion": "Which User Does This Apply To?",
+ "allPlatforms": "All Platforms",
+ "allUsers": "All Users",
"searchPlatform": "Search platforms",
"noPlatformCandidates": "No platforms available",
"platformTargetPreview": "all {platform} users",
"platformUserTargetPreview": "{user} on {platform}",
"userTargetPreview": "user {user}",
- "previewScopeAny": "for all chats",
- "previewScopePrivate": "only in private chats",
- "previewScopeGroup": "only in groups",
- "previewScopeThread": "only in threads",
- "previewScopeSpecific": "only in the selected conversation",
+ "previewScopeAny": "In All Chats",
+ "previewScopePrivate": "Only In DMs",
+ "previewScopeGroup": "Only In Groups",
+ "previewScopeThread": "Only In Threads",
+ "previewScopeSpecific": "Only In The Selected Chat",
"effectAllow": "Allow",
"effectDeny": "Deny",
"rulesTitle": "Rules",
"addRule": "Add Rule",
"editRule": "Edit Rule",
- "rulesEmpty": "No rules",
- "rulesEmptyDescription": "Add a rule to control access beyond the default effect.",
+ "rulesEmpty": "No Rules",
+ "rulesEmptyDescription": "Add a rule to override the default behavior.",
"enabled": "Enabled",
- "effect": "Effect",
- "matchTarget": "Match Target",
- "targetQuestion": "Who does this list entry apply to?",
- "scopeQuestion": "Where should it take effect?",
+ "effect": "Action",
+ "matchTarget": "Applies To",
+ "targetQuestion": "Who Does This Apply To?",
+ "scopeQuestion": "Where Should It Work?",
"subjectAll": "All",
"subjectChannelType": "Platform",
"subjectChannelIdentity": "User",
@@ -1358,49 +1506,49 @@
"ruleDisabled": "Disabled",
"enableRule": "Enable",
"disableRule": "Disable",
- "saveOnly": "Save without Enabling",
+ "saveOnly": "Save",
"saveAndEnable": "Save and Enable",
"saveFailed": "Failed to save",
- "deleteSuccess": "Rule deleted",
- "deleteFailed": "Failed to delete rule",
- "anyConversationScope": "Any chat scope",
+ "deleteSuccess": "Deleted",
+ "deleteFailed": "Failed to delete",
+ "anyConversationScope": "Anywhere",
"chatScope": "Chat Scope",
- "chatScopeDescription": "Choose which chat contexts this list entry applies to.",
+ "chatScopeDescription": "Choose where this rule applies.",
"chatScopeAny": "All chats",
- "specificConversationTitle": "Limit to one specific chat",
- "specificConversationDescription": "Usually unnecessary. Use this only when the entry should apply to one group, private chat, or thread.",
- "sourceChannel": "Source Platform",
- "anyChannel": "Any platform",
- "conversationType": "Conversation Type",
- "anyConversationType": "Any conversation type",
- "privateConversationType": "Private chats only",
- "groupConversationType": "Groups only",
- "threadConversationType": "Threads only",
- "allowPrivateConversation": "Allow private chats",
- "allowGroupConversation": "Allow groups",
- "allowThreadConversation": "Allow threads",
- "denyPrivateConversation": "Block private chats",
- "denyGroupConversation": "Block groups",
- "denyThreadConversation": "Block threads",
- "privateConversationGroup": "Private Chats",
+ "specificConversationTitle": "Limit to a Specific Chat",
+ "specificConversationDescription": "Most people don't need this. Use it only if you want to target a single group, DM, or thread.",
+ "sourceChannel": "Platform",
+ "anyChannel": "Any Platform",
+ "conversationType": "Type",
+ "anyConversationType": "Any Type",
+ "privateConversationType": "DMs Only",
+ "groupConversationType": "Groups Only",
+ "threadConversationType": "Threads Only",
+ "allowPrivateConversation": "Allow DMs",
+ "allowGroupConversation": "Allow Groups",
+ "allowThreadConversation": "Allow Threads",
+ "denyPrivateConversation": "Block DMs",
+ "denyGroupConversation": "Block Groups",
+ "denyThreadConversation": "Block Threads",
+ "privateConversationGroup": "DMs",
"groupConversationGroup": "Groups",
"threadConversationGroup": "Threads",
- "unknownConversationGroup": "Other Conversations",
- "conversationSource": "Conversation",
- "existingConversation": "Existing Conversation",
- "selectConversationSource": "Search or select a conversation",
- "searchConversationSource": "Search conversations",
- "noObservedConversations": "No matching conversations in history yet. Use manual IDs below, or ensure this bot has messages in those chats (including private).",
- "manualConversationIds": "Can't find it? Enter IDs manually",
- "manualConversationIdsHint": "Use this only when the target is missing from history. Copy the raw conversation ID and thread ID from the platform.",
- "pickTargetForConversationSearch": "Choose a platform or user first, then pick from existing conversations.",
- "pickIdentityForConversationSearch": "Choose a user above to search conversations observed for this bot.",
- "pickChannelTypeForConversationSearch": "Choose a platform above to search conversations this bot has seen on that platform.",
+ "unknownConversationGroup": "Other",
+ "conversationSource": "Chat",
+ "existingConversation": "Known Chats",
+ "selectConversationSource": "Find a Conversation",
+ "searchConversationSource": "Search chats",
+ "noObservedConversations": "We haven't seen any conversations matching this yet. You can enter IDs manually below, or wait for the bot to show up in those chats.",
+ "manualConversationIds": "Enter IDs Manually",
+ "manualConversationIdsHint": "Only use this if you can't find the chat in history. You'll need to grab the IDs directly from the platform.",
+ "pickTargetForConversationSearch": "Choose a platform or user first to see their conversations.",
+ "pickIdentityForConversationSearch": "Pick a user to search their chat history.",
+ "pickChannelTypeForConversationSearch": "Pick a platform to search its chat history.",
"conversationId": "Conversation ID",
- "conversationIdPlaceholder": "Enter conversation ID",
+ "conversationIdPlaceholder": "Enter ID",
"threadId": "Thread ID",
"threadIdPlaceholder": "Enter thread ID",
- "clearSpecificConversation": "Clear Specific Conversation",
+ "clearSpecificConversation": "Clear Selection",
"lastObserved": "Last seen"
},
"channels": {
@@ -1464,6 +1612,8 @@
}
},
"memory": {
+ "unsavedChanges": "Unsaved changes",
+ "emptyHistory": "No history available.",
"title": "Here lie the memories.",
"files": "Memory Files",
"empty": "No memory entries found.",
@@ -1511,8 +1661,8 @@
"discoverySaveSuccess": "Skill paths saved",
"discoverySaveFailed": "Failed to save skill paths",
"addSkill": "New Skill",
- "emptyTitle": "No Skills",
- "emptyDescription": "Click above to create a new skill",
+ "emptyTitle": "No Active Skills",
+ "emptyDescription": "Create a managed skill or scan external paths to get started.",
"managedBadge": "Managed",
"discoveredBadge": "External",
"effectiveBadge": "Effective",
@@ -1524,7 +1674,7 @@
"descriptionPlaceholder": "Enter skill description",
"content": "Content",
"contentPlaceholder": "Enter skill content/prompt",
- "deleteConfirm": "Are you sure you want to delete this skill?",
+ "deleteConfirm": "Permanently delete this managed skill?",
"overrideTitle": "Edit to create a managed copy",
"adoptAction": "Copy to Managed Path",
"adoptBlocked": "A managed copy already exists",
@@ -1541,7 +1691,8 @@
"deleteFailed": "Failed to delete skill",
"saveSuccess": "Skill saved",
"saveFailed": "Failed to save skill",
- "loadFailed": "Failed to load skills"
+ "loadFailed": "Failed to load skills",
+ "intro": "Configure custom abilities for this bot. Managed skills take precedence."
},
"compaction": {
"title": "Compaction Logs",
@@ -1577,58 +1728,65 @@
"statusAlert": "Alert",
"statusError": "Error",
"filterAll": "All",
- "noResult": "—"
+ "noResult": "—",
+ "description": "Heartbeat allows the bot to periodically scan for items needing attention, ensuring tasks are processed even when not directly messaged.",
+ "filterEmpty": "No logs matching the selected status filter."
},
"schedule": {
- "title": "Scheduled Tasks",
- "loadFailed": "Failed to load schedules",
- "empty": "No scheduled tasks",
+ "title": "Schedule",
+ "subtitle": "Configure automated tasks. Use the visual builder or cron expressions for precise control.",
+ "loadFailed": "Load failed",
+ "empty": "No tasks scheduled",
"name": "Name",
"pattern": "Pattern",
"enabled": "Enabled",
"calls": "Calls",
"createdAt": "Created",
"updatedAt": "Updated",
- "statusEnabled": "Enabled",
- "statusDisabled": "Disabled",
- "unlimited": "∞",
+ "statusEnabled": "Active",
+ "statusDisabled": "Inactive",
+ "unlimited": "Unlimited",
"actions": "Actions",
- "create": "New Schedule",
- "edit": "Edit",
+ "create": "New Task",
+ "edit": "Edit Task",
"delete": "Delete",
- "deleteConfirm": "Delete schedule \"{name}\"? This cannot be undone.",
- "deleteSuccess": "Schedule deleted",
- "deleteFailed": "Failed to delete schedule",
- "saveSuccess": "Schedule saved",
- "saveFailed": "Failed to save schedule",
+ "deleteConfirm": "Delete task \"{name}\"? This cannot be undone.",
+ "deleteSuccess": "Task deleted",
+ "deleteFailed": "Delete failed",
+ "saveSuccess": "Task saved",
+ "saveFailed": "Save failed",
+ "dangerZoneDesc": "Task deletion is permanent. Proceed with caution.",
"form": {
- "name": "Name",
- "namePlaceholder": "e.g. Morning brief",
+ "name": "Task Name",
+ "namePlaceholder": "e.g. Daily Briefing",
"description": "Description",
- "descriptionPlaceholder": "What this schedule does",
- "command": "Instruction",
- "commandPlaceholder": "Tell the bot what to do when this fires",
- "commandHint": "This will be delivered to the bot as a message each time the schedule triggers.",
+ "descriptionPlaceholder": "What this task does",
+ "command": "Command",
+ "commandPlaceholder": "Instruction to execute",
+ "commandHint": "This command is sent to the bot as a message upon triggering.",
"pattern": "Schedule",
"mode": "Mode",
- "everyMinutes": "Every N minutes (1-59)",
- "atMinute": "At minute of each hour (0-59)",
+ "everyMinutes": "Every N mins",
+ "atMinute": "At specific minute",
"hour": "Hour",
"hours": "Hours",
- "hoursHint": "Click to select one or more hours of the day.",
+ "hoursHint": "Select hours of the day.",
"minute": "Minute",
- "weekdays": "Days of week",
- "monthDays": "Days of month",
+ "weekdays": "Weekdays",
+ "monthDays": "Month days",
"month": "Month",
"monthDay": "Day",
- "maxCalls": "Run limit",
- "maxCallsUnlimited": "Unlimited",
- "enabled": "Enabled",
- "patternPreview": "Cron pattern",
+ "maxCalls": "Run Limit",
+ "maxCallsUnlimited": "No limit",
+ "enabled": "Enable Task",
+ "visualBuilder": "Visual Builder",
+ "cronCode": "Cron Expression",
+ "manualEditHint": "Manual edits will sync with the visual builder.",
+ "patternPreview": "Preview Pattern",
"nextRuns": "Next runs ({tz})",
- "invalidPattern": "Pattern is invalid",
- "advancedPattern": "Cron expression",
- "advancedHint": "Standard cron: minute hour day-of-month month day-of-week. Descriptors like @daily are also accepted."
+ "invalidPattern": "Invalid pattern",
+ "advancedPattern": "Cron Expression",
+ "advancedHint": "Supports standard Cron format and @daily descriptors."
},
"mode": {
"minutes": "Every N minutes",
diff --git a/apps/web/src/i18n/locales/zh.json b/apps/web/src/i18n/locales/zh.json
index e2183bee3..356daf782 100644
--- a/apps/web/src/i18n/locales/zh.json
+++ b/apps/web/src/i18n/locales/zh.json
@@ -13,7 +13,13 @@
"operation": "操作",
"enable": "启用",
"optional": "可选",
- "advanced": "高级选项",
+ "allOptional": "全部可选",
+ "placeholderPrefix": "比如 {example}",
+ "advanced": "高级",
+ "primary": "主要",
+ "format": "格式化",
+ "dangerZone": "危险区域",
+ "viewAll": "查看全部",
"import": "导入",
"export": "导出",
"copy": "复制",
@@ -27,12 +33,18 @@
"batchDeleteConfirm": "确定删除选中的 {count} 项?",
"batchExport": "批量导出",
"cancelSelection": "取消选择",
+ "updatedAt": "更新时间",
+ "actions": "操作",
+ "enabled": "已启用",
+ "disabled": "已禁用",
"name": "名称",
"namePlaceholder": "输入名称",
"type": "类型",
"typePlaceholder": "选择类型",
"refresh": "刷新",
"status": "状态",
+ "active": "启用",
+ "inactive": "未启用",
"loadFailed": "加载失败",
"saveFailed": "保存失败",
"createdAt": "创建时间",
@@ -768,15 +780,105 @@
"callbackUrl": "回调地址",
"callbackUrlHint": "请在 OAuth 应用设置中填入此回调地址。",
"callbackMissingParams": "缺少授权码或状态参数"
- }
+ },
+ "servers": "服务器",
+ "addNew": "添加服务器",
+ "searchServers": "搜索服务器...",
+ "unnamedServer": "未命名服务器",
+ "untitled": "无标题",
+ "unsavedChangesTitle": "未保存更改",
+ "verifyingCancel": "取消",
+ "discardDraftConfirm": "确定要放弃当前草稿吗?",
+ "discard": "放弃草稿",
+ "invalidConfig": "配置无效",
+ "handshakeError": "连接失败",
+ "viewRawLog": "查看原始日志",
+ "identity": "身份标识",
+ "placeholders": {
+ "name": "例如:天气 API",
+ "url": "https://...",
+ "envKey": "键",
+ "envValue": "值",
+ "headerKey": "请求头",
+ "headerValue": "值"
+ },
+ "transportType": "传输方式",
+ "payload": "传输配置",
+ "endpointUrl": "服务地址",
+ "streamProtocol": "流协议",
+ "protocol": {
+ "http": "HTTP",
+ "sse": "SSE"
+ },
+ "advancedSettings": "高级设置",
+ "advancedSettingsHint": "配置环境变量、请求头及 OAuth。",
+ "expand": "展开",
+ "collapse": "收起",
+ "envVars": "环境变量",
+ "httpHeaders": "HTTP 请求头",
+ "notConfigured": "未配置",
+ "discoveredTools": "已发现的工具",
+ "noToolsExposed": "该服务器未暴露任何工具。",
+ "more": "更多",
+ "dangerZoneHint": "永久删除此服务器配置。",
+ "importSandbox": "导入配置",
+ "pathCopied": "路径已复制",
+ "blindImport": "导入",
+ "allTools": "全部工具",
+ "searchTools": "搜索工具...",
+ "noDescription": "暂无描述。",
+ "noToolsMatch": "未找到匹配的工具。",
+ "diagnosticLog": "诊断日志",
+ "noLog": "暂无诊断信息。",
+ "copyLog": "复制日志",
+ "editValue": "编辑 {value}",
+ "editLongTextHint": "在此处输入或修改较长的配置值。",
+ "enterContent": "请输入内容...",
+ "unsavedChangesDesc": "你有未保存的更改,要放弃它们并切换吗?",
+ "keepEditing": "继续编辑",
+ "discardAndSwitch": "放弃并切换"
},
"home": {
"title": "首页"
},
"bots": {
"toolApproval": {
+ "posture": {
+ "title": "安全态势",
+ "hardened": "已加固",
+ "description": "审核策略正在积极拦截越权行为。"
+ },
+ "metrics": {
+ "activeRules": "生效规则",
+ "totalDefined": "已定义总数",
+ "blockedCount": "拦截次数",
+ "sessionTrust": "会话信任"
+ },
+ "recentActivity": "近期活动",
+ "trust": "信任",
+ "actions": {
+ "trustCall": "信任此调用",
+ "trustDir": "信任此目录"
+ },
+ "noActivity": "暂无近期活动。",
+ "warnings": {
+ "disabled": "工具审核目前已关闭。",
+ "breachRisk": "重置将清空所有自定义的安全规则。"
+ },
+ "restoreSecurity": "启用工具审核",
+ "examples": "示例",
+ "status": {
+ "active": "生效中",
+ "implicitDeny": "默认拒绝",
+ "sealed": "已封锁"
+ },
+ "dangerZone": "危险操作",
+ "dangerZoneDesc": "管理核心安全策略。",
+ "resetDefaults": "恢复默认设置",
+ "confirmReset": "确定要将所有工具的审核规则恢复到初始状态吗?",
+ "resetWarningExtra": "这将丢失你添加的所有白名单和黑名单。",
"title": "工具调用审核",
- "intro": "Bot 在容器内执行写入、修改文件或运行命令前,可以要求人工审核。下方为每类敏感工具单独配置规则——白名单内自动放行,黑名单强制审核。",
+ "intro": "在 Bot 修改文件或运行命令前进行拦截审核。为不同工具配置独立规则:白名单自动放行,黑名单强制审核。",
"tools": {
"write": "在容器内创建新文件",
"edit": "修改容器内已存在的文件",
@@ -798,7 +900,7 @@
"title": "Bots",
"searchPlaceholder": "搜索 Bot…",
"createBot": "新建 Bot",
- "createBotWaitHint": "首次创建时可能需要拉取基础镜像,提交后请耐心等待片刻。",
+ "createBotWaitHint": "首次创建可能需要拉取基础镜像,请耐心等待。",
"createBotSuccess": "Bot 创建成功。",
"steps": {
"basicInfo": "基本信息",
@@ -823,7 +925,7 @@
},
"localWorkspacePath": "本地工作区文件夹",
"localWorkspacePathPlaceholder": "选择这台电脑上的文件夹",
- "localWorkspaceWarning": "Local 工作区会以 server 用户权限访问宿主文件和执行命令。",
+ "localWorkspaceWarning": "Local 工作区将直接以服务器用户权限运行,具有操作宿主机文件与执行命令的完整权限。",
"editBot": "编辑 Bot",
"deleteConfirm": "确定要删除这个 Bot 吗?",
"renameSuccess": "Bot 名称已更新",
@@ -840,9 +942,9 @@
"timezoneInherited": "继承用户或系统时区",
"timezoneInheritedHint": "留空则继承用户时区,若用户未设置则回退到系统时区。",
"aclPreset": "安全策略",
- "aclPresetDescription": "创建时选择一个常见 ACL 场景,后续仍可在访问控制中继续微调。",
+ "aclPresetDescription": "选择初始的访问控制预设,后续可随时调整。",
"aclPresetHint": "建议:个人助手用“仅私聊”,群机器人用“仅群聊”或“群聊和话题”,不确定时保留“允许全部”。",
- "aclPresetHelp": "创建时会按所选策略初始化 ACL 默认行为和预设规则,后续仍可在访问控制页面修改。",
+ "aclPresetHelp": "这会配置默认的访问规则。你可以随时在“访问控制”面板中修改。",
"aclPresets": {
"allowAll": {
"title": "允许全部",
@@ -887,6 +989,22 @@
"deleteFailed": "删除失败"
},
"checks": {
+ "lastSync": "上次同步",
+ "statusTitle": "健康检查",
+ "status": {
+ "issue": "需要关注",
+ "stable": "运行正常",
+ "ok": "正常",
+ "warn": "警告",
+ "error": "错误",
+ "unknown": "未知"
+ },
+ "vitalityTitle": "活跃度",
+ "vitalityUnit": "次事件",
+ "diagnosticTitle": "诊断信息",
+ "diagnosticSubtitle": "实时系统诊断指标。",
+ "expandAll": "全部展开",
+ "collapse": "收起",
"title": "运行时检查",
"subtitle": "查看当前健康状态与异常详情。",
"ok": "无异常",
@@ -910,15 +1028,10 @@
"containerTask": "容器任务",
"containerDataPath": "容器数据路径",
"botDelete": "Bot 删除"
- },
- "status": {
- "ok": "正常",
- "warn": "警告",
- "error": "错误",
- "unknown": "未知"
}
},
"tabs": {
+ "overviewSubtitle": "系统健康概览与核心指标。",
"overview": "概览",
"general": "通用",
"desktop": "桌面",
@@ -940,32 +1053,44 @@
"settings": "设置"
},
"desktop": {
- "runtimeTitle": "运行环境",
+ "title": "桌面环境",
+ "subtitle": "管理虚拟显示器与交互会话。",
+ "groupInfrastructure": "基础架构",
+ "groupEnvironment": "运行环境",
+ "groupApplication": "功能集成",
+ "runtimeTitle": "运行状态",
"runtimeButton": "运行环境",
- "liveTitle": "桌面 1",
- "liveDescription": "主工作区桌面实时画面。",
- "previewTitle": "其他桌面",
- "previewDescription": "已连接的会话会以截图形式显示在这里。",
- "previewEmpty": "等待截图",
+ "liveTitle": "主显示器",
+ "liveDescription": "工作区桌面的实时预览。",
+ "previewTitle": "活动会话",
+ "previewDescription": "其他已连接会话的实时截图。",
+ "previewEmpty": "无预览",
"sessionsTitle": "会话",
- "summaryDisabled": "桌面未启用",
- "summaryReady": "桌面已就绪",
- "summaryPreparing": "打开窗口时会准备桌面运行环境",
+ "summaryDisabled": "已禁用",
+ "summaryReady": "正在运行",
+ "summaryPreparing": "正在准备环境...",
+ "statusReady": "已就绪",
+ "statusNotReady": "未就绪",
+ "statusRunning": "正在运行",
+ "statusStopped": "已停止",
"enabled": "已启用",
"runtime": "运行环境",
"vnc": "VNC",
"desktop": "桌面",
"browser": "浏览器",
- "toolkit": "Toolkit",
+ "toolkit": "工具箱",
"system": "系统",
"session": "会话",
"state": "状态",
"codec": "编码",
- "createdAt": "创建时间",
+ "createdAt": "启动时间",
"actions": "操作",
- "noSessions": "没有其他桌面会话",
- "closeSession": "关闭会话",
- "closeFailed": "关闭桌面会话失败",
+ "noSessions": "无活动会话",
+ "closeSession": "终止",
+ "closeSessionConfirm": "确认终止会话?",
+ "closeFailed": "终止会话失败",
+ "desktopEnabledSuccess": "桌面环境已开启",
+ "desktopDisabledSuccess": "桌面环境已关闭",
"unknown": "未知"
},
"terminal": {
@@ -1037,32 +1162,32 @@
"sentAt": "发送时间"
},
"container": {
- "title": "容器管理",
- "subtitle": "管理当前 Bot 对应的运行容器。",
- "botNotReady": "当前 Bot 正在生命周期变更中,暂时不可操作容器。",
- "empty": "当前 Bot 尚未创建容器,创建后可启用运行环境能力。",
- "legacyWarning": "当前容器使用旧版架构,需要重建以获得完整兼容性。重建时数据会自动保留。",
- "legacyRecreate": "重建容器",
- "legacyRecreateSuccess": "容器重建成功",
- "createHint": "容器会基于当前镜像创建;如你显式开启恢复,则会在创建后尝试恢复已保留的数据。",
+ "title": "容器",
+ "subtitle": "管理此 Bot 的运行环境。",
+ "botNotReady": "Bot 生命周期变更中,暂时无法操作容器。",
+ "empty": "尚未创建容器。创建后即可启用运行环境。",
+ "legacyWarning": "旧版架构。建议重建以获得完整兼容性(数据将自动保留)。",
+ "legacyRecreate": "重建",
+ "legacyRecreateSuccess": "容器已重建",
+ "createHint": "容器基于当前镜像创建。开启恢复可自动找回保留数据。",
"createRestoreDataLabel": "创建后恢复已保留数据",
- "createRestoreDataDescription": "如果存在之前导出的备份或旧版 bind mount 数据,将在容器创建后恢复到 `/data`。",
+ "createRestoreDataDescription": "导出的备份或旧版数据将在创建后自动恢复至 /data。",
"createImageLabel": "基础镜像",
- "createImageDescription": "作为容器基础环境的 Docker 镜像(如 debian:bookworm-slim、alpine:latest、ubuntu:24.04)。留空则使用默认镜像。",
+ "createImageDescription": "作为基础环境的 Docker 镜像(如 debian:bookworm-slim)。留空使用默认镜像。",
"createAdvancedTitle": "高级选项",
- "createAdvancedDescription": "配置该容器的可选 GPU 访问能力与原始 CDI 设备映射。",
+ "createAdvancedDescription": "配置 GPU 访问能力与 CDI 设备映射。",
"createGpuLabel": "启用 GPU",
- "createGpuDescription": "为新容器开启宿主机 GPU 访问。",
+ "createGpuDescription": "允许容器使用宿主机的 GPU。",
"createGpuDevicesLabel": "CDI 设备",
- "createGpuDevicesDescription": "每行或用逗号填写一个 CDI 设备名,例如 `nvidia.com/gpu=0` 或 `amd.com/gpu=0`。关闭 GPU 后会显式清空已保存的 GPU 偏好。",
+ "createGpuDevicesDescription": "每行或用逗号填写一个 CDI 设备名。关闭 GPU 后将清空已保存的偏好。",
"createGpuDevicesPlaceholder": "nvidia.com/gpu=0\namd.com/gpu=0",
"gpuDevicesRequired": "已启用 GPU 时,至少需要填写一个 CDI 设备名。",
"cdiDevicesEmpty": "未附加 GPU",
- "gpuRecreateHint": "GPU 配置变更需要重建容器后才会生效,单纯启动或停止不会更新当前已附加的设备。",
- "deleteConfirm": "确定要彻底删除这个容器吗?未保留的数据将无法恢复。",
- "deletePreserveConfirm": "确定要先导出 `/data` 再删除这个容器吗?",
- "restoreConfirm": "确定要将已保留的数据恢复到当前容器的 `/data` 吗?",
- "rollbackConfirm": "确定要回滚到这个快照版本吗?",
+ "gpuRecreateHint": "GPU 配置变更需要重建容器后生效,单纯启动或停止不会更新设备。",
+ "deleteConfirm": "确定要彻底删除此容器吗?未保留的数据将无法恢复。",
+ "deletePreserveConfirm": "确定要先导出 `/data` 再删除此容器吗?",
+ "restoreConfirm": "确定要将已保留的数据恢复到 `/data` 吗?",
+ "rollbackConfirm": "确定要回滚到此快照版本吗?",
"taskRunning": "运行中",
"taskStopped": "已停止",
"taskCompleted": "已完成",
@@ -1074,7 +1199,7 @@
"loadFailed": "加载容器信息失败",
"actionFailed": "容器操作失败",
"createSuccess": "容器创建成功",
- "createRestoreSuccess": "容器创建成功,已恢复数据",
+ "createRestoreSuccess": "容器创建成功,数据已恢复",
"startSuccess": "容器启动成功",
"stopSuccess": "容器停止成功",
"deleteSuccess": "容器删除成功",
@@ -1082,24 +1207,27 @@
"snapshotSuccess": "快照创建成功",
"exportSuccess": "数据导出成功",
"importSuccess": "数据导入成功",
- "restoreSuccess": "已恢复保留数据",
+ "restoreSuccess": "数据恢复成功",
"rollbackSuccess": "快照回滚成功",
"pullingImage": "正在拉取镜像...",
"creatingContainer": "正在创建容器...",
- "preservingData": "正在备份数据,数据量较大时可能需要一段时间...",
- "restoringData": "正在迁移数据,数据量较大时可能需要一段时间...",
+ "preservingData": "正在备份数据...",
+ "restoringData": "正在迁移数据...",
+ "lifecycleTitle": "生命周期",
+ "snapshotTitle": "快照管理",
+ "snapshotSubtitle": "保存或回滚容器运行状态。",
"snapshotEmpty": "暂无快照",
"snapshotLoadFailed": "加载快照失败",
- "snapshotNamePlaceholder": "快照显示名称(可选)",
- "snapshotNameHint": "这里只填写用户可见的显示名称,系统会自动生成内部快照名。",
+ "snapshotNamePlaceholder": "显示名称(可选)",
+ "snapshotNameHint": "用户可见的显示名称,系统将自动生成内部快照名。",
"metricsTitle": "资源状态",
- "metricsSubtitle": "查看当前容器的 CPU、内存与整个容器文件系统的存储使用情况。",
- "metricsLoadFailed": "加载容器资源状态失败",
- "metricsUnsupported": "当前容器后端暂不支持资源监控。",
- "metricsUnavailable": "当前暂无可用的资源指标。",
- "metricsStopped": "容器任务未运行,CPU 和内存指标暂不可用;如有存储信息仍会继续显示。",
+ "metricsSubtitle": "CPU、内存及存储使用情况。",
+ "metricsLoadFailed": "加载资源状态失败",
+ "metricsUnsupported": "当前后端不支持资源监控。",
+ "metricsUnavailable": "暂无可用指标。",
+ "metricsStopped": "容器未运行,仅显示存储使用情况。",
"metricsPath": "统计范围",
- "metricsUnlimited": "未配置内存限制",
+ "metricsUnlimited": "未配置限额",
"currentSample": "当前采样",
"sampledAt": "采样时间",
"metricsLabels": {
@@ -1108,24 +1236,25 @@
"storage": "存储"
},
"dataTitle": "数据操作",
- "dataSubtitle": "独立管理容器 `/data` 目录的导入、导出与恢复。",
+ "dataSubtitle": "管理 `/data` 目录的导入、导出与恢复。",
"deleteTitle": "删除容器",
- "deleteSubtitle": "删除容器前请明确选择是否先保留 `/data`,避免误删用户数据。",
- "preservedDataAvailable": "检测到可恢复的已保留数据,可直接恢复到当前容器。",
+ "deleteSubtitle": "请确认是否在删除前备份 /data。",
+ "deleteZoneDesc": "删除容器操作不可撤销,请谨慎操作。",
+ "preservedDataAvailable": "检测到可恢复的已保留数据。",
"preservedDataAvailableShort": "可恢复",
"preservedDataEmpty": "无",
"sourceManual": "手动创建",
"sourcePreExec": "执行前自动创建",
"sourceRollback": "回滚生成",
"fields": {
- "id": "容器 ID",
- "status": "容器状态",
- "task": "任务状态",
+ "id": "ID",
+ "status": "状态",
+ "task": "任务",
"namespace": "命名空间",
"image": "镜像",
"cdiDevices": "CDI 设备",
"hostPath": "主机路径",
- "containerPath": "容器路径",
+ "containerPath": "路径",
"preservedData": "保留数据",
"createdAt": "创建时间",
"updatedAt": "更新时间"
@@ -1139,22 +1268,36 @@
"actions": "操作"
},
"actions": {
- "create": "创建容器",
+ "create": "创建",
"start": "启动",
"stop": "停止",
- "delete": "彻底删除",
- "deletePreserve": "保留数据后删除",
- "snapshot": "创建快照",
- "exportData": "导出数据",
- "importData": "导入数据",
- "restoreData": "恢复保留数据",
+ "delete": "删除",
+ "deletePreserve": "保留并删除",
+ "snapshot": "创建",
+ "exportData": "导出",
+ "importData": "导入",
+ "restoreData": "恢复",
"rollback": "回滚"
}
},
"settings": {
+ "blocks": {
+ "context": "上下文与记忆",
+ "contextDescription": "配置该 Bot 记忆和处理信息的方式。",
+ "global": "全局设置",
+ "globalDescription": "Bot 的核心偏好配置。",
+ "interaction": "交互方式",
+ "interactionDescription": "配置 Bot 在对话中的行为习惯。",
+ "multimedia": "多媒体",
+ "multimediaDescription": "配置语音与图片生成等相关模型。"
+ },
+ "hideMemoryDetails": "隐藏详情",
+ "showMemoryDetails": "查看详情",
+ "chatLanguage": "语言",
+ "chatLanguagePlaceholder": "例如:English、zh-CN",
"chatModel": "对话模型",
"titleModel": "标题模型",
- "titleModelDescription": "选择一个小模型来自动生成会话标题。留空则禁用自动标题生成。",
+ "titleModelDescription": "选择用于自动生成会话标题的小模型。留空表示禁用该功能。",
"titleModelPlaceholder": "未启用(不自动生成标题)",
"searchProvider": "搜索提供方",
"searchProviderPlaceholder": "选择搜索提供方",
@@ -1162,12 +1305,12 @@
"memoryProviderPlaceholder": "选择记忆提供方(为空则禁用)",
"memoryModePreview": "当前内置模式:{mode}",
"sparseStatusTitle": "稀疏检索状态",
- "sparseStatusHint": "Markdown 文件是唯一可信源;手动同步会把 /data/memory 下的条目重新写入 Qdrant。",
+ "sparseStatusHint": "Markdown 文件是唯一可信源;手动同步将根据 /data/memory 重新构建 Qdrant 索引。",
"denseStatusTitle": "稠密检索状态",
- "denseStatusHint": "Markdown 文件是唯一可信源;手动同步会把 /data/memory 下的条目重新写入稠密 Qdrant 索引。",
+ "denseStatusHint": "Markdown 文件是唯一可信源;手动同步将根据 /data/memory 重建稠密 Qdrant 索引。",
"mem0StatusTitle": "Mem0 同步状态",
- "mem0StatusHint": "Markdown 文件是唯一可信源;手动同步会把 /data/memory 下托管的记忆条目重新同步到 Mem0。",
- "indexedMemoryStatusPendingSave": "请先保存当前记忆提供方选择,再查看索引状态或执行同步。",
+ "mem0StatusHint": "Markdown 文件是唯一可信源;手动同步将把 /data/memory 中的条目重新同步至 Mem0。",
+ "indexedMemoryStatusPendingSave": "请在查看索引状态或执行同步前,先保存所选的记忆提供方。",
"memorySyncAction": "手动同步",
"memorySyncSuccess": "同步完成:源条目 {fsCount} 条,修复 {restoredCount} 条,索引现有 {storageCount} 条。",
"memorySyncFailed": "手动同步失败",
@@ -1196,41 +1339,44 @@
"reasoningEffortLow": "低",
"reasoningEffortMedium": "中",
"reasoningEffortHigh": "高",
- "reasoningEffortXHigh": "超高",
+ "reasoningEffortXHigh": "极高",
"heartbeatEnabled": "启用心跳",
- "heartbeatDescription": "定期触发 Agent 检查是否有需要关注的事项",
+ "heartbeatDescription": "定期唤醒 Agent,检查是否有需要处理的事务。",
"heartbeatInterval": "心跳间隔(分钟)",
"heartbeatModel": "心跳模型",
"heartbeatModelDescription": "选择心跳检查使用的模型,未设置时默认使用聊天模型。",
"heartbeatModelPlaceholder": "使用聊天模型(默认)",
"compactionEnabled": "启用上下文压缩",
- "compactionDescription": "上下文过大时自动摘要旧消息以节省 token",
+ "compactionDescription": "当对话上下文过长时,自动对旧消息进行摘要以节省 Token。",
"compactionThreshold": "压缩阈值(输入 token 数)",
"compactionRatio": "压缩比例(%)",
- "compactionRatioDescription": "压缩较旧消息的百分比,剩余的最近消息保持原始完整度。",
+ "compactionRatioDescription": "指定需要压缩的旧消息比例,最近的消息将保持原样。",
"compactionModel": "压缩模型",
"compactionModelDescription": "选择用于摘要的模型,未设置时默认使用聊天模型。",
"compactionModelPlaceholder": "使用聊天模型(默认)",
"showToolCallsInIM": "在 IM 中显示工具调用",
- "showToolCallsInIMDescription": "在 IM 频道中以单条消息持续展示工具执行的状态(进行中 / 已完成 / 失败)。默认关闭。",
+ "showToolCallsInIMDescription": "在聊天中以单条消息实时更新工具的执行状态。默认关闭。",
"displayEnabled": "启用工作区显示器",
- "displayEnabledDescription": "在容器启动时启动 Xvnc,保存后需重启工作区容器才会生效。",
+ "displayEnabledDescription": "随容器启动 Xvnc 服务。保存并重启容器后生效。",
"desktopEnabled": "桌面",
- "desktopEnabledDescription": "启用工作区 VNC 桌面。缺少运行环境时,Memoh 会在打开桌面时自动准备 Debian/Ubuntu 或 Alpine 工作区。",
+ "desktopEnabledDescription": "启用 VNC 桌面。若缺少环境,Memoh 会在打开时自动配置 Debian/Ubuntu 或 Alpine 工作区。",
"toolApproval": "工具调用审核",
- "toolApprovalDescription": "对 write、edit、exec 等敏感工具启用人工审核,可配置可跳过审核的路径或命令。",
+ "toolApprovalDescription": "拦截并人工审核 write、edit、exec 等敏感工具的调用。你可以配置免审核的白名单路径或命令。",
"toolApprovalBypass": "跳过审核",
"toolApprovalMustReview": "必须审核",
+ "botStatusTitle": "Bot 运行状态",
+ "botStatusSubtitle": "当前工作区容器与基础网络环境信息。",
"networkPageTitle": "网络",
- "networkPageSubtitle": "工作区网络状态与 SD-WAN 相关设置。",
- "networkStatusEmpty": "暂无可用状态字段。",
+ "networkPageSubtitle": "查看网络状态并配置 SD-WAN。",
+ "networkStatusEmpty": "暂无可用状态。",
"networkSDWANSectionTitle": "SD-WAN",
- "networkSDWANSectionHint": "虚拟专网与出站能力。",
+ "networkSDWANSectionHint": "配置虚拟网络与出站流量。",
"overlayProviderFieldLabel": "接入方式",
- "overlayProviderPlaceholder": "选择方案(关闭开关可不使用 SD-WAN)",
+ "overlayProviderPlaceholder": "选择接入方案",
"overlayProviderRequired": "启用前请先选择接入方式。",
+ "overlayPrimaryConfigTitle": "主要配置",
"networkStatusPendingSaveTitle": "待保存",
- "networkStatusPendingSave": "网络配置已变更,保存后才能看到当前状态。",
+ "networkStatusPendingSave": "配置已更改,保存后同步状态。",
"networkWorkspaceStateLabel": "状态",
"networkWorkspaceContainerID": "容器 ID",
"networkWorkspaceTaskStatus": "任务状态",
@@ -1239,48 +1385,50 @@
"networkWorkspaceMessage": "说明",
"networkWorkspaceState": {
"workspace_missing": "尚未创建工作区容器",
- "runtime_unavailable": "无法查询容器任务(运行时未就绪)",
- "task_stopped": "工作区未运行或任务未启动",
- "network_target_ready": "工作区运行中,网络目标可用",
+ "runtime_unavailable": "运行时未就绪",
+ "task_stopped": "工作区未启动",
+ "network_target_ready": "工作区已运行,网络就绪",
"unknown": "未知"
},
- "networkActionFailed": "网络检测失败",
+ "networkActionFailed": "检测失败",
"networkStatusState": "状态",
"networkStatusIP": "Tailnet IP",
"networkStatusProxy": "代理地址",
"networkStatusPID": "进程 PID",
"networkStatusDNSName": "DNS 名称",
- "networkStatusBackendState": "Tailscale 后端状态",
+ "networkStatusBackendState": "后端状态",
"networkStatusHealth": "健康信息",
"networkStatusSocket": "LocalAPI Socket",
"networkStatusExitNode": "Exit Node",
- "networkNeedsLoginDescription": "需要身份认证。点击下方链接登录到 SD-WAN 提供商。",
- "networkOpenLoginPage": "打开登录页面",
- "networkNeedsLoginHint": "在浏览器中完成登录后,返回此页面刷新状态。",
+ "networkNeedsLoginDescription": "需要认证,请登录服务商授权。",
+ "networkOpenLoginPage": "前往登录",
+ "networkNeedsLoginHint": "登录完成后,返回此页刷新状态。",
"networkLogout": "退出登录",
- "networkLogoutSuccess": "已成功退出登录。",
- "networkLogoutFailed": "退出登录失败。",
+ "networkLogoutSuccess": "已退出登录。",
+ "networkLogoutFailed": "退出失败。",
"networkExitNode": "Exit Node",
- "networkExitNodeSectionHint": "通过 Tailscale Exit Node 路由所有出站流量,实现透明代理。",
+ "networkExitNodeSectionHint": "将出站流量路由至出口节点实现代理。",
"networkExitNodePlaceholder": "选择 Exit Node",
- "networkExitNodeDescription": "从当前接入方式返回的候选节点中选择一个出口节点。",
+ "networkExitNodeDescription": "从候选列表中选择出口节点。",
"networkExitNodeStatus": "节点状态",
"networkExitNodeAddresses": "节点地址",
"networkExitNodeOnline": "在线",
"networkExitNodeOffline": "离线",
- "networkExitNodeRequired": "透明出站必须选择一个 Exit Node。",
- "networkNodesPendingSave": "请先保存当前网络配置,再刷新节点列表。",
- "networkNodesEmpty": "当前没有可用的 Exit Node。请确认 Bot 工作区已运行且网络已连通。",
- "networkNodesRefreshFailed": "刷新 Exit Node 列表失败",
+ "networkExitNodeRequired": "必须选择一个 Exit Node。",
+ "networkNodesPendingSave": "刷新前请先保存网络配置。",
+ "networkNodesEmpty": "暂无可用节点。请确保网络已连通。",
+ "networkNodesRefreshFailed": "刷新节点列表失败",
"allowGuest": "ACL 默认行为",
- "allowGuestPersonalHint": "ACL 规则适用于所有类型的 Bot。",
+ "allowGuestPersonalHint": "ACL 规则将应用于所有类型的 Bot。",
"loopDetectionTitle": "自动检测并阻止模型循环输出",
"searchModel": "搜索模型…",
"noModel": "暂无可选模型",
"saveSuccess": "设置已保存",
+ "saveOnly": "保存但不启用",
+ "saveAndEnable": "保存并启用",
"save": "保存设置",
"dangerZone": "危险操作",
- "deleteBotDescription": "删除此 Bot 后无法恢复,请谨慎操作。",
+ "deleteBotDescription": "此操作不可逆。删除后 Bot 将无法恢复。",
"deleteBot": "删除 Bot"
},
"access": {
@@ -1292,25 +1440,25 @@
"modeDescription": "选择默认放行还是默认拦截。名单里的规则会覆盖默认模式。",
"defaultEffectSaved": "访问模式已更新",
"blacklistMode": "黑名单模式",
- "blacklistModeDescription": "默认允许所有消息触发 Bot,只拒绝黑名单中的对象。",
- "blacklistModeHint": "当前默认允许;新增条目会加入黑名单。",
+ "blacklistModeDescription": "只要没在名单里,谁都能用。",
+ "blacklistModeHint": "默认为允许。新条目将加入黑名单。",
"whitelistMode": "白名单模式",
- "whitelistModeDescription": "默认拒绝所有消息触发 Bot,只允许白名单中的对象。",
- "whitelistModeHint": "当前默认拒绝;新增条目会加入白名单。",
+ "whitelistModeDescription": "只有名单上的人能通过。",
+ "whitelistModeHint": "默认为拒绝。新条目将加入白名单。",
"blacklistTitle": "黑名单",
- "blacklistDescription": "名单中的对象会被拒绝。",
+ "blacklistDescription": "这个名单里的人都会被拦住。",
"whitelistTitle": "白名单",
- "whitelistDescription": "只有名单中的对象会被允许。",
+ "whitelistDescription": "只有这个名单里的人才会被允许。",
"addBlacklistEntry": "添加黑名单条目",
"addWhitelistEntry": "添加白名单条目",
"blacklistEmpty": "黑名单为空",
- "blacklistEmptyDescription": "当前没有额外拒绝项,所有未被其他规则命中的消息都会被允许。",
+ "blacklistEmptyDescription": "目前没设任何拦截规则。没被选中的人都能正常通过。",
"whitelistEmpty": "白名单为空",
- "whitelistEmptyDescription": "当前没有放行项,所有未被其他规则命中的消息都会被拒绝。",
- "blacklistPreview": "将 {target} 加入黑名单。",
- "whitelistPreview": "将 {target} 加入白名单。",
- "platformQuestion": "这条名单适用于哪个平台?",
- "userQuestion": "这条名单适用于哪个用户?",
+ "whitelistEmptyDescription": "还没添加放行的人。没在这份名单里的都会被拦截。",
+ "blacklistPreview": "把 {target} 加进黑名单。",
+ "whitelistPreview": "把 {target} 加进白名单。",
+ "platformQuestion": "这条规则在哪用?",
+ "userQuestion": "这条规则针对谁?",
"allPlatforms": "所有平台",
"allUsers": "所有用户",
"searchPlatform": "搜索平台",
@@ -1361,17 +1509,17 @@
"deleteFailed": "删除规则失败",
"anyConversationScope": "任何聊天范围",
"chatScope": "聊天范围",
- "chatScopeDescription": "选择这条名单规则适用于哪些聊天场景。",
+ "chatScopeDescription": "选一下这条规则在哪些场景生效。",
"chatScopeAny": "所有聊天",
- "specificConversationTitle": "只限制某个具体聊天",
- "specificConversationDescription": "一般不需要设置。只有想让这条名单只在某个群、私聊或话题里生效时再选择。",
- "sourceChannel": "来源平台",
+ "specificConversationTitle": "只针对某个具体聊天",
+ "specificConversationDescription": "大多数情况下不需要。除非你只想针对某一个特定的群、私聊或话题。",
+ "sourceChannel": "平台",
"anyChannel": "任意平台",
- "conversationType": "会话类型",
- "anyConversationType": "任意会话类型",
- "privateConversationType": "仅私聊",
- "groupConversationType": "仅群聊",
- "threadConversationType": "仅话题",
+ "conversationType": "类型",
+ "anyConversationType": "任意类型",
+ "privateConversationType": "只管私聊",
+ "groupConversationType": "只管群聊",
+ "threadConversationType": "只管话题",
"allowPrivateConversation": "允许私聊",
"allowGroupConversation": "允许群聊",
"allowThreadConversation": "允许话题",
@@ -1381,22 +1529,22 @@
"privateConversationGroup": "私聊",
"groupConversationGroup": "群聊",
"threadConversationGroup": "话题",
- "unknownConversationGroup": "其他会话",
+ "unknownConversationGroup": "其他",
"conversationSource": "会话",
- "existingConversation": "已有会话",
- "selectConversationSource": "搜索或选择会话",
- "searchConversationSource": "搜索会话",
- "noObservedConversations": "暂无符合的历史会话。可手动填写 ID,或确认该 Bot 在对应会话中已有消息(含私聊)。",
- "manualConversationIds": "找不到会话?手动填写 ID",
- "manualConversationIdsHint": "仅在历史会话列表没有目标时使用。请从平台复制原始会话 ID、话题 ID。",
- "pickTargetForConversationSearch": "请选择一个平台或用户后,再从已有会话中选择。",
- "pickIdentityForConversationSearch": "请先在上方选择用户,才能按历史记录搜索会话。",
- "pickChannelTypeForConversationSearch": "请先在上方选择平台,才能按该平台上的历史会话搜索。",
+ "existingConversation": "已知会话",
+ "selectConversationSource": "找个会话",
+ "searchConversationSource": "搜搜看",
+ "noObservedConversations": "还没在历史记录里找到匹配的聊天。你可以手动填下 ID,或者等 Bot 在那个频道里露个脸。",
+ "manualConversationIds": "找不到?手动填 ID",
+ "manualConversationIdsHint": "只有找不到聊天记录时才用这个。你需要从聊天平台里手动复制会话或话题 ID。",
+ "pickTargetForConversationSearch": "先选下平台或用户,然后再搜相关的会话。",
+ "pickIdentityForConversationSearch": "先选个用户,才能搜他的聊天历史。",
+ "pickChannelTypeForConversationSearch": "先选个平台,才能搜这个平台上的聊天历史。",
"conversationId": "会话 ID",
- "conversationIdPlaceholder": "输入会话 ID",
+ "conversationIdPlaceholder": "输入 ID",
"threadId": "话题 ID",
"threadIdPlaceholder": "输入话题 ID",
- "clearSpecificConversation": "清空指定会话",
+ "clearSpecificConversation": "清空选择",
"lastObserved": "最近出现"
},
"channels": {
@@ -1423,12 +1571,12 @@
"deleteSuccess": "平台已移除",
"deleteFailed": "移除平台失败",
"webhookCallback": "WebHook 回调地址",
- "webhookCallbackHint": "将该地址配置到对应平台控制台的 Webhook 回调 URL。",
- "webhookCallbackPending": "保存平台配置后会生成回调地址。",
+ "webhookCallbackHint": "请将此地址填入对应平台控制台的 Webhook 配置中。",
+ "webhookCallbackPending": "保存当前配置后即可生成回调地址。",
"showSecretField": "显示{field}",
"hideSecretField": "隐藏{field}",
- "feishuWebhookSecurityHint": "出于安全考虑,Webhook 模式必须配置 Encrypt Key 或 Verification Token 之一;未受保护的回调地址不应直接暴露在公网上。",
- "feishuWebhookSecretRequired": "出于安全考虑,请至少配置 Encrypt Key 或 Verification Token 之一。",
+ "feishuWebhookSecurityHint": "为了安全,使用 Webhook 模式时必须配置 Encrypt Key 或 Verification Token;不要将未受保护的回调地址直接暴露。",
+ "feishuWebhookSecretRequired": "为了安全,请至少配置 Encrypt Key 或 Verification Token 其中的一项。",
"noAvailableTypes": "所有平台类型均已配置",
"platformKey": "平台标识:{key}",
"weixinQr": {
@@ -1460,20 +1608,22 @@
}
},
"memory": {
+ "unsavedChanges": "有未保存的更改",
+ "emptyHistory": "暂无对话历史。",
"title": "所忆皆在此间",
"files": "记忆文件",
"empty": "暂无记忆条目",
"searchPlaceholder": "搜索记忆...",
"newMemory": "新建记忆",
"compact": "压缩记忆",
- "compactConfirm": "确定要压缩记忆吗?这会通过 AI 合并相似内容,可能会减少记忆条目数量。",
+ "compactConfirm": "确定要压缩记忆吗?系统将利用 AI 合并相似内容,这会减少记忆条目的总数。",
"compactRatio": "压缩率",
"compactRatioLight": "轻度 (0.8)",
"compactRatioMedium": "中度 (0.5)",
"compactRatioAggressive": "重度 (0.3)",
- "compactRatioLightDesc": "保留大部分细节,主要是去重。",
- "compactRatioMediumDesc": "合并相似事实,平衡压缩。",
- "compactRatioAggressiveDesc": "深度整合,仅保留核心事实。",
+ "compactRatioLightDesc": "保留绝大部分细节,主要进行去重处理。",
+ "compactRatioMediumDesc": "合并相似的事实,在细节与容量间保持平衡。",
+ "compactRatioAggressiveDesc": "深度压缩,剔除冗余并仅保留核心事实。",
"compactDecayDate": "以此日期之前的记忆会被优先压缩",
"compactSuccess": "记忆压缩成功",
"compactFailed": "记忆压缩失败",
@@ -1486,15 +1636,15 @@
"skills": {
"title": "技能",
"discoveryTitle": "技能路径",
- "discoveryDescription": "管理这个 Bot 的托管技能保存位置,以及会扫描哪些外部技能路径。",
+ "discoveryDescription": "配置该 Bot 的托管技能存放位置,并指定需要扫描的外部技能路径。",
"managedPathLabel": "托管路径",
- "managedPathDescription": "Memoh 托管技能会保存在这里。",
- "managedPathHint": "“复制到托管路径”会把外部技能复制到这里。托管副本会优先生效。",
+ "managedPathDescription": "所有由 Memoh 托管的技能文件都将存放在此。",
+ "managedPathHint": "“复制到托管路径”可将外部技能复制至此,执行时托管副本具有最高优先级。",
"discoveryPathsLabel": "外部技能路径",
- "discoveryPathsDescription": "Memoh 会扫描这些绝对路径中的兼容外部技能。每行填写一个路径。",
+ "discoveryPathsDescription": "Memoh 会自动扫描这些绝对路径下的可用外部技能。每行一个。",
"discoveryPathPlaceholder": "/root/.agents/skills",
"discoveryAddPath": "添加路径",
- "discoveryEmpty": "当前没有外部技能路径,仅会扫描托管技能和旧版技能。",
+ "discoveryEmpty": "目前未配置外部技能路径。仅扫描托管与旧版的内置技能。",
"discoveryDefaultHint": "默认外部路径:{paths}",
"discoveryReset": "重置",
"discoverySummaryDefault": "默认",
@@ -1502,13 +1652,13 @@
"discoverySummaryUnsaved": "有未保存修改",
"discoveryPathRequired": "路径不能为空",
"discoveryPathAbsolute": "路径必须是绝对路径",
- "discoveryPathReserved": "这个路径已被 Memoh 托管技能或旧版技能占用",
+ "discoveryPathReserved": "此路径已被 Memoh 托管技能或旧版技能使用。",
"discoveryPathDuplicate": "路径重复",
"discoverySaveSuccess": "技能路径已保存",
"discoverySaveFailed": "保存技能路径失败",
"addSkill": "新建技能",
- "emptyTitle": "暂无技能",
- "emptyDescription": "点击上方按钮创建新技能",
+ "emptyTitle": "技能库为空",
+ "emptyDescription": "请创建新的托管技能,或配置外部扫描路径以引入现有技能。",
"managedBadge": "托管",
"discoveredBadge": "外部",
"effectiveBadge": "生效中",
@@ -1520,8 +1670,8 @@
"descriptionPlaceholder": "输入技能描述",
"content": "内容",
"contentPlaceholder": "输入技能内容/提示词",
- "deleteConfirm": "确定要删除这个技能吗?",
- "overrideTitle": "编辑后将创建托管副本",
+ "deleteConfirm": "是否永久删除此托管技能?",
+ "overrideTitle": "编辑此技能将自动创建一份托管副本。",
"adoptAction": "复制到托管路径",
"adoptBlocked": "已有托管副本",
"disableAction": "禁用这个技能来源",
@@ -1532,12 +1682,13 @@
"disableFailed": "禁用技能失败",
"enableSuccess": "技能已启用",
"enableFailed": "启用技能失败",
- "shadowedBy": "被以下来源覆盖:",
+ "shadowedBy": "被以下规则覆盖:",
"deleteSuccess": "技能已删除",
"deleteFailed": "删除技能失败",
"saveSuccess": "技能已保存",
"saveFailed": "保存技能失败",
- "loadFailed": "加载技能失败"
+ "loadFailed": "加载技能失败",
+ "intro": "管理此机器人的专属技能。本地托管副本具有最高优先级。"
},
"compaction": {
"title": "压缩记录",
@@ -1573,58 +1724,65 @@
"statusAlert": "告警",
"statusError": "错误",
"filterAll": "全部",
- "noResult": "—"
+ "noResult": "—",
+ "description": "心跳机制允许机器人定期扫描需要关注的项目,确保即使在没有直接对话的情况下也能处理任务。",
+ "filterEmpty": "没有匹配当前状态筛选条件的日志。"
},
"schedule": {
"title": "定时任务",
- "loadFailed": "加载定时任务失败",
+ "subtitle": "配置自动化指令。通过可视化工具或 Cron 表达式控制执行周期。",
+ "loadFailed": "加载失败",
"empty": "暂无定时任务",
"name": "名称",
"pattern": "表达式",
"enabled": "启用",
- "calls": "调用次数",
+ "calls": "调用",
"createdAt": "创建时间",
"updatedAt": "更新时间",
"statusEnabled": "已启用",
"statusDisabled": "已禁用",
- "unlimited": "无限制",
+ "unlimited": "不限",
"actions": "操作",
"create": "新建任务",
- "edit": "编辑",
+ "edit": "编辑任务",
"delete": "删除",
- "deleteConfirm": "确定删除任务 \"{name}\" 吗?此操作无法撤销。",
- "deleteSuccess": "已删除",
+ "deleteConfirm": "确定删除任务 \"{name}\"?此操作不可撤销。",
+ "deleteSuccess": "任务已删除",
"deleteFailed": "删除失败",
- "saveSuccess": "已保存",
+ "saveSuccess": "任务已保存",
"saveFailed": "保存失败",
+ "dangerZoneDesc": "任务删除后无法恢复,请谨慎操作。",
"form": {
- "name": "名称",
- "namePlaceholder": "例如:每日早报",
- "description": "描述",
- "descriptionPlaceholder": "这个任务做什么",
- "command": "指令",
- "commandPlaceholder": "每次触发时让 Bot 做什么",
- "commandHint": "任务触发时,这段内容会作为消息发送给 Bot。",
+ "name": "任务名称",
+ "namePlaceholder": "例如:每日日报",
+ "description": "任务描述",
+ "descriptionPlaceholder": "简述任务用途",
+ "command": "自动化指令",
+ "commandPlaceholder": "触发时执行的指令",
+ "commandHint": "触发时,此指令将作为消息发送给 Bot 执行。",
"pattern": "调度规则",
- "mode": "模式",
- "everyMinutes": "每 N 分钟 (1-59)",
- "atMinute": "每小时的第 M 分钟 (0-59)",
+ "mode": "调度模式",
+ "everyMinutes": "每 N 分钟",
+ "atMinute": "指定分钟",
"hour": "小时",
"hours": "小时",
- "hoursHint": "点击选择一个或多个小时。",
+ "hoursHint": "选择触发的小时。",
"minute": "分钟",
"weekdays": "星期",
- "monthDays": "每月日期",
+ "monthDays": "日期",
"month": "月份",
"monthDay": "日期",
"maxCalls": "运行次数限制",
- "maxCallsUnlimited": "不限制",
- "enabled": "启用",
- "patternPreview": "Cron 表达式",
- "nextRuns": "接下来的触发时间({tz})",
+ "maxCallsUnlimited": "不限次数",
+ "enabled": "启用任务",
+ "visualBuilder": "可视化配置",
+ "cronCode": "Cron 表达式",
+ "manualEditHint": "手动编辑将同步至可视化配置。",
+ "patternPreview": "预览表达式",
+ "nextRuns": "下次触发 ({tz})",
"invalidPattern": "表达式无效",
"advancedPattern": "Cron 表达式",
- "advancedHint": "标准 cron 格式:分 时 日 月 星期。也支持 @daily 等描述符。"
+ "advancedHint": "支持标准 Cron 格式及 @daily 等描述符。"
},
"mode": {
"minutes": "每 N 分钟",
diff --git a/apps/web/src/layout/main-layout/index.vue b/apps/web/src/layout/main-layout/index.vue
index f2ebe3c59..2cb36a9e1 100644
--- a/apps/web/src/layout/main-layout/index.vue
+++ b/apps/web/src/layout/main-layout/index.vue
@@ -1,5 +1,5 @@
-
+
-
+
diff --git a/apps/web/src/pages/appearance/index.vue b/apps/web/src/pages/appearance/index.vue
index b42d5fc22..8f8c3b36b 100644
--- a/apps/web/src/pages/appearance/index.vue
+++ b/apps/web/src/pages/appearance/index.vue
@@ -1,5 +1,5 @@
-
+
diff --git a/apps/web/src/pages/bots/components/bot-access.vue b/apps/web/src/pages/bots/components/bot-access.vue
index 7c20d3fef..7a8610604 100644
--- a/apps/web/src/pages/bots/components/bot-access.vue
+++ b/apps/web/src/pages/bots/components/bot-access.vue
@@ -1,103 +1,121 @@
-
-
+
+
+
-
+
+
+
+
-
-
+
+
{{ $t('bots.access.modeTitle') }}
-
+
{{ $t('bots.access.modeDescription') }}
+ {{ $t('bots.access.blacklistMode') }}
+
{{ $t('bots.access.blacklistModeDescription') }}
+
+ {{ $t('bots.access.whitelistMode') }}
+
{{ $t('bots.access.whitelistModeDescription') }}
-
-
-
-
+
+
{{ listTitle }}
-
+
{{ listDescription }}
-
+
-
+
+
+ class="border border-dashed border-border/60 bg-muted/5 rounded-lg py-10"
+ >
+
+
+
+
- {{ ruleTargetFallback(rule) }}
+
+ {{ ruleTargetFallback(rule) }}
+
-
-
-
+
-
+
-
+
-
+
{{ describeRuleTarget(rule) }}
-
{{ rule.enabled ? $t('bots.access.ruleEnabled') : $t('bots.access.ruleDisabled') }}
-
+
-
+
{{ ruleScopePrefix(rule) }}
- :
+ :
- {{ ruleScopeFallback(rule) }}
+
+ {{ ruleScopeFallback(rule) }}
+
{{ ruleScopeDetail(rule) }}
@@ -168,31 +192,32 @@
{{ rule.description }}
-
-
+
+
-
+
@@ -218,273 +241,177 @@
-
-
-
- {{ editingRule ? $t('bots.access.editRule') : addListEntryLabel }}
-
-
-
-
-