{
margin-bottom: 16px;
font-weight: 600;
line-height: 1.25;
+ scroll-margin-top: 12px;
}
:deep(.markdown-body h1) {
diff --git a/dashboard/src/composables/useProviderSources.ts b/dashboard/src/composables/useProviderSources.ts
index 97eb044da..8c1256284 100644
--- a/dashboard/src/composables/useProviderSources.ts
+++ b/dashboard/src/composables/useProviderSources.ts
@@ -2,6 +2,7 @@ import { ref, computed, onMounted, nextTick, watch } from 'vue'
import axios from 'axios'
import { getProviderIcon } from '@/utils/providerUtils'
import { askForConfirmation as askForConfirmationDialog, useConfirmDialog } from '@/utils/confirmDialog'
+import { normalizeTextInput } from '@/utils/inputValue'
export interface UseProviderSourcesOptions {
defaultTab?: string
@@ -157,7 +158,7 @@ export function useProviderSources(options: UseProviderSourcesOptions) {
})
const filteredMergedModelEntries = computed(() => {
- const term = modelSearch.value.trim().toLowerCase()
+ const term = normalizeTextInput(modelSearch.value).trim().toLowerCase()
if (!term) return mergedModelEntries.value
return mergedModelEntries.value.filter((entry: any) => {
diff --git a/dashboard/src/i18n/composables.ts b/dashboard/src/i18n/composables.ts
index 131010bc3..c67d74903 100644
--- a/dashboard/src/i18n/composables.ts
+++ b/dashboard/src/i18n/composables.ts
@@ -11,7 +11,7 @@ const translations = ref>({});
*/
export async function initI18n(locale: Locale = 'zh-CN') {
currentLocale.value = locale;
-
+
// 加载静态翻译数据
loadTranslations(locale);
}
@@ -50,7 +50,7 @@ export function useI18n() {
const t = (key: string, params?: Record): string => {
const keys = key.split('.');
let value: any = translations.value;
-
+
// 遍历键路径
for (const k of keys) {
if (value && typeof value === 'object' && k in value) {
@@ -61,35 +61,35 @@ export function useI18n() {
return `[MISSING: ${key}]`;
}
}
-
+
if (typeof value !== 'string') {
console.warn(`Translation value is not string: ${key}`, value);
// 返回带括号的键名,便于在开发时识别类型错误的翻译
return `[INVALID: ${key}]`;
}
-
+
// 此时value确定是string类型
let result: string = value;
-
+
// 处理参数插值
if (params) {
result = result.replace(/\{(\w+)\}/g, (match: string, paramKey: string) => {
return params[paramKey]?.toString() || match;
});
}
-
+
return result;
};
-
+
// 切换语言
const setLocale = async (newLocale: Locale) => {
if (newLocale !== currentLocale.value) {
currentLocale.value = newLocale;
loadTranslations(newLocale);
-
+
// 保存到localStorage
localStorage.setItem('astrbot-locale', newLocale);
-
+
// 触发自定义事件,通知相关页面重新加载配置数据
// 这是因为插件适配器的 i18n 数据是通过后端 API 注入的,
// 需要根据 Accept-Language 头重新获取
@@ -98,16 +98,16 @@ export function useI18n() {
}));
}
};
-
+
// 获取当前语言
const locale = computed(() => currentLocale.value);
-
+
// 获取可用语言列表
- const availableLocales: Locale[] = ['zh-CN', 'en-US'];
-
+ const availableLocales: Locale[] = ['zh-CN', 'en-US', 'ru-RU'];
+
// 检查是否已加载
const isLoaded = computed(() => Object.keys(translations.value).length > 0);
-
+
return {
t,
locale,
@@ -122,13 +122,13 @@ export function useI18n() {
*/
export function useModuleI18n(moduleName: string) {
const { t } = useI18n();
-
+
const tm = (key: string, params?: Record): string => {
// 将斜杠转换为点号以匹配嵌套对象结构
const normalizedModuleName = moduleName.replace(/\//g, '.');
return t(`${normalizedModuleName}.${key}`, params);
};
-
+
// 获取原始翻译值(可能是字符串、数组或对象)
const getRaw = (key: string): any => {
const normalizedModuleName = moduleName.replace(/\//g, '.');
@@ -143,10 +143,10 @@ export function useModuleI18n(moduleName: string) {
return null;
}
}
-
+
return value;
};
-
+
return { tm, getRaw };
}
@@ -155,20 +155,21 @@ export function useModuleI18n(moduleName: string) {
*/
export function useLanguageSwitcher() {
const { locale, setLocale, availableLocales } = useI18n();
-
+
const languageOptions = computed(() => [
{ value: 'zh-CN', label: '简体中文', flag: '🇨🇳' },
- { value: 'en-US', label: 'English', flag: '🇺🇸' }
+ { value: 'en-US', label: 'English', flag: '🇺🇸' },
+ { value: 'ru-RU', label: 'Русский', flag: '🇷🇺' }
]);
-
+
const currentLanguage = computed(() => {
return languageOptions.value.find(lang => lang.value === locale.value);
});
-
+
const switchLanguage = async (newLocale: Locale) => {
await setLocale(newLocale);
};
-
+
return {
locale,
languageOptions,
@@ -220,9 +221,9 @@ function deepMerge(target: Record, source: Record) {
export async function setupI18n() {
// 从localStorage获取保存的语言设置
const savedLocale = localStorage.getItem('astrbot-locale') as Locale;
- const initialLocale = savedLocale && ['zh-CN', 'en-US'].includes(savedLocale)
- ? savedLocale
+ const initialLocale = savedLocale && ['zh-CN', 'en-US', 'ru-RU'].includes(savedLocale)
+ ? savedLocale
: 'zh-CN';
-
+
await initI18n(initialLocale);
}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/en-US/features/config-metadata.json b/dashboard/src/i18n/locales/en-US/features/config-metadata.json
index cad25e835..5688b4e45 100644
--- a/dashboard/src/i18n/locales/en-US/features/config-metadata.json
+++ b/dashboard/src/i18n/locales/en-US/features/config-metadata.json
@@ -3,7 +3,7 @@
"name": "AI",
"agent_runner": {
"description": "Agent Runner",
- "hint": "Select the runner for AI conversations. Defaults to AstrBot's built-in Agent runner, which supports knowledge base, persona, and tool calling features. You don't need to modify this section unless you plan to integrate third-party Agent runners like Dify or Coze.",
+ "hint": "Select the runner for AI conversations. Defaults to AstrBot's built-in Agent runner, which supports knowledge base, persona, and tool calling features. You don't need to modify this section unless you plan to integrate third-party Agent runners like Dify, Coze, or DeerFlow.",
"provider_settings": {
"enable": {
"description": "Enable",
@@ -15,7 +15,8 @@
"Built-in Agent",
"Dify",
"Coze",
- "Alibaba Cloud Bailian Application"
+ "Alibaba Cloud Bailian Application",
+ "DeerFlow"
]
},
"coze_agent_runner_provider_id": {
@@ -26,6 +27,9 @@
},
"dashscope_agent_runner_provider_id": {
"description": "Alibaba Cloud Bailian Application Agent Runner Provider ID"
+ },
+ "deerflow_agent_runner_provider_id": {
+ "description": "DeerFlow Agent Runner Provider ID"
}
}
},
@@ -74,6 +78,7 @@
},
"persona": {
"description": "Persona",
+ "hint": "Set the default persona for AI conversations. Personas can be managed in the Persona tab.",
"provider_settings": {
"default_personality": {
"description": "Default Persona"
@@ -157,6 +162,22 @@
"booter": {
"description": "Sandbox Environment Driver"
},
+ "shipyard_neo_endpoint": {
+ "description": "Shipyard Neo API Endpoint",
+ "hint": "Bay API address, default http://127.0.0.1:8114."
+ },
+ "shipyard_neo_access_token": {
+ "description": "Shipyard Neo Access Token",
+ "hint": "Bay API Key (sk-bay-...). Leave empty for auto-discovery from credentials.json."
+ },
+ "shipyard_neo_profile": {
+ "description": "Shipyard Neo Profile",
+ "hint": "Sandbox profile for Shipyard Neo, e.g. python-default."
+ },
+ "shipyard_neo_ttl": {
+ "description": "Shipyard Neo Sandbox TTL",
+ "hint": "Sandbox time-to-live in seconds."
+ },
"shipyard_endpoint": {
"description": "Shipyard API Endpoint",
"hint": "API access address for Shipyard service."
@@ -350,7 +371,8 @@
"hint": "Optional Discord activity name. Leave empty to disable."
},
"discord_command_register": {
- "description": "Auto-register plugin commands as Discord slash commands"
+ "description": "Register Discord slash commands",
+ "hint": "When enabled, AstrBot will automatically register plugin commands as Discord slash commands"
},
"discord_proxy": {
"description": "Discord Proxy URL",
@@ -529,6 +551,10 @@
"description": "WeCom AI Bot Name",
"hint": "Must be correct; otherwise some commands won't work."
},
+ "wecom_ai_bot_connection_mode": {
+ "description": "WeCom AI Bot Connection Mode",
+ "hint": "Webhook mode requires Token/EncodingAESKey; long_connection mode requires BotID/Secret."
+ },
"wecomaibot_friend_message_welcome_text": {
"description": "WeCom AI Bot DM Welcome Message",
"hint": "When a user enters a DM session on that day, reply with a welcome message. Leave empty to disable."
@@ -537,6 +563,30 @@
"description": "WeCom AI Bot Initial Response Text",
"hint": "First reply when the bot receives a message. Leave empty to disable."
},
+ "wecomaibot_token": {
+ "description": "WeCom AI Bot Token",
+ "hint": "Used for authentication in webhook callback mode."
+ },
+ "wecomaibot_encoding_aes_key": {
+ "description": "WeCom AI Bot EncodingAESKey",
+ "hint": "Used for message encryption/decryption in webhook callback mode."
+ },
+ "wecomaibot_ws_bot_id": {
+ "description": "Long Connection BotID",
+ "hint": "BotID credential for WeCom AI Bot long connection mode."
+ },
+ "wecomaibot_ws_secret": {
+ "description": "Long Connection Secret",
+ "hint": "Secret credential for WeCom AI Bot long connection mode."
+ },
+ "wecomaibot_ws_url": {
+ "description": "Long Connection WebSocket URL",
+ "hint": "Default is wss://openws.work.weixin.qq.com and usually does not need changes."
+ },
+ "wecomaibot_heartbeat_interval": {
+ "description": "Long Connection Heartbeat Interval",
+ "hint": "Heartbeat interval (seconds) in long connection mode. 30 seconds is recommended."
+ },
"wpp_active_message_poll": {
"description": "Enable Proactive Message Polling",
"hint": "Only enable if WeChat messages are not syncing to AstrBot on time. Disabled by default."
@@ -563,6 +613,51 @@
"only_use_webhook_url_to_send": {
"description": "Send Replies via Webhook Only",
"hint": "When enabled, all WeCom AI Bot replies are sent through msg_push_webhook_url. The message push webhook supports more message types (such as images, files, etc.). If you do not need the typing effect, it is strongly recommended to use this option. "
+ },
+ "kook_bot_token": {
+ "description": "Bot Token",
+ "type": "string",
+ "hint": "Required. The Bot Token obtained from the KOOK Developer Platform."
+ },
+ "kook_bot_nickname": {
+ "description": "Bot Nickname",
+ "type": "string",
+ "hint": "Optional. If the sender nickname matches this value, the message will be ignored to prevent broadcast storms."
+ },
+ "kook_reconnect_delay": {
+ "description": "Reconnect Delay",
+ "type": "int",
+ "hint": "Delay time for reconnection (seconds), using an exponential backoff strategy."
+ },
+ "kook_max_reconnect_delay": {
+ "description": "Max Reconnect Delay",
+ "type": "int",
+ "hint": "The maximum value for reconnection delay (seconds)."
+ },
+ "kook_max_retry_delay": {
+ "description": "Max Retry Delay",
+ "type": "int",
+ "hint": "The maximum delay time for retries (seconds)."
+ },
+ "kook_heartbeat_interval": {
+ "description": "Heartbeat Interval",
+ "type": "int",
+ "hint": "The interval time for heartbeat detection (seconds)."
+ },
+ "kook_heartbeat_timeout": {
+ "description": "Heartbeat Timeout",
+ "type": "int",
+ "hint": "The timeout duration for heartbeat detection (seconds)."
+ },
+ "kook_max_heartbeat_failures": {
+ "description": "Max Heartbeat Failures",
+ "type": "int",
+ "hint": "Maximum allowed heartbeat failures; the connection will be dropped if exceeded."
+ },
+ "kook_max_consecutive_failures": {
+ "description": "Max Consecutive Failures",
+ "type": "int",
+ "hint": "Maximum allowed consecutive failures; retries will stop if exceeded."
}
},
"general": {
@@ -717,6 +812,17 @@
"hint": "Telegram only supports a fixed reaction set, reference: [https://gist.github.com/Soulter/3f22c8e5f9c7e152e967e8bc28c97fc9](https://gist.github.com/Soulter/3f22c8e5f9c7e152e967e8bc28c97fc9)"
}
}
+ },
+ "discord": {
+ "pre_ack_emoji": {
+ "enable": {
+ "description": "[Discord] Enable Pre-acknowledgment Emoji"
+ },
+ "emojis": {
+ "description": "Emoji List (Unicode or Custom Emoji Name)",
+ "hint": "Enter Unicode emoji symbols, e.g., 👍, 🤔, ⏳"
+ }
+ }
}
}
}
@@ -768,7 +874,8 @@
]
},
"regex": {
- "description": "Segmentation Regular Expression"
+ "description": "Segmentation Regular Expression",
+ "hint": "Used to identify split points with a regular expression. Prefer patterns that match separators."
},
"split_words": {
"description": "Split Word List",
@@ -1363,6 +1470,45 @@
"description": "API Base URL",
"hint": "Base URL for the Coze API. Default: https://api.coze.cn"
},
+ "deerflow_api_base": {
+ "description": "API Base URL",
+ "hint": "DeerFlow API gateway URL. Default: http://127.0.0.1:2026"
+ },
+ "deerflow_api_key": {
+ "description": "DeerFlow API Key",
+ "hint": "Optional. Fill this if your DeerFlow gateway is protected by Bearer auth."
+ },
+ "deerflow_auth_header": {
+ "description": "Authorization Header",
+ "hint": "Optional. Custom Authorization header value; takes precedence over DeerFlow API Key."
+ },
+ "deerflow_assistant_id": {
+ "description": "Assistant ID",
+ "hint": "LangGraph assistant_id, default is lead_agent."
+ },
+ "deerflow_model_name": {
+ "description": "Model name override",
+ "hint": "Optional. Overrides DeerFlow default model (maps to runtime context model_name)."
+ },
+ "deerflow_thinking_enabled": {
+ "description": "Enable thinking mode"
+ },
+ "deerflow_plan_mode": {
+ "description": "Enable plan mode",
+ "hint": "Maps to DeerFlow is_plan_mode."
+ },
+ "deerflow_subagent_enabled": {
+ "description": "Enable subagent",
+ "hint": "Maps to DeerFlow subagent_enabled."
+ },
+ "deerflow_max_concurrent_subagents": {
+ "description": "Max concurrent subagents",
+ "hint": "Maps to DeerFlow max_concurrent_subagents. Effective only when subagent is enabled. Default: 3."
+ },
+ "deerflow_recursion_limit": {
+ "description": "Recursion limit",
+ "hint": "Maps to LangGraph recursion_limit."
+ },
"auto_save_history": {
"description": "Conversation history managed by Coze",
"hint": "When enabled, Coze manages conversation history. AstrBot's locally saved context will not take effect (read-only), and operations on AstrBot context will not apply. If disabled, AstrBot manages the context."
@@ -1377,4 +1523,4 @@
"helpMiddle": "or",
"helpSuffix": "."
}
-}
+}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/en-US/features/extension.json b/dashboard/src/i18n/locales/en-US/features/extension.json
index 8542df208..07affcd62 100644
--- a/dashboard/src/i18n/locales/en-US/features/extension.json
+++ b/dashboard/src/i18n/locales/en-US/features/extension.json
@@ -11,10 +11,21 @@
"titles": {
"installedAstrBotPlugins": "Installed AstrBot Plugins"
},
+ "failedPlugins": {
+ "title": "Failed to Load Plugins ({count})",
+ "hint": "These plugins failed to load. You can try reload or uninstall them directly.",
+ "columns": {
+ "plugin": "Plugin",
+ "error": "Error"
+ }
+ },
"search": {
"placeholder": "Search extensions...",
"marketPlaceholder": "Search market extensions..."
},
+ "filters": {
+ "all": "All"
+ },
"views": {
"card": "Card View",
"list": "List View"
@@ -109,13 +120,19 @@
"sourceExists": "This source already exists",
"installPlugin": "Install Plugin",
"randomPlugins": "🎲 Random Plugins",
+ "showRandomPlugins": "Show Random Plugins",
+ "hideRandomPlugins": "Hide Random Plugins",
"sourceSafetyWarning": "Even with the default source, plugin stability and security cannot be fully guaranteed. Please verify carefully before use."
},
"sort": {
+ "by": "Sort by",
"default": "Default",
+ "installTime": "Last Modified",
+ "name": "Name",
"stars": "Stars",
"author": "Author",
"updated": "Last Updated",
+ "updateStatus": "Update Status",
"ascending": "Ascending",
"descending": "Descending"
},
@@ -177,7 +194,9 @@
"refreshing": "Refreshing extension list...",
"refreshSuccess": "Extension list refreshed!",
"refreshFailed": "Error occurred while refreshing extension list",
+ "operationFailed": "Operation failed",
"reloadSuccess": "Reload successful",
+ "reloadFailed": "Reload failed",
"updateSuccess": "Update successful!",
"addSuccess": "Add successful!",
"saveSuccess": "Save successful!",
@@ -204,19 +223,58 @@
"enterUrl": "Enter extension repository URL"
},
"skills": {
+ "modeLocal": "Local Skills",
+ "modeNeo": "Neo Skills",
+ "actions": "Actions",
"upload": "Upload Skills",
"refresh": "Refresh",
"empty": "No Skills found",
"emptyHint": "Upload a Skills zip to get started",
"uploadDialogTitle": "Upload Skills",
- "uploadHint": "Upload a zip file that contains skill_name/ and a SKILL.md inside.",
+ "uploadHint": "Upload multiple zip skill packages or drag them in. The system validates the structure automatically and shows a result for each file.",
+ "structureRequirement": "The most common failure is an invalid archive structure. Each zip must contain exactly one top-level folder such as `skillname/`, and that folder must include `SKILL.md`.",
+ "abilityMultiple": "Upload multiple zip files at once",
+ "abilityValidate": "Validate `SKILL.md` automatically",
+ "abilitySkip": "Automatically skip duplicate files.",
"selectFile": "Select file",
- "confirmUpload": "Upload",
+ "selectFiles": "Select files (multiple allowed)",
+ "dropzoneTitle": "Drag multiple zip files here",
+ "dropzoneAction": "or click to pick multiple files from a folder",
+ "dropzoneHint": "Batch upload is supported and the structure will be validated automatically",
+ "fileListTitle": "Files in queue",
+ "fileListEmpty": "Selected files will appear here with validation feedback and upload status",
+ "uploading": "Uploading...",
+ "batchResultTitle": "Batch Upload Results",
+ "batchResultSummary": "{success} of {total} files uploaded successfully",
+ "batchSuccessList": "Successfully uploaded",
+ "batchFailedList": "Failed to upload",
+ "confirm": "OK",
+ "confirmUpload": "Start Upload",
"cancel": "Cancel",
+ "statusWaiting": "Waiting",
+ "statusUploading": "Uploading",
+ "statusSuccess": "Uploaded",
+ "statusError": "Failed",
+ "statusSkipped": "Skipped",
+ "summaryTotal": "{count} file(s)",
+ "summaryReady": "Pending {count}",
+ "summarySuccess": "Success {count}",
+ "summaryFailed": "Failed {count}",
+ "summarySkipped": "Skipped {count}",
+ "validationReady": "Ready to upload. The archive structure will be checked during upload.",
+ "validationZipOnly": "Only zip skill packages are supported",
+ "validationDuplicate": "A file with the same name is already in the queue and has been skipped",
+ "validationUploading": "Validating and uploading...",
+ "validationUploadFailed": "Upload failed. Please try again.",
+ "validationUploadedAs": "Installed as {name}",
+ "validationNoResult": "No validation result was returned. Check the platform logs.",
"noDescription": "No description",
"path": "Path",
"uploadSuccess": "Upload succeeded",
"uploadFailed": "Upload failed",
+ "download": "Download",
+ "downloadSuccess": "Download succeeded",
+ "downloadFailed": "Download failed",
"loadFailed": "Failed to load Skills",
"updateSuccess": "Updated successfully",
"updateFailed": "Update failed",
@@ -224,8 +282,42 @@
"deleteMessage": "Are you sure you want to delete this Skill?",
"deleteSuccess": "Deleted successfully",
"deleteFailed": "Delete failed",
+ "neoSkillKey": "Filter by skill_key",
+ "neoStatus": "Candidate Status",
+ "neoStage": "Release Stage",
+ "neoFilterHint": "Filter candidates and release records",
+ "neoAll": "All",
+ "neoCandidates": "Neo Candidates",
+ "neoReleases": "Neo Releases",
+ "neoLoadFailed": "Failed to load Neo skills data",
+ "neoPass": "Pass",
+ "neoReject": "Reject",
+ "neoEvaluateSuccess": "Evaluation updated",
+ "neoEvaluateFailed": "Failed to update evaluation",
+ "neoPromoteSuccess": "Promoted successfully",
+ "neoPromoteFailed": "Failed to promote",
+ "neoRollback": "Rollback",
+ "neoRollbackSuccess": "Rollback succeeded",
+ "neoRollbackFailed": "Rollback failed",
+ "neoDeactivate": "Deactivate",
+ "neoDeactivateSuccess": "Deactivated successfully",
+ "neoDeactivateFailed": "Failed to deactivate",
+ "neoSync": "Sync",
+ "neoSyncSuccess": "Sync succeeded",
+ "neoSyncFailed": "Sync failed",
+ "neoDelete": "Delete",
+ "neoDeleteSuccess": "Deleted successfully",
+ "neoDeleteFailed": "Failed to delete",
+ "neoPayloadTitle": "Neo Payload",
+ "neoPayloadFailed": "Failed to load payload",
"runtimeNoneWarning": "Computer Use runtime is set to None; Skills may not run correctly because no runtime is enabled.",
- "runtimeHint": "Set the Computer Use runtime to Local or Sandbox in settings so AstrBot can use your Skills."
+ "runtimeHint": "Set the Computer Use runtime to Local or Sandbox in settings so AstrBot can use your Skills.",
+ "neoRuntimeRequired": "Neo Skills are available only when runtime is sandbox and sandbox booter is shipyard_neo.",
+ "sourceLocalOnly": "Local Skill",
+ "sourceSandboxOnly": "Sandbox Preset Skill",
+ "sourceBoth": "Local + Sandbox",
+ "sandboxDiscoveryPending": "Sandbox preset skills have not been discovered yet. Start at least one sandbox session to populate this list.",
+ "sandboxPresetReadonly": "Sandbox preset skills are read-only here. You cannot delete or enable/disable them from Local Skills."
},
"card": {
"actions": {
diff --git a/dashboard/src/i18n/locales/en-US/features/persona.json b/dashboard/src/i18n/locales/en-US/features/persona.json
index 9a091e80a..84aaef52c 100644
--- a/dashboard/src/i18n/locales/en-US/features/persona.json
+++ b/dashboard/src/i18n/locales/en-US/features/persona.json
@@ -20,6 +20,8 @@
"form": {
"personaId": "Persona ID",
"systemPrompt": "System Prompt",
+ "customErrorMessage": "Custom Error Reply Message (Optional)",
+ "customErrorMessageHelp": "When this persona's LLM request fails (for example, connection failures), this error reply is sent first. Leave empty to use the default error message.",
"presetDialogs": "Preset Dialogs",
"presetDialogsHelp": "Add some preset dialogs to help the bot better understand the role settings. The number of dialogs must be even (users and assistants take turns).",
"userMessage": "User Message",
diff --git a/dashboard/src/i18n/locales/ru-RU/core/actions.json b/dashboard/src/i18n/locales/ru-RU/core/actions.json
new file mode 100644
index 000000000..9e91e1143
--- /dev/null
+++ b/dashboard/src/i18n/locales/ru-RU/core/actions.json
@@ -0,0 +1,24 @@
+{
+ "create": "Создать",
+ "read": "Чтение",
+ "update": "Обновить",
+ "delete": "Удалить",
+ "search": "Поиск",
+ "filter": "Фильтр",
+ "sort": "Сортировка",
+ "export": "Экспорт",
+ "import": "Импорт",
+ "backup": "Резервное копирование",
+ "restore": "Восстановление",
+ "copy": "Копировать",
+ "paste": "Вставить",
+ "cut": "Вырезать",
+ "undo": "Отменить",
+ "redo": "Повторить",
+ "refresh": "Обновить",
+ "submit": "Отправить",
+ "reset": "Сбросить",
+ "clear": "Очистить",
+ "save": "Сохранить",
+ "close": "Закрыть"
+}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/ru-RU/core/common.json b/dashboard/src/i18n/locales/ru-RU/core/common.json
new file mode 100644
index 000000000..e9f0d4a11
--- /dev/null
+++ b/dashboard/src/i18n/locales/ru-RU/core/common.json
@@ -0,0 +1,133 @@
+{
+ "save": "Сохранить",
+ "cancel": "Отмена",
+ "close": "Закрыть",
+ "copy": "Копировать",
+ "copied": "Скопировано",
+ "copyFailed": "Ошибка копирования",
+ "delete": "Удалить",
+ "edit": "Редактировать",
+ "add": "Добавить",
+ "confirm": "Подтвердить",
+ "loading": "Загрузка...",
+ "success": "Успешно",
+ "error": "Ошибка",
+ "warning": "Внимание",
+ "info": "Информация",
+ "name": "Имя",
+ "description": "Описание",
+ "author": "Автор",
+ "status": "Статус",
+ "actions": "Действия",
+ "enable": "Включить",
+ "disable": "Выключить",
+ "enabled": "Включено",
+ "disabled": "Выключено",
+ "reload": "Перезагрузить",
+ "configure": "Настроить",
+ "install": "Установить",
+ "uninstall": "Удалить",
+ "update": "Обновить",
+ "language": "Язык",
+ "settings": "Настройки",
+ "locale": "JSON",
+ "type": "Тип",
+ "press": "Нажмите",
+ "longPress": "Долгое нажатие",
+ "yes": "Да",
+ "no": "Нет",
+ "imagePreview": "Предпросмотр изображения",
+ "autoDetect": "Автоопределение",
+ "dialog": {
+ "confirmTitle": "Подтверждение",
+ "confirmMessage": "Вы уверены, что хотите выполнить это действие?",
+ "confirmButton": "ОК",
+ "cancelButton": "Отмена"
+ },
+ "restart": {
+ "waiting": "Ожидание перезагрузки AstrBot...",
+ "maxRetriesReached": "Превышено количество попыток проверки статуса. Пожалуйста, проверьте вручную."
+ },
+ "readme": {
+ "title": "Документация плагина",
+ "buttons": {
+ "viewOnGithub": "Открыть репозиторий на GitHub",
+ "refresh": "Обновить"
+ },
+ "loading": "Загрузка README...",
+ "errors": {
+ "fetchFailed": "Не удалось загрузить README",
+ "fetchError": "Произошла ошибка при загрузке README"
+ },
+ "empty": {
+ "title": "У этого плагина нет ссылки на документацию или репозиторий GitHub.",
+ "subtitle": "Пожалуйста, посетите магазин плагинов или свяжитесь с автором для получения дополнительной информации."
+ }
+ },
+ "changelog": {
+ "title": "Журнал изменений",
+ "loading": "Загрузка журнала изменений...",
+ "empty": {
+ "title": "У этого плагина нет журнала изменений",
+ "subtitle": "Разработчики могут добавить файл CHANGELOG.md в директорию плагина"
+ }
+ },
+ "editor": {
+ "fullscreen": "На весь экран",
+ "editingTitle": "Редактирование содержимого"
+ },
+ "templateList": {
+ "addEntry": "Добавить запись",
+ "empty": "Записей нет, выберите шаблон для добавления",
+ "missingTemplate": "Шаблон не найден, пожалуйста, удалите и добавьте заново.",
+ "unknownTemplate": "Неизвестный шаблон"
+ },
+ "list": {
+ "addItemPlaceholder": "Добавьте новый элемент и нажмите Enter",
+ "addButton": "Добавить",
+ "addMore": "Добавить еще",
+ "batchImport": "Массовый импорт",
+ "batchImportTitle": "Массовый импорт",
+ "batchImportLabel": "Один элемент на строку",
+ "batchImportPlaceholder": "Например:\nЭлемент 1\nЭлемент 2\nЭлемент 3",
+ "batchImportHint": "Каждая строка будет считаться отдельным элементом. Пустые строки игнорируются.",
+ "batchImportButton": "Импортировать {count} эл.",
+ "noItems": "Список пуст",
+ "noItemsHint": "Элементов нет. Напишите что-нибудь выше и нажмите Enter.",
+ "inputPlaceholder": "Введите текст и нажмите Enter",
+ "editTitle": "Изменить элемент",
+ "modifyButton": "Изменить"
+ },
+ "itemCard": {
+ "enabled": "Включено",
+ "disabled": "Выключено",
+ "delete": "Удалить",
+ "edit": "Изменить",
+ "copy": "Копировать",
+ "noData": "Нет данных"
+ },
+ "objectEditor": {
+ "dialogTitle": "Изменение пар ключ-значение",
+ "noItems": "Нет элементов",
+ "noParams": "Нет параметров",
+ "presets": "Пресеты",
+ "newKeyLabel": "Имя ключа",
+ "valueTypeLabel": "Тип значения",
+ "keyExists": "Ключ уже существует",
+ "invalidJson": "Некорректный формат JSON",
+ "placeholders": {
+ "keyName": "Ключ",
+ "stringValue": "Строка",
+ "numberValue": "Число",
+ "jsonValue": "JSON"
+ }
+ },
+ "firstNotice": {
+ "title": "Первичная информация",
+ "loading": "Загрузка информации...",
+ "empty": {
+ "title": "Нет информации для отображения",
+ "subtitle": "Файл FIRST_NOTICE.md не найден или пуст."
+ }
+ }
+}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/ru-RU/core/header.json b/dashboard/src/i18n/locales/ru-RU/core/header.json
new file mode 100644
index 000000000..a23f3dfd3
--- /dev/null
+++ b/dashboard/src/i18n/locales/ru-RU/core/header.json
@@ -0,0 +1,108 @@
+{
+ "logoTitle": "Панель управления AstrBot",
+ "version": {
+ "hasNewVersion": "Доступна новая версия AstrBot!",
+ "dashboardHasNewVersion": "Доступна новая версия WebUI!"
+ },
+ "buttons": {
+ "update": "Обновить",
+ "account": "Аккаунт",
+ "theme": {
+ "light": "Светлая тема",
+ "dark": "Темная тема"
+ }
+ },
+ "updateDialog": {
+ "title": "Обновить AstrBot",
+ "currentVersion": "Текущая версия",
+ "status": {
+ "checking": "Проверка обновлений...",
+ "switching": "Переключение версии...",
+ "updating": "Обновление..."
+ },
+ "tabs": {
+ "release": "😊 Релиз"
+ },
+ "updateToLatest": "Обновить до последней версии",
+ "preRelease": "Предварительная версия",
+ "preReleaseWarning": {
+ "title": "Внимание: предварительная версия",
+ "description": "Версии с меткой Pre-release могут содержать неизвестные ошибки. Не рекомендуется использовать в рабочих средах. Если вы обнаружили ошибку, пожалуйста, сообщите о ней в ",
+ "issueLink": "GitHub Issues"
+ },
+ "tip": "💡 ПОДСКАЗКА: ",
+ "tipContinue": "По умолчанию при переключении версии загружаются соответствующие файлы WebUI. Код WebUI находится в директории dashboard, вы можете собрать его самостоятельно с помощью npm.",
+ "dockerTip": "При переключении версии будет предпринята попытка обновить как основной процесс бота, так и панель управления. Если вы используете Docker, вы также можете обновить образ или использовать",
+ "dockerTipLink": "watchtower",
+ "dockerTipContinue": "для автоматического мониторинга и обновления.",
+ "table": {
+ "tag": "Тег",
+ "publishDate": "Дата публикации",
+ "content": "Содержание",
+ "sourceUrl": "Исходный код",
+ "actions": "Действия",
+ "view": "Просмотр",
+ "switch": "Переключить"
+ },
+ "releaseNotes": {
+ "title": "Журнал изменений"
+ },
+ "redirectConfirm": {
+ "title": "Переход по ссылке",
+ "message": "Вы будете перенаправлены на страницу GitHub Releases. Продолжить?",
+ "latestLabel": "Последняя версия",
+ "targetVersion": "Целевая версия:",
+ "currentVersion": "Текущая версия:",
+ "guideTitle": "Рекомендации после перехода:",
+ "guideStep1": "Загрузите пакет, соответствующий архитектуре вашей системы.",
+ "guideStep2": "После завершения установки перезапустите AstrBot.",
+ "guideStep3": "Если вы используете Docker, отдайте приоритет обновлению через образ."
+ },
+ "desktopApp": {
+ "title": "Обновить десктопное приложение",
+ "message": "Проверка и обновление десктопной версии AstrBot.",
+ "currentVersion": "Текущая версия:",
+ "latestVersion": "Последняя версия:",
+ "checking": "Проверка обновлений десктопного приложения...",
+ "hasNewVersion": "Найдена новая версия. Нажмите для подтверждения обновления.",
+ "isLatest": "Установлена последняя версия",
+ "installing": "Загрузка и установка обновления... Приложение будет перезапущено автоматически.",
+ "checkFailed": "Ошибка проверки обновлений. Попробуйте позже.",
+ "installFailed": "Ошибка обновления. Попробуйте позже."
+ },
+ "dashboardUpdate": {
+ "title": "Обновить только панель управления",
+ "currentVersion": "Текущая версия",
+ "hasNewVersion": "Доступна новая версия!",
+ "isLatest": "Установлена последняя версия.",
+ "downloadAndUpdate": "Скачать и обновить"
+ }
+ },
+ "accountDialog": {
+ "title": "Изменить аккаунт",
+ "securityWarning": "Безопасность: Пожалуйста, смените пароль по умолчанию для защиты аккаунта",
+ "form": {
+ "currentPassword": "Текущий пароль",
+ "newPassword": "Новый пароль",
+ "confirmPassword": "Подтвердите новый пароль",
+ "newUsername": "Новое имя пользователя (опционально)",
+ "passwordHint": "Пароль должен быть не менее 8 символов",
+ "confirmPasswordHint": "Введите новый пароль еще раз",
+ "usernameHint": "Оставьте пустым, если не хотите менять имя пользователя",
+ "defaultCredentials": "Логин и пароль по умолчанию: astrbot"
+ },
+ "validation": {
+ "passwordRequired": "Введите пароль",
+ "passwordMinLength": "Пароль должен быть не менее 8 символов",
+ "passwordMatch": "Паролы не совпадают",
+ "usernameMinLength": "Имя пользователя должно быть не менее 3 символов"
+ },
+ "actions": {
+ "save": "Сохранить изменения",
+ "cancel": "Отмена"
+ },
+ "messages": {
+ "updateFailed": "Ошибка обновления, попробуйте еще раз"
+ }
+ }
+}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/ru-RU/core/navigation.json b/dashboard/src/i18n/locales/ru-RU/core/navigation.json
new file mode 100644
index 000000000..2abb189f4
--- /dev/null
+++ b/dashboard/src/i18n/locales/ru-RU/core/navigation.json
@@ -0,0 +1,49 @@
+{
+ "welcome": "Добро пожаловать",
+ "dashboard": "Статистика",
+ "platforms": "Боты",
+ "providers": "Провайдеры моделей",
+ "commands": "Команды",
+ "persona": "Персонажи",
+ "subagent": "Субагенты",
+ "toolUse": "Инструменты MCP",
+ "extension": "Плагины",
+ "extensionTabs": {
+ "installed": "Плагины AstrBot",
+ "market": "Магазин плагинов",
+ "mcp": "Серверы MCP",
+ "skills": "Навыки",
+ "components": "Управление поведением"
+ },
+ "config": "Конфигурация",
+ "chat": "Чат",
+ "cron": "Запланированные задачи",
+ "conversation": "Данные диалогов",
+ "sessionManagement": "Пользовательские правила",
+ "console": "Логи платформы",
+ "trace": "Трассировка",
+ "alkaid": "Alkaid Lab",
+ "knowledgeBase": "База знаний",
+ "about": "О программе",
+ "settings": "Настройки",
+ "changelog": "Журнал изменений",
+ "documentation": "Документация",
+ "faq": "FAQ",
+ "github": "GitHub",
+ "drag": "Перетащить",
+ "groups": {
+ "more": "Дополнительно"
+ },
+ "changelogDialog": {
+ "title": "Журнал изменений",
+ "loading": "Загрузка...",
+ "error": "Ошибка загрузки",
+ "notFound": "Журнал изменений для этой версии не найден",
+ "selectVersion": "Выберите версию",
+ "current": "Текущая"
+ },
+ "configTabs": {
+ "normal": "Обычная конфигурация",
+ "system": "Системная конфигурация"
+ }
+}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/ru-RU/core/shared.json b/dashboard/src/i18n/locales/ru-RU/core/shared.json
new file mode 100644
index 000000000..e59705a4b
--- /dev/null
+++ b/dashboard/src/i18n/locales/ru-RU/core/shared.json
@@ -0,0 +1,111 @@
+{
+ "knowledgeBaseSelector": {
+ "notSelected": "Не выбрано",
+ "buttonText": "Выбрать базу знаний...",
+ "dialogTitle": "Выбор базы знаний",
+ "loading": "Загрузка...",
+ "noKnowledgeBases": "Базы знаний не найдены",
+ "createKnowledgeBase": "Создать базу знаний",
+ "selectedCount": "Выбрано баз знаний: {count}",
+ "confirmSelection": "ОК",
+ "cancelSelection": "Отмена",
+ "noDescription": "Нет описания",
+ "documentCount": "Документов: {count}",
+ "chunkCount": "Фрагментов: {count}"
+ },
+ "pluginSetSelector": {
+ "notSelected": "Плагины не включены",
+ "allPlugins": "Включить все плагины (*)",
+ "selectedCount": "Выбрано плагинов: {count}",
+ "buttonText": "Выбрать набор плагинов...",
+ "dialogTitle": "Выбор набора плагинов",
+ "loading": "Загрузка...",
+ "enableAll": "Включить все",
+ "enableNone": "Ничего не включать",
+ "customSelect": "Настроить выбор",
+ "noPlugins": "Доступных плагинов нет",
+ "confirmSelection": "ОК",
+ "cancelSelection": "Отмена",
+ "noDescription": "Нет описания",
+ "notActivated": "Не активирован",
+ "note": "*Системные и уже выключенные в настройках плагины не отображаются.",
+ "selectedPluginsLabel": "Выбранные плагины:",
+ "allPluginsLabel": "Все плагины"
+ },
+ "providerSelector": {
+ "notSelected": "Не выбрано",
+ "buttonText": "Выбрать провайдера...",
+ "dialogTitle": "Выбор провайдера",
+ "loading": "Загрузка...",
+ "noProviders": "Доступных провайдеров нет",
+ "confirmSelection": "ОК",
+ "cancelSelection": "Отмена",
+ "clearSelection": "Сбросить выбор",
+ "clearSelectionSubtitle": "Очистить текущий выбор",
+ "unknownType": "Неизвестный тип",
+ "createProvider": "Создать провайдера",
+ "manageProviders": "Управление провайдерами",
+ "selectProviderPool": "Выбрать пул провайдеров...",
+ "selectedCount": "Выбрано провайдеров: {count}"
+ },
+ "personaSelector": {
+ "notSelected": "Не выбрано",
+ "defaultPersona": "Персонаж по умолчанию",
+ "buttonText": "Выбрать персонажа...",
+ "editPersona": "Изменить текущего персонажа",
+ "dialogTitle": "Выбор персонажа",
+ "noDescription": "Нет описания",
+ "noPersonas": "Доступных персонажей нет",
+ "createPersona": "Создать персонажа",
+ "cancelSelection": "Отмена",
+ "confirmSelection": "ОК",
+ "selectPersonaPool": "Выбрать пул персонажей...",
+ "rootFolder": "Все персонажи",
+ "emptyFolder": "Папка пуста"
+ },
+ "personaQuickPreview": {
+ "title": "Быстрый просмотр",
+ "loading": "Загрузка...",
+ "noPersonaSelected": "Персонаж не выбран",
+ "personaNotFound": "Информация о персонаже не найдена",
+ "systemPromptLabel": "Системный промпт",
+ "toolsLabel": "Инструменты",
+ "skillsLabel": "Навыки (Skills)",
+ "originLabel": "Источник",
+ "originNameLabel": "Имя источника",
+ "toolInactive": "Выключено",
+ "toolInactiveTooltip": "Этот инструмент выключен. Включите его в Плагины -> Управление поведением -> Функции.",
+ "allTools": "Доступны все инструменты",
+ "allToolsWithCount": "Доступны все инструменты ({count})",
+ "noTools": "Инструменты не настроены",
+ "allSkills": "Доступны все навыки (Skills)",
+ "allSkillsWithCount": "Доступны все навыки ({count})",
+ "noSkills": "Навыки (Skills) не настроены"
+ },
+ "t2iTemplateEditor": {
+ "buttonText": "Настроить T2I шаблон",
+ "dialogTitle": "Настройка HTML шаблона Text-to-Image",
+ "newTemplateNameLabel": "Введите имя нового шаблона",
+ "nameRequired": "Имя обязательно для заполнения",
+ "selectTemplateLabel": "Выбрать шаблон",
+ "applied": "Применено",
+ "apply": "Применить",
+ "templateEditor": "Редактор шаблона",
+ "new": "Создать",
+ "resetBase": "Сбросить 'base'",
+ "delete": "Удалить",
+ "save": "Сохранить",
+ "livePreview": "Предпросмотр (может отличаться)",
+ "refreshPreview": "Обновить",
+ "syntaxHint": "Поддерживается синтаксис jinja2. Переменные: text | safe (текст для рендеринга), version (версия AstrBot)",
+ "saveAndApply": "Сохранить и применить текущий шаблон",
+ "confirmReset": "Подтверждение сброса",
+ "confirmResetMessage": "Вы уверены, что хотите сбросить шаблон 'base' до значений по умолчанию? Все несохраненные изменения будут потеряны. Это действие необратимо.",
+ "confirmResetButton": "Сбросить",
+ "confirmDelete": "Подтверждение удаления",
+ "confirmDeleteMessage": "Вы уверены, что хотите удалить шаблон '{name}'? Это действие необратимо.",
+ "confirmDeleteButton": "Удалить",
+ "confirmAction": "Подтверждение действия",
+ "confirmApplyMessage": "Вы уверены, что хотите сохранить изменения в '{name}' и сделать его активным шаблоном?"
+ }
+}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/ru-RU/core/status.json b/dashboard/src/i18n/locales/ru-RU/core/status.json
new file mode 100644
index 000000000..a016dae17
--- /dev/null
+++ b/dashboard/src/i18n/locales/ru-RU/core/status.json
@@ -0,0 +1,22 @@
+{
+ "loading": "Загрузка",
+ "success": "Успешно",
+ "error": "Ошибка",
+ "warning": "Внимание",
+ "info": "Информация",
+ "pending": "В ожидании",
+ "processing": "В процессе",
+ "completed": "Завершено",
+ "failed": "Ошибка",
+ "cancelled": "Отменено",
+ "timeout": "Тайм-аут",
+ "connecting": "Подключение",
+ "connected": "Подключено",
+ "disconnected": "Отключено",
+ "online": "В сети",
+ "offline": "Не в сети",
+ "active": "Активен",
+ "inactive": "Неактивен",
+ "ready": "Готов",
+ "busy": "Занят"
+}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/ru-RU/features/about.json b/dashboard/src/i18n/locales/ru-RU/features/about.json
new file mode 100644
index 000000000..d9ef90b4f
--- /dev/null
+++ b/dashboard/src/i18n/locales/ru-RU/features/about.json
@@ -0,0 +1,17 @@
+{
+ "hero": {
+ "title": "AstrBot",
+ "subtitle": "Проект, рожденный из интереса и любви ❤️",
+ "starButton": "Star этот проект! 🌟",
+ "issueButton": "Сообщить об ошибке"
+ },
+ "contributors": {
+ "title": "Контрибьюторы",
+ "description": "Этот проект поддерживается участниками open-source сообщества. Спасибо каждому за вклад!",
+ "viewLink": "Посмотреть всех участников"
+ },
+ "stats": {
+ "title": "Глобальное развертывание",
+ "license": "AstrBot распространяется по лицензии AGPL v3"
+ }
+}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/ru-RU/features/alkaid/index.json b/dashboard/src/i18n/locales/ru-RU/features/alkaid/index.json
new file mode 100644
index 000000000..ece76056a
--- /dev/null
+++ b/dashboard/src/i18n/locales/ru-RU/features/alkaid/index.json
@@ -0,0 +1,44 @@
+{
+ "title": "Лаборатория Alkaid",
+ "subtitle": "Исследуйте передовые возможности AI",
+ "comingSoon": "Этот мир еще впереди, заходите позже!",
+ "page": {
+ "title": "Проект Alkaid.",
+ "subtitle": "AstrBot Alpha Project",
+ "navigation": {
+ "knowledgeBase": "База знаний (Плагин)",
+ "longTermMemory": "Долгосрочная память",
+ "other": "..."
+ }
+ },
+ "features": {
+ "knowledgeBase": "База знаний",
+ "longTermMemory": "Долгосрочная память",
+ "advancedChat": "Продвинутый чат",
+ "multiModal": "Мультимодальность"
+ },
+ "status": {
+ "experimental": "Экспериментально",
+ "beta": "Бета",
+ "stable": "Стабильно",
+ "deprecated": "Устарело"
+ },
+ "sigma": {
+ "subtitle": "Экспериментальный проект AstrBot",
+ "visualization": "Визуализация",
+ "filterUserId": "Фильтр по User ID",
+ "filter": "Фильтр",
+ "resetFilter": "Сброс",
+ "refreshGraph": "Обновить граф",
+ "nodeDetails": "Детали узла",
+ "id": "ID",
+ "type": "Тип",
+ "name": "Имя",
+ "userId": "ID пользователя",
+ "timestamp": "Метка времени",
+ "graphStats": "Статистика графа",
+ "nodeCount": "Узлов",
+ "edgeCount": "Связей",
+ "inDevelopment": "В разработке"
+ }
+}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/ru-RU/features/alkaid/knowledge-base.json b/dashboard/src/i18n/locales/ru-RU/features/alkaid/knowledge-base.json
new file mode 100644
index 000000000..3d52f2614
--- /dev/null
+++ b/dashboard/src/i18n/locales/ru-RU/features/alkaid/knowledge-base.json
@@ -0,0 +1,155 @@
+{
+ "title": "База знаний",
+ "subtitle": "Управление контентом базы знаний и поиск",
+ "documents": {
+ "title": "Список документов",
+ "name": "Имя файла",
+ "size": "Размер",
+ "uploadTime": "Дата загрузки",
+ "status": "Статус",
+ "actions": "Действия"
+ },
+ "management": {
+ "delete": "Удалить",
+ "preview": "Предпросмотр",
+ "download": "Скачать",
+ "reindex": "Переиндексировать"
+ },
+ "notInstalled": {
+ "title": "Плагин базы знаний не установлен",
+ "install": "Установить сейчас"
+ },
+ "empty": {
+ "title": "База знаний пуста. Создайте свою первую базу! 🙂",
+ "create": "Создать базу знаний"
+ },
+ "list": {
+ "title": "Список баз знаний",
+ "create": "Создать базу знаний",
+ "config": "Настройка",
+ "checkUpdate": "Проверить обновления плагина",
+ "updatePlugin": "Обновить плагин до версии {version}",
+ "knowledgeCount": "записей",
+ "tips": "Совет: используйте команду /kb в чате, чтобы узнать, как пользоваться базой!"
+ },
+ "createDialog": {
+ "title": "Создание базы знаний",
+ "nameLabel": "Название",
+ "descriptionLabel": "Описание",
+ "descriptionPlaceholder": "Краткое описание...",
+ "embeddingModelLabel": "Embedding модель",
+ "rerankModelLabel": "Rerank модель",
+ "providerInfo": "Провайдер: {id} | Размерность: {dimensions}",
+ "rerankProviderInfo": "Провайдер: {id}",
+ "tips": "Совет: после выбора Embedding модели не рекомендуется менять провайдера или размерность векторов, так как это сделает текущий индекс нечитаемым.",
+ "cancel": "Отмена",
+ "create": "Создать"
+ },
+ "emojiPicker": {
+ "title": "Выберите иконку",
+ "close": "Закрыть",
+ "categories": {
+ "emotions": "Смайлы",
+ "animals": "Животные и природа",
+ "food": "Еда и напитки",
+ "activities": "Занятия и вещи",
+ "travel": "Места и путешествия",
+ "symbols": "Символы и флаги"
+ }
+ },
+ "contentDialog": {
+ "title": "Управление базой знаний",
+ "embeddingModel": "Embedding модель",
+ "vectorDimension": "Размерность",
+ "usage": "Использование: введите «/kb use {name}» в чате",
+ "tabs": {
+ "upload": "Загрузка файлов",
+ "search": "Поиск",
+ "fromURL": "Импорт из URL"
+ }
+ },
+ "upload": {
+ "title": "Загрузка файлов",
+ "subtitle": "Поддерживаются форматы txt, pdf, word, excel и др.",
+ "dropzone": "Перетащите файлы сюда или нажмите для выбора",
+ "chunkSettings": {
+ "title": "Настройка фрагментации (Chunking)",
+ "tooltip": "Размер фрагмента определяет объем текста в одном блоке. Перекрытие позволяет сохранить контекст между соседними блоками.\nМаленькие фрагменты точнее, но увеличивают объем базы.",
+ "chunkSizeLabel": "Размер фрагмента",
+ "chunkSizeHint": "Длина текста в одном блоке (пусто = по умолчанию)",
+ "overlapLabel": "Перекрытие",
+ "overlapHint": "Нахлест между соседними блоками (пусто = по умолчанию)"
+ },
+ "upload": "Начать загрузку",
+ "uploading": "Загрузка..."
+ },
+ "search": {
+ "queryLabel": "Поиск по базе знаний",
+ "queryPlaceholder": "Введите ключевые слова...",
+ "resultCountLabel": "Количество результатов",
+ "searching": "Поиск...",
+ "resultsTitle": "Результаты поиска",
+ "relevance": "Релевантность",
+ "noResults": "Совпадений не найдено"
+ },
+ "deleteDialog": {
+ "title": "Подтверждение удаления",
+ "confirmText": "Вы уверены, что хотите удалить базу знаний «{name}»?",
+ "warning": "Это действие необратимо. Весь контент базы знаний будет навсегда удален.",
+ "cancel": "Отмена",
+ "delete": "Удалить"
+ },
+ "messages": {
+ "pluginNotAvailable": "Плагин не установлен или недоступен",
+ "pluginNotActivated": "Плагин astrbot_plugin_knowledge_base не включен. Пожалуйста, активируйте его в разделе плагинов и перезапустите AstrBot.",
+ "checkPluginFailed": "Не удалось проверить плагин",
+ "installFailed": "Ошибка установки",
+ "installPluginFailed": "Не удалось установить плагин",
+ "getKnowledgeBaseListFailed": "Ошибка получения списка баз знаний",
+ "knowledgeBaseCreated": "База знаний создана",
+ "createFailed": "Ошибка создания",
+ "createKnowledgeBaseFailed": "Не удалось создать базу знаний",
+ "pleaseEnterKnowledgeBaseName": "Укажите название базы знаний",
+ "pleaseSelectFile": "Пожалуйста, сначала выберите файл",
+ "operationSuccess": "Успешно: {message}",
+ "uploadFailed": "Ошибка загрузки",
+ "fileUploadFailed": "Не удалось загрузить файл",
+ "pleaseEnterSearchContent": "Введите текст для поиска",
+ "noMatchingContent": "Ничего не найдено",
+ "searchFailed": "Ошибка поиска",
+ "searchKnowledgeBaseFailed": "Не удалось выполнить поиск",
+ "deleteTargetNotExists": "Объект для удаления не найден",
+ "knowledgeBaseDeleted": "База знаний удалена",
+ "deleteFailed": "Ошибка удаления",
+ "deleteKnowledgeBaseFailed": "Не удалось удалить базу знаний",
+ "getEmbeddingModelListFailed": "Не удалось загрузить список Embedding моделей",
+ "updateAvailable": "Доступна новая версия: {current} -> {latest}",
+ "pluginUpToDate": "У вас последняя версия плагина",
+ "pluginNotFoundInMarket": "Плагин не найден в магазине",
+ "checkUpdateFailed": "Ошибка проверки обновлений",
+ "updateSuccess": "Плагин успешно обновлен",
+ "updateFailed": "Ошибка обновления",
+ "updatePluginFailed": "Не удалось обновить плагин"
+ },
+ "importFromUrl": {
+ "title": "Импорт из URL",
+ "urlLabel": "Адрес страницы",
+ "urlPlaceholder": "Введите URL для извлечения знаний",
+ "optionsTitle": "Настройки импорта",
+ "tooltip": "Эти параметры управляют извлечением текста из URL.\nЕсли оставить пустыми, будут использованы настройки по умолчанию.\nТекстовая очистка через LLM может занять время.",
+ "useLlmRepairLabel": "Исправление текста через LLM",
+ "useClusteringSummaryLabel": "Кластеризация и суммаризация",
+ "repairLlmProviderIdLabel": "Модель для очистки",
+ "summarizeLlmProviderIdLabel": "Модель для суммаризации",
+ "embeddingProviderIdLabel": "Embedding модель",
+ "chunkSizeLabel": "Размер фрагмента",
+ "chunkOverlapLabel": "Перекрытие",
+ "startImport": "Начать импорт",
+ "importing": "Импорт...",
+ "importSuccess": "Импортировано успешно",
+ "importFailed": "Ошибка импорта",
+ "uploadingChunks": "Текст извлечен, загрузка фрагментов...",
+ "preRequisite": "Примечание: сначала установите плагин astrbot_plugin_url_2_knowledge_base и выполните установку playwright согласно документации.",
+ "allChunksUploaded": "Все фрагменты успешно загружены"
+ }
+}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/ru-RU/features/alkaid/memory.json b/dashboard/src/i18n/locales/ru-RU/features/alkaid/memory.json
new file mode 100644
index 000000000..507c6ae18
--- /dev/null
+++ b/dashboard/src/i18n/locales/ru-RU/features/alkaid/memory.json
@@ -0,0 +1,97 @@
+{
+ "title": "Долгосрочная память",
+ "subtitle": "Управление памятью вашего AI-помощника",
+ "memories": {
+ "title": "Список воспоминаний",
+ "content": "Содержание",
+ "importance": "Важность",
+ "createTime": "Дата создания",
+ "lastAccess": "Последнее обращение",
+ "category": "Категория"
+ },
+ "categories": {
+ "personal": "Личное",
+ "preferences": "Предпочтения",
+ "conversations": "История диалогов",
+ "facts": "Факты",
+ "skills": "Навыки"
+ },
+ "importance": {
+ "high": "Высокая",
+ "medium": "Средняя",
+ "low": "Низкая"
+ },
+ "actions": {
+ "view": "Детали",
+ "edit": "Изменить",
+ "delete": "Удалить",
+ "pin": "Закрепить",
+ "unpin": "Открепить"
+ },
+ "filters": {
+ "all": "Все",
+ "category": "По категории",
+ "importance": "По важности",
+ "dateRange": "По периоду",
+ "title": "Фильтр",
+ "userIdLabel": "Фильтр по User ID",
+ "filterButton": "Применить",
+ "resetButton": "Сбросить",
+ "refreshButton": "Обновить граф"
+ },
+ "search": {
+ "title": "Поиск по памяти",
+ "userIdLabel": "ID пользователя",
+ "queryLabel": "Ключевое слово",
+ "searchButton": "Поиск",
+ "resultsTitle": "Результаты поиска",
+ "noResults": "Ничего не найдено",
+ "similarity": "Сходство",
+ "noTextContent": "Нет текста"
+ },
+ "addMemory": {
+ "title": "Добавить данные в память",
+ "textLabel": "Текст воспоминания",
+ "userIdLabel": "ID пользователя",
+ "summarizeLabel": "Нужна суммаризация",
+ "addButton": "Добавить"
+ },
+ "nodeDetails": {
+ "title": "Детали узла",
+ "id": "ID",
+ "type": "Тип",
+ "name": "Имя",
+ "userId": "ID пользователя",
+ "timestamp": "Метка времени"
+ },
+ "graphStats": {
+ "title": "Статистика графа",
+ "nodeCount": "Узлов",
+ "edgeCount": "Связей"
+ },
+ "factDialog": {
+ "title": "Факт из памяти",
+ "id": "ID",
+ "docId": "ID документа",
+ "createdAt": "Создано",
+ "updatedAt": "Обновлено",
+ "metadata": "Метаданные",
+ "metadataKey": "Ключ",
+ "metadataValue": "Значение",
+ "loading": "Загрузка...",
+ "close": "Закрыть",
+ "noValue": "нет",
+ "unknown": "неизвестно"
+ },
+ "messages": {
+ "searchQueryRequired": "Пожалуйста, введите запрос",
+ "searchSuccess": "Найдено записей: {count}",
+ "searchNoResults": "В памяти ничего не найдено",
+ "searchError": "Ошибка поиска",
+ "addSuccess": "Данные успешно добавлены в память!",
+ "addError": "Не удалось добавить данные",
+ "factDetailsError": "Ошибка загрузки деталей",
+ "metadataParseError": "Не удалось разобрать метаданные",
+ "relationNoMemoryData": "У этой связи нет ассоциированных данных"
+ }
+}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/ru-RU/features/auth.json b/dashboard/src/i18n/locales/ru-RU/features/auth.json
new file mode 100644
index 000000000..d6ba05dc3
--- /dev/null
+++ b/dashboard/src/i18n/locales/ru-RU/features/auth.json
@@ -0,0 +1,14 @@
+{
+ "login": "Вход",
+ "username": "Имя пользователя",
+ "password": "Пароль",
+ "defaultHint": "Логин и пароль по умолчанию: astrbot",
+ "logo": {
+ "title": "Панель управления AstrBot",
+ "subtitle": "Добро пожаловать"
+ },
+ "theme": {
+ "switchToDark": "Перейти на темную тему",
+ "switchToLight": "Перейти на светлую тему"
+ }
+}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/ru-RU/features/chart.json b/dashboard/src/i18n/locales/ru-RU/features/chart.json
new file mode 100644
index 000000000..d5d20474d
--- /dev/null
+++ b/dashboard/src/i18n/locales/ru-RU/features/chart.json
@@ -0,0 +1,4 @@
+{
+ "messageCount": "Количество сообщений",
+ "time": "Время"
+}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/ru-RU/features/chat.json b/dashboard/src/i18n/locales/ru-RU/features/chat.json
new file mode 100644
index 000000000..fa434bb7d
--- /dev/null
+++ b/dashboard/src/i18n/locales/ru-RU/features/chat.json
@@ -0,0 +1,146 @@
+{
+ "title": "Давай пообщаемся!",
+ "subtitle": "Общение с AI-помощником",
+ "input": {
+ "placeholder": "Введите сообщение...",
+ "send": "Отправить",
+ "clear": "Очистить",
+ "upload": "Загрузить файл",
+ "voice": "Голосовой ввод",
+ "recordingPrompt": "Запись... говорите",
+ "chatPrompt": "Давай пообщаемся!",
+ "dropToUpload": "Отпустите, чтобы загрузить файл",
+ "stopGenerating": "Остановить генерацию"
+ },
+ "message": {
+ "user": "Вы",
+ "assistant": "Ассистент",
+ "system": "Система",
+ "error": "Ошибка в сообщении",
+ "loading": "Думаю..."
+ },
+ "voice": {
+ "start": "Начать запись",
+ "stop": "Стоп",
+ "recording": "Запись",
+ "processing": "Обработка...",
+ "error": "Ошибка записи",
+ "listening": "Слушаю...",
+ "speaking": "Говорю",
+ "startRecording": "Начать голосовой ввод",
+ "liveMode": "Общение в реальном времени"
+ },
+ "welcome": {
+ "title": "Добро пожаловать в AstrBot",
+ "subtitle": "Ваш умный помощник",
+ "quickActions": "Быстрые действия",
+ "examples": "Примеры вопросов"
+ },
+ "actions": {
+ "copy": "Копировать",
+ "regenerate": "Перегенерировать",
+ "like": "Нравится",
+ "dislike": "Не нравится",
+ "share": "Поделиться",
+ "newChat": "Новый чат",
+ "deleteChat": "Удалить чат",
+ "editTitle": "Изменить заголовок",
+ "fullscreen": "На весь экран",
+ "exitFullscreen": "Выход из полноэкранного режима",
+ "reply": "Ответить",
+ "providerConfig": "Настройки AI",
+ "toolsUsed": "Использованные инструменты",
+ "toolCallUsed": "Использован инструмент {name}",
+ "pythonCodeAnalysis": "Использован анализ кода Python"
+ },
+ "ipython": {
+ "output": "Вывод"
+ },
+ "conversation": {
+ "newConversation": "Новый чат",
+ "noHistory": "История диалогов пуста",
+ "systemStatus": "Статус системы",
+ "llmService": "Сервис LLM",
+ "speechToText": "Преобразование речи",
+ "editDisplayName": "Изменить имя чата",
+ "displayName": "Имя чата",
+ "displayNameUpdated": "Имя чата обновлено",
+ "displayNameUpdateFailed": "Не удалось обновить имя чата",
+ "confirmDelete": "Вы уверены, что хотите удалить «{name}»? Это действие необратимо."
+ },
+ "modes": {
+ "darkMode": "Темная тема",
+ "lightMode": "Светлая тема"
+ },
+ "shortcuts": {
+ "help": "Справка",
+ "voiceRecord": "Запись голоса",
+ "pasteImage": "Вставить изображение"
+ },
+ "streaming": {
+ "enabled": "Потоковый ответ включен",
+ "disabled": "Потоковый ответ выключен",
+ "on": "Поток",
+ "off": "Обычный"
+ },
+ "transport": {
+ "title": "Протокол передачи",
+ "sse": "SSE",
+ "websocket": "WebSocket"
+ },
+ "config": {
+ "title": "Конфигурация"
+ },
+ "reasoning": {
+ "thinking": "Рассуждение"
+ },
+ "reply": {
+ "replyTo": "В ответ на",
+ "notFound": "Сообщение не найдено"
+ },
+ "project": {
+ "title": "Проект",
+ "create": "Создать проект",
+ "edit": "Изменить проект",
+ "name": "Имя проекта",
+ "emoji": "Иконка (Emoji)",
+ "description": "Описание проекта (опционально)",
+ "noSessions": "В этом проекте пока нет диалогов",
+ "confirmDelete": "Вы уверены, что хотите удалить проект «{title}»? Диалоги внутри проекта не будут удалены."
+ },
+ "time": {
+ "today": "Сегодня",
+ "yesterday": "Вчера"
+ },
+ "stats": {
+ "tokens": "Токены",
+ "inputTokens": "Входящие",
+ "outputTokens": "Исходящие",
+ "cachedTokens": "Кэшированные",
+ "duration": "Время",
+ "ttft": "Время до первого токена"
+ },
+ "refs": {
+ "title": "Ссылки",
+ "sources": "Источники"
+ },
+ "connection": {
+ "title": "Статус подключения",
+ "message": "Системе необходимо переустановить соединение с чатом.",
+ "reasons": "Это может быть вызвано следующими причинами:",
+ "reasonWindowResize": "Изменение размера окна (нормально)",
+ "reasonMultipleTabs": "Страница чата открыта в другой вкладке",
+ "reasonNetworkIssue": "Временная проблема с сетью",
+ "notice": "Примечание: для стабильной работы допускается только одно активное соединение. Если вы используете чат в нескольких вкладках, рекомендуем оставить только одну.",
+ "understand": "Понятно",
+ "status": {
+ "reconnecting": "Переподключение...",
+ "reconnected": "Соединение восстановлено",
+ "failed": "Ошибка подключения, обновите страницу"
+ }
+ },
+ "errors": {
+ "sendMessageFailed": "Ошибка отправки сообщения, попробуйте еще раз",
+ "createSessionFailed": "Ошибка создания сессии, обновите страницу"
+ }
+}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/ru-RU/features/command.json b/dashboard/src/i18n/locales/ru-RU/features/command.json
new file mode 100644
index 000000000..7d887c8ef
--- /dev/null
+++ b/dashboard/src/i18n/locales/ru-RU/features/command.json
@@ -0,0 +1,95 @@
+{
+ "title": "Управление командами",
+ "summary": {
+ "total": "Всего команд",
+ "disabled": "Отключено",
+ "conflicts": "Конфликты"
+ },
+ "conflictAlert": {
+ "title": "Обнаружены конфликты команд",
+ "description": "Сейчас конфликтуют {count} пары команд. Это может привести к одновременному срабатыванию нескольких плагинов и непредсказуемому поведению.",
+ "hint": "Нажмите «Переименовать», чтобы изменить название конфликтующей команды."
+ },
+ "table": {
+ "headers": {
+ "command": "Команда",
+ "type": "Тип",
+ "plugin": "Плагин",
+ "description": "Описание",
+ "permission": "Доступ",
+ "status": "Статус",
+ "actions": "Действия"
+ }
+ },
+ "type": {
+ "command": "Команда",
+ "group": "Группа команд",
+ "subCommand": "Под-команда"
+ },
+ "status": {
+ "enabled": "Активна",
+ "disabled": "Отключена",
+ "conflict": "Конфликт"
+ },
+ "permission": {
+ "everyone": "Все",
+ "admin": "Админ"
+ },
+ "tooltips": {
+ "enable": "Включить",
+ "disable": "Выключить",
+ "rename": "Переименовать",
+ "viewDetails": "Подробности"
+ },
+ "dialogs": {
+ "rename": {
+ "title": "Переименование команды",
+ "newName": "Новое название",
+ "aliases": "Управление алиасами",
+ "addAlias": "Добавить алиас",
+ "cancel": "Отмена",
+ "confirm": "Подтвердить"
+ },
+ "details": {
+ "title": "Детали команды",
+ "type": "Тип команды",
+ "handler": "Обработчик (Handler)",
+ "module": "Путь к модулю",
+ "originalCommand": "Исходная команда",
+ "effectiveCommand": "Действующая команда",
+ "parentGroup": "Родительская группа",
+ "subCommands": "Под-команды",
+ "aliases": "Алиасы (Синонимы)",
+ "permission": "Требования прав",
+ "conflictStatus": "Статус конфликта"
+ }
+ },
+ "messages": {
+ "toggleSuccess": "Статус команды обновлен",
+ "toggleFailed": "Не удалось изменить статус команды",
+ "renameSuccess": "Команда переименована",
+ "renameFailed": "Ошибка переименования",
+ "loadFailed": "Ошибка загрузки списка команд",
+ "updateSuccess": "Обновлено успешно",
+ "updateFailed": "Ошибка обновления"
+ },
+ "search": {
+ "placeholder": "Поиск команд..."
+ },
+ "empty": {
+ "noCommands": "Команд не найдено",
+ "noCommandsDesc": "По вашему запросу не найдено ни одной команды"
+ },
+ "filters": {
+ "all": "Все",
+ "enabled": "Активные",
+ "disabled": "Отключенные",
+ "conflict": "Конфликтующие",
+ "byPlugin": "По плагину",
+ "byType": "По типу",
+ "byPermission": "По правам",
+ "byStatus": "По статусу",
+ "showSystemPlugins": "Показывать системные плагины",
+ "systemPluginConflictHint": "Конфликт затрагивает системный плагин, его нельзя скрыть до разрешения конфликта"
+ }
+}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/ru-RU/features/config-metadata.json b/dashboard/src/i18n/locales/ru-RU/features/config-metadata.json
new file mode 100644
index 000000000..56d12c983
--- /dev/null
+++ b/dashboard/src/i18n/locales/ru-RU/features/config-metadata.json
@@ -0,0 +1,1526 @@
+{
+ "ai_group": {
+ "name": "AI",
+ "agent_runner": {
+ "description": "Запуск агентов (Agent Runner)",
+ "hint": "Выберите среду для работы AI-диалогов. По умолчанию используется встроенный агент AstrBot, поддерживающий базу знаний, персонализацию и вызов технических инструментов. Не изменяйте этот раздел, если не планируете использовать сторонние платформы, такие как Dify, Coze или DeerFlow.",
+ "provider_settings": {
+ "enable": {
+ "description": "Включить",
+ "hint": "Главный переключатель для AI-диалогов"
+ },
+ "agent_runner_type": {
+ "description": "Запуск (Runner)",
+ "labels": [
+ "Встроенный агент",
+ "Dify",
+ "Coze",
+ "Приложение Alibaba Cloud Bailian",
+ "DeerFlow"
+ ]
+ },
+ "coze_agent_runner_provider_id": {
+ "description": "ID провайдера Coze Agent Runner"
+ },
+ "dify_agent_runner_provider_id": {
+ "description": "ID провайдера Dify Agent Runner"
+ },
+ "dashscope_agent_runner_provider_id": {
+ "description": "ID провайдера Alibaba Cloud Bailian"
+ },
+ "deerflow_agent_runner_provider_id": {
+ "description": "ID провайдера DeerFlow Agent Runner"
+ }
+ }
+ },
+ "ai": {
+ "description": "Модель",
+ "hint": "При использовании сторонних сред запуска модель чата и модель описания изображений могут не работать напрямую, но некоторые плагины всё равно зависят от этих настроек.",
+ "provider_settings": {
+ "default_provider_id": {
+ "description": "Модель чата по умолчанию",
+ "hint": "Если пусто, используется первая доступная модель"
+ },
+ "fallback_chat_models": {
+ "description": "Резервные модели чата (ID)",
+ "hint": "Если текущая модель недоступна, запрос будет перенаправлен на эти модели по порядку."
+ },
+ "default_image_caption_provider_id": {
+ "description": "Модель описания изображений",
+ "hint": "Оставьте пустым для отключения; полезно для моделей без поддержки мультимодальности"
+ },
+ "image_caption_prompt": {
+ "description": "Промпт для описания изображений"
+ }
+ },
+ "provider_stt_settings": {
+ "enable": {
+ "description": "Включить преобразование речи в текст (STT)",
+ "hint": "Главный переключатель для STT"
+ },
+ "provider_id": {
+ "description": "Модель STT по умолчанию",
+ "hint": "Пользователи могут выбирать другие модели STT через команду /provider."
+ }
+ },
+ "provider_tts_settings": {
+ "enable": {
+ "description": "Включить преобразование текста в речь (TTS)",
+ "hint": "Главный переключатель для TTS"
+ },
+ "provider_id": {
+ "description": "Модель TTS по умолчанию"
+ },
+ "trigger_probability": {
+ "description": "Вероятность срабатывания TTS"
+ }
+ }
+ },
+ "persona": {
+ "description": "Персонаж",
+ "hint": "Установите персонажа по умолчанию для AI-диалогов. Управлять персонажами можно на вкладке «Персонажи».",
+ "provider_settings": {
+ "default_personality": {
+ "description": "Персонаж по умолчанию"
+ }
+ }
+ },
+ "knowledgebase": {
+ "description": "База знаний",
+ "kb_names": {
+ "description": "Список баз знаний",
+ "hint": "Поддерживается выбор нескольких баз"
+ },
+ "kb_fusion_top_k": {
+ "description": "Кол-во результатов (Fusion Search)",
+ "hint": "Количество результатов после объединения данных из нескольких баз знаний"
+ },
+ "kb_final_top_k": {
+ "description": "Итоговое кол-во результатов",
+ "hint": "Количество результатов, извлекаемых из базы знаний. Высокие значения дают больше данных, но могут добавить шума. Настройте по необходимости."
+ },
+ "kb_agentic_mode": {
+ "description": "Агентский режим извлечения (Agentic Retrieval)",
+ "hint": "Если включено, извлечение из базы знаний становится инструментом (Tool) для LLM, позволяя модели самой решать, когда обращаться к базе. Требует поддержки вызова функций (function calling) в модели."
+ }
+ },
+ "websearch": {
+ "description": "Поиск в сети",
+ "provider_settings": {
+ "web_search": {
+ "description": "Включить поиск в сети"
+ },
+ "websearch_provider": {
+ "description": "Провайдер поиска"
+ },
+ "websearch_tavily_key": {
+ "description": "API-ключ Tavily",
+ "hint": "Можно добавить несколько ключей для ротации."
+ },
+ "websearch_bocha_key": {
+ "description": "API-ключ BoCha",
+ "hint": "Можно добавить несколько ключей для ротации."
+ },
+ "websearch_baidu_app_builder_key": {
+ "description": "API-ключ Baidu Qianfan APP Builder",
+ "hint": "Ссылка: [https://console.bce.baidu.com/iam/#/iam/apikey/list](https://console.bce.baidu.com/iam/#/iam/apikey/list)"
+ },
+ "web_search_link": {
+ "description": "Показывать ссылки на источники"
+ }
+ }
+ },
+ "file_extract": {
+ "description": "Извлечение из файлов",
+ "provider_settings": {
+ "file_extract": {
+ "enable": {
+ "description": "Включить извлечение из файлов"
+ },
+ "provider": {
+ "description": "Провайдер извлечения"
+ },
+ "moonshotai_api_key": {
+ "description": "API-ключ Moonshot AI"
+ }
+ }
+ }
+ },
+ "agent_computer_use": {
+ "description": "Использование компьютера (Agent Computer Use)",
+ "hint": "Позволяет AstrBot получать доступ к вашему компьютеру или песочнице для выполнения сложных задач. См. [Режим песочницы](https://docs.astrbot.app/use/astrbot-agent-sandbox.html), [Навыки](https://docs.astrbot.app/use/skills.html)",
+ "provider_settings": {
+ "computer_use_runtime": {
+ "description": "Среда выполнения (Runtime)",
+ "hint": "'sandbox' означает запуск в изолированной среде, 'local' — локально на вашем ПК, 'none' — отключено. Если навыки загружены, выбор 'none' сделает их недоступными для агента."
+ },
+ "computer_use_require_admin": {
+ "description": "Требовать права администратора AstrBot",
+ "hint": "Если включено, только администраторы смогут использовать возможности управления компьютером. Добавить администраторов можно в конфиге платформы."
+ },
+ "sandbox": {
+ "booter": {
+ "description": "Драйвер среды песочницы"
+ },
+ "shipyard_neo_endpoint": {
+ "description": "Эндпоинт Shipyard Neo API",
+ "hint": "Адрес Bay API, по умолчанию http://127.0.0.1:8114."
+ },
+ "shipyard_neo_access_token": {
+ "description": "Токен доступа Shipyard Neo",
+ "hint": "Ключ Bay API (sk-bay-...). Оставьте пустым для автопоиска в credentials.json."
+ },
+ "shipyard_neo_profile": {
+ "description": "Профиль Shipyard Neo",
+ "hint": "Профиль песочницы, например, python-default."
+ },
+ "shipyard_neo_ttl": {
+ "description": "TTL песочницы Shipyard Neo",
+ "hint": "Время жизни песочницы в секундах."
+ },
+ "shipyard_endpoint": {
+ "description": "Эндпоинт Shipyard API",
+ "hint": "Адрес API для доступа к сервису Shipyard."
+ },
+ "shipyard_access_token": {
+ "description": "Токен доступа Shipyard",
+ "hint": "Токен доступа для работы с сервисом Shipyard."
+ },
+ "shipyard_ttl": {
+ "description": "TTL сессии Shipyard",
+ "hint": "Время жизни сессии в секундах."
+ },
+ "shipyard_max_sessions": {
+ "description": "Макс. количество сессий Shipyard",
+ "hint": "Максимальное количество сессий Shipyard, которое может поддерживать экземпляр."
+ }
+ }
+ }
+ },
+ "proactive_capability": {
+ "description": "Проактивный агент",
+ "hint": "AstrBot будет просыпаться, выполнять ваши задачи и сообщать о результатах. См. [Проактивный агент](https://docs.astrbot.app/en/use/proactive-agent.html)",
+ "provider_settings": {
+ "proactive_capability": {
+ "add_cron_tools": {
+ "description": "Включить",
+ "hint": "Если включено, агенту будут переданы инструменты для проактивной работы. Вы сможете поручать задачи на будущее, и они будут выполнены по расписанию."
+ }
+ }
+ }
+ },
+ "truncate_and_compress": {
+ "hint": "[Управление контекстом](https://docs.astrbot.app/en/use/context-compress.html)",
+ "description": "Стратегия управления контекстом",
+ "provider_settings": {
+ "max_context_length": {
+ "description": "Макс. количество раундов диалога",
+ "hint": "При превышении удаляются старые сообщения. 1 раунд = 1 пара запрос-ответ. -1 означает без ограничений."
+ },
+ "dequeue_context_length": {
+ "description": "Кол-во удаляемых раундов",
+ "hint": "Сколько раундов удалять за один раз при достижении лимита."
+ },
+ "context_limit_reached_strategy": {
+ "description": "Действие при переполнении окна контекста",
+ "labels": [
+ "Обрезать по раундам",
+ "Сжать с помощью LLM"
+ ],
+ "hint": "При выборе 'Обрезать' удаляются старые сообщения. При выборе 'Сжать' используется модель для суммаризации контекста."
+ },
+ "llm_compress_instruction": {
+ "description": "Инструкция для сжатия контекста",
+ "hint": "Если пусто, используется промпт по умолчанию."
+ },
+ "llm_compress_keep_recent": {
+ "description": "Сохранять последние раунды при сжатии",
+ "hint": "Всегда оставлять последние N раундов диалога без изменений при сжатии."
+ },
+ "llm_compress_provider_id": {
+ "description": "Модель для сжатия контекста",
+ "hint": "Если не выбрано, произойдет откат к стратегии удаления сообщений."
+ }
+ }
+ },
+ "others": {
+ "description": "Прочие настройки",
+ "provider_settings": {
+ "display_reasoning_text": {
+ "description": "Отображать процесс рассуждения (Reasoning)"
+ },
+ "llm_safety_mode": {
+ "description": "Безопасный режим",
+ "hint": "Добавляет защитные фильтры к ответам модели."
+ },
+ "safety_mode_strategy": {
+ "description": "Стратегия безопасного режима",
+ "hint": "Как применять защитные фильтры."
+ },
+ "identifier": {
+ "description": "Идентификация пользователя",
+ "hint": "Если включено, информация об ID пользователя будет включена в промпт."
+ },
+ "group_name_display": {
+ "description": "Отображать название группы",
+ "hint": "Если включено, название группы будет включено в промпт на поддерживаемых платформах (OneBot v11)."
+ },
+ "datetime_system_prompt": {
+ "description": "Осведомленность о реальном времени",
+ "hint": "Если включено, информация о текущем времени будет добавлена в системный промпт."
+ },
+ "show_tool_use_status": {
+ "description": "Выводить статус вызова функций"
+ },
+ "show_tool_call_result": {
+ "description": "Выводить результаты работы инструментов",
+ "hint": "Работает только при включенном статусе вызова функций. Показывает макс. 70 символов."
+ },
+ "sanitize_context_by_modalities": {
+ "description": "Очистка истории по модальностям",
+ "hint": "Если включено, очищает контекст перед запросом, удаляя блоки (например, изображения), которые не поддерживаются выбранным провайдером."
+ },
+ "max_quoted_fallback_images": {
+ "description": "Лимит загрузки изображений из пересланных сообщений",
+ "hint": "Максимальное количество изображений при парсинге цитируемых сообщений."
+ },
+ "quoted_message_parser": {
+ "max_component_chain_depth": {
+ "description": "Глубина парсинга богатого текста",
+ "hint": "Максимальная глубина рекурсии при парсинге сложных компонентов в пересланных сообщениях."
+ },
+ "max_forward_node_depth": {
+ "description": "Глубина вложенности пересылок",
+ "hint": "Максимальная глубина парсинга вложенных пересланных узлов."
+ },
+ "max_forward_fetch": {
+ "description": "Лимит рекурсивного получения пересылок",
+ "hint": "Максимальное количество операций get_forward_msg."
+ },
+ "warn_on_action_failure": {
+ "description": "Предупреждать при ошибке парсинга пересылок",
+ "hint": "Если включено, логирует предупреждения при неудачных попытках получения сообщений."
+ }
+ },
+ "max_agent_step": {
+ "description": "Макс. количество раундов вызова инструментов"
+ },
+ "tool_call_timeout": {
+ "description": "Таймаут вызова инструмента (сек)"
+ },
+ "tool_schema_mode": {
+ "description": "Режим схемы инструментов",
+ "hint": "Skills-like сначала отправляет имя/описание и дозапрашивает параметры; Full отправляет полную схему сразу.",
+ "labels": [
+ "Skills-like (двухэтапный)",
+ "Полная схема (Full)"
+ ]
+ },
+ "streaming_response": {
+ "description": "Потоковый вывод (Streaming)"
+ },
+ "unsupported_streaming_strategy": {
+ "description": "Для платформ без поддержки стриминга",
+ "hint": "Выберите метод обработки, если платформа не поддерживает потоковые ответы. 'Сегментированный ответ' отправляет части текста по мере появления знаков препинания.",
+ "labels": [
+ "Сегментированный ответ в реальном времени",
+ "Отключить стриминг"
+ ]
+ },
+ "wake_prefix": {
+ "description": "Дополнительный префикс пробуждения LLM",
+ "hint": "Если префикс пробуждения '/', а дополнительные — 'chat', то потребуется '/chat' для активации LLM."
+ },
+ "prompt_prefix": {
+ "description": "Промпт пользователя",
+ "hint": "Вы можете использовать {{prompt}} как заполнитель для ввода. Если заполнитель не указан, он будет добавлен перед текстом пользователя."
+ },
+ "reachability_check": {
+ "description": "Проверка доступности провайдеров",
+ "hint": "При выполнении команды /provider проверяет связь со всеми моделями. Это может расходовать токены."
+ }
+ },
+ "provider_tts_settings": {
+ "dual_output": {
+ "description": "Выводить и голос, и текст при включенном TTS"
+ }
+ }
+ }
+ },
+ "platform_group": {
+ "name": "Платформы",
+ "platform": {
+ "description": "Адаптеры сообщений",
+ "active_send_mode": {
+ "description": "Использовать API активной отправки"
+ },
+ "appid": {
+ "description": "ID приложения",
+ "hint": "Обязательно для QQ Official Bot. См. документацию."
+ },
+ "callback_server_host": {
+ "description": "Хост callback-сервера",
+ "hint": "Оставьте пустым для отключения."
+ },
+ "card_template_id": {
+ "description": "ID шаблона карточки",
+ "hint": "Необязательно. Для интерактивных карточек DingTalk."
+ },
+ "discord_activity_name": {
+ "description": "Название активности Discord",
+ "hint": "Статус бота в Discord. Оставьте пустым для отключения."
+ },
+ "discord_command_register": {
+ "description": "Регистрировать слэш-команды Discord",
+ "hint": "Если включено, команды плагинов будут зарегистрированы как /команды Discord."
+ },
+ "discord_proxy": {
+ "description": "Proxy URL для Discord",
+ "hint": "Формат: http://ip:port"
+ },
+ "discord_token": {
+ "description": "Токен бота Discord",
+ "hint": "Введите сюда токен вашего Discord-бота."
+ },
+ "enable": {
+ "description": "Включить",
+ "hint": "Включить этот адаптер. Отключенные адаптеры не будут получать сообщения."
+ },
+ "enable_group_c2c": {
+ "description": "Включить личные сообщения из списка",
+ "hint": "Позволяет боту получать личные сообщения из списка QQ (может потребоваться добавление в друзья)."
+ },
+ "enable_guild_direct_message": {
+ "description": "Включить ЛС в гильдиях",
+ "hint": "Позволяет боту получать прямые сообщения в рамках гильдий."
+ },
+ "id": {
+ "description": "Имя бота",
+ "hint": "Отображаемое имя бота"
+ },
+ "is_sandbox": {
+ "description": "Режим песочницы"
+ },
+ "kf_name": {
+ "description": "Имя аккаунта службы поддержки WeChat",
+ "hint": "Необязательно. См. https://kf.weixin.qq.com/kf/frame#/accounts"
+ },
+ "lark_bot_name": {
+ "description": "Имя бота Lark",
+ "hint": "Должно быть точным для работы через @ упоминания."
+ },
+ "lark_connection_mode": {
+ "description": "Режим подписки",
+ "labels": [
+ "Режим длинного соединения",
+ "Режим Webhook"
+ ]
+ },
+ "lark_encrypt_key": {
+ "description": "Ключ шифрования",
+ "hint": "Для расшифровки данных обратного вызова Lark."
+ },
+ "lark_verification_token": {
+ "description": "Токен верификации",
+ "hint": "Для проверки запросов обратного вызова Lark."
+ },
+ "misskey_allow_insecure_downloads": {
+ "description": "Разрешить небезопасные загрузки (без SSL)",
+ "hint": "Отключает проверку SSL если у удаленного сервера проблемы с сертификатами. Используйте с осторожностью."
+ },
+ "misskey_default_visibility": {
+ "description": "Видимость постов по умолчанию",
+ "hint": "public — всем, home — в ленте, followers — только подписчикам."
+ },
+ "misskey_download_chunk_size": {
+ "description": "Размер чанка загрузки (байт)",
+ "hint": "Влияет на потребление памяти при загрузке файлов."
+ },
+ "misskey_download_timeout": {
+ "description": "Таймаут загрузки (сек)",
+ "hint": "Максимльное время на загрузку файлов из сети."
+ },
+ "misskey_enable_chat": {
+ "description": "Включить ответы в чатах",
+ "hint": "Бот будет отвечать на личные сообщения в Misskey."
+ },
+ "misskey_enable_file_upload": {
+ "description": "Включить загрузку файлов в Misskey",
+ "hint": "Бот будет загружать файлы из сообщений в хранилище Misskey."
+ },
+ "misskey_instance_url": {
+ "description": "URL инстанса Misskey",
+ "hint": "Например, https://misskey.example"
+ },
+ "misskey_local_only": {
+ "description": "Только локально (без федерации)",
+ "hint": "Посты бота будут видны только на текущем инстансе."
+ },
+ "misskey_max_download_bytes": {
+ "description": "Макс. размер загрузки (байт)",
+ "hint": "Лимит на размер загружаемых файлов для предотвращения нехватки памяти."
+ },
+ "misskey_token": {
+ "description": "Токен доступа Misskey",
+ "hint": "Токен доступа к API, созданный в настройках сервиса подключения."
+ },
+ "misskey_upload_concurrency": {
+ "description": "Лимит одновременных загрузок",
+ "hint": "По умолчанию 3."
+ },
+ "misskey_upload_folder": {
+ "description": "ID папки в хранилище",
+ "hint": "Необязательно. Если пусто — в корень."
+ },
+ "port": {
+ "description": "Порт callback-сервера",
+ "hint": "Оставьте пустым для отключения."
+ },
+ "satori_api_base_url": {
+ "description": "Эндпоинт Satori API",
+ "hint": "Базовый URL для Satori API."
+ },
+ "satori_auto_reconnect": {
+ "description": "Автоматическое переподключение",
+ "hint": "Переподключать WebSocket при разрыве."
+ },
+ "satori_endpoint": {
+ "description": "WebSocket эндпоинт Satori",
+ "hint": "WebSocket-эндпоинт для событий Satori."
+ },
+ "satori_heartbeat_interval": {
+ "description": "Интервал сердцебиения Satori",
+ "hint": "Интервал в секундах между отправкой heartbeat-сообщений."
+ },
+ "satori_reconnect_delay": {
+ "description": "Задержка переподключения Satori",
+ "hint": "Задержка перед попыткой переподключения (в секундах)."
+ },
+ "satori_token": {
+ "description": "Токен Satori",
+ "hint": "Токен для аутентификации в Satori API."
+ },
+ "secret": {
+ "description": "Секрет (Secret)",
+ "hint": "Обязательно."
+ },
+ "slack_connection_mode": {
+ "description": "Режим соединения Slack",
+ "hint": "webhook — через вебхуки, socket — через Socket Mode."
+ },
+ "slack_webhook_host": {
+ "description": "Хост вебхука Slack",
+ "hint": "Действительно только если режим подключения Slack установлен как `webhook`."
+ },
+ "slack_webhook_path": {
+ "description": "Путь вебхука Slack",
+ "hint": "Действительно только если режим подключения Slack установлен как `webhook`."
+ },
+ "slack_webhook_port": {
+ "description": "Порт вебхука Slack",
+ "hint": "Действительно только если режим подключения Slack установлен как `webhook`."
+ },
+ "telegram_command_auto_refresh": {
+ "description": "Автообновление команд Telegram",
+ "hint": "Если включено, AstrBot автоматически обновляет команды Telegram во время выполнения. (Одна эта настройка не имеет эффекта)"
+ },
+ "telegram_command_register": {
+ "description": "Регистрация команд Telegram",
+ "hint": "Если включено, AstrBot автоматически регистрирует команды Telegram."
+ },
+ "telegram_command_register_interval": {
+ "description": "Интервал автообновления команд Telegram",
+ "hint": "Интервал автоматического обновления команд Telegram в секундах."
+ },
+ "telegram_token": {
+ "description": "Токен бота",
+ "hint": "Если вы находитесь в материковом Китае, установите прокси или измените api_base в разделе «Другие настройки»."
+ },
+ "type": {
+ "description": "Тип адаптера"
+ },
+ "unified_webhook_mode": {
+ "description": "Единый режим Webhook",
+ "hint": "Использовать общий вход вебхуков AstrBot без открытия новых портов. URL: /api/platform/webhook/{uuid}."
+ },
+ "webhook_uuid": {
+ "description": "UUID вебхука",
+ "hint": "Создается автоматически при добавлении платформы."
+ },
+ "wecom_ai_bot_name": {
+ "description": "Имя бота WeCom AI",
+ "hint": "Должно быть указано верно, иначе некоторые команды не будут работать."
+ },
+ "wecom_ai_bot_connection_mode": {
+ "description": "Режим соединения WeCom AI",
+ "hint": "webhook требует Token/AESKey; long_connection требует BotID/Secret."
+ },
+ "wecomaibot_friend_message_welcome_text": {
+ "description": "Приветствие в ЛС WeCom AI",
+ "hint": "Отправляется при первом входе пользователя в чат за день."
+ },
+ "wecomaibot_init_respond_text": {
+ "description": "Начальный текст ответа WeCom AI",
+ "hint": "Первое сообщение, которое отправляет бот при получении запроса."
+ },
+ "wecomaibot_token": {
+ "description": "Токен WeCom AI",
+ "hint": "Используется для аутентификации в режиме обратного вызова webhook."
+ },
+ "wecomaibot_encoding_aes_key": {
+ "description": "EncodingAESKey для ИИ-бота WeCom",
+ "hint": "Используется для шифрования/дешифрования сообщений в режиме обратного вызова webhook."
+ },
+ "wecomaibot_ws_bot_id": {
+ "description": "BotID для длинного соединения",
+ "hint": "Учетные данные BotID для режима длительного соединения ИИ-бота WeCom."
+ },
+ "wecomaibot_ws_secret": {
+ "description": "Secret для длинного соединения",
+ "hint": "Учетные данные Secret для режима длительного соединения ИИ-бота WeCom."
+ },
+ "wecomaibot_ws_url": {
+ "description": "WebSocket URL для длинного соединения",
+ "hint": "По умолчанию используется wss://openws.work.weixin.qq.com, обычно не требует изменений."
+ },
+ "wecomaibot_heartbeat_interval": {
+ "description": "Интервал сердцебиения соединения",
+ "hint": "Интервал пульса (в секундах) в режиме длительного соединения. Рекомендуется 30 секунд."
+ },
+ "wpp_active_message_poll": {
+ "description": "Включить активный опрос сообщений",
+ "hint": "Включите, только если сообщения WeChat приходят с задержкой."
+ },
+ "wpp_active_message_poll_interval": {
+ "description": "Интервал опроса сообщений",
+ "hint": "По умолчанию 3 сек."
+ },
+ "ws_reverse_host": {
+ "description": "Хост реверсивного WebSocket",
+ "hint": "AstrBot выступает в роли сервера."
+ },
+ "ws_reverse_port": {
+ "description": "Порт реверсивного WebSocket"
+ },
+ "ws_reverse_token": {
+ "description": "Токен реверсивного WebSocket",
+ "hint": "Токен обратного WebSocket (Reverse WebSocket). Если не задан, проверка токена будет отключена."
+ },
+ "msg_push_webhook_url": {
+ "description": "URL вебхука для пуш-сообщений WeCom",
+ "hint": "Рекомендуется для корректной отправки всех типов сообщений."
+ },
+ "only_use_webhook_url_to_send": {
+ "description": "Отправлять ответы только через Webhook",
+ "hint": "Все ответы WeCom AI Bot будут идти через вебхук пуш-сообщений. Поддерживает больше типов контента."
+ },
+ "kook_bot_token": {
+ "description": "Токен бота",
+ "type": "string",
+ "hint": "Обязательно. Токен бота, полученный на платформе разработчиков KOOK."
+ },
+ "kook_bot_nickname": {
+ "description": "Никнейм бота",
+ "type": "string",
+ "hint": "Сообщения от пользователя с таким никнеймом будут игнорироваться."
+ },
+ "kook_reconnect_delay": {
+ "description": "Задержка переподключения",
+ "type": "int",
+ "hint": "Задержка перед повторным подключением (в секундах), используется стратегия экспоненциальной задержки (exponential backoff)."
+ },
+ "kook_max_reconnect_delay": {
+ "description": "Макс. задержка переподключения",
+ "type": "int",
+ "hint": "Максимальное значение задержки для повторного подключения (в секундах)."
+ },
+ "kook_max_retry_delay": {
+ "description": "Макс. задержка повтора",
+ "type": "int",
+ "hint": "Максимальное время задержки для повторных попыток (в секундах)."
+ },
+ "kook_heartbeat_interval": {
+ "description": "Интервал сердцебиения",
+ "type": "int",
+ "hint": "Интервал времени для проверки пульса (в секундах)."
+ },
+ "kook_heartbeat_timeout": {
+ "description": "Таймаут сердцебиения",
+ "type": "int",
+ "hint": "Длительность ожидания (таймаут) для проверки пульса (в секундах)."
+ },
+ "kook_max_heartbeat_failures": {
+ "description": "Макс. количество сбоев сердцебиения",
+ "type": "int",
+ "hint": "Максимально допустимое количество сбоев пульса; если лимит превышен, соединение будет разорвано."
+ },
+ "kook_max_consecutive_failures": {
+ "description": "Макс. количество последовательных сбоев",
+ "type": "int",
+ "hint": "Максимально допустимое количество последовательных сбоев; если лимит превышен, повторные попытки будут остановлены."
+ }
+ },
+ "general": {
+ "description": "Общие",
+ "admins_id": {
+ "description": "ID администраторов"
+ },
+ "platform_settings": {
+ "unique_session": {
+ "description": "Изолировать сессии",
+ "hint": "У каждого участника группы будет свой независимый контекст."
+ },
+ "friend_message_needs_wake_prefix": {
+ "description": "Личные сообщения требуют префикс пробуждения"
+ },
+ "reply_prefix": {
+ "description": "Префикс текста ответа"
+ },
+ "reply_with_mention": {
+ "description": "Упоминать отправителя в ответе"
+ },
+ "reply_with_quote": {
+ "description": "Цитировать сообщение отправителя в ответе"
+ },
+ "forward_threshold": {
+ "description": "Порог количества слов для пересылки"
+ },
+ "empty_mention_waiting": {
+ "description": "Реагировать на пустое упоминание (@бота)"
+ }
+ },
+ "wake_prefix": {
+ "description": "Префикс пробуждения"
+ },
+ "disable_builtin_commands": {
+ "description": "Отключить встроенные команды",
+ "hint": "Отключает help, provider, model и другие базовые команды."
+ }
+ },
+ "whitelist": {
+ "description": "Белый список",
+ "platform_settings": {
+ "enable_id_white_list": {
+ "description": "Включить белый список",
+ "hint": "Бот будет отвечать только в разрешенных сессиях."
+ },
+ "id_whitelist": {
+ "description": "Список разрешенных ID",
+ "hint": "Используйте /sid для получения ID."
+ },
+ "id_whitelist_log": {
+ "description": "Выводить логи",
+ "hint": "Логировать попытки доступа от пользователей не из белого списка."
+ },
+ "wl_ignore_admin_on_group": {
+ "description": "Администраторы в группах обходят белый список"
+ },
+ "wl_ignore_admin_on_friend": {
+ "description": "Администраторы в ЛС обходят белый список"
+ }
+ }
+ },
+ "rate_limit": {
+ "description": "Лимит частоты",
+ "platform_settings": {
+ "rate_limit": {
+ "time": {
+ "description": "Время лимита сообщений (сек)"
+ },
+ "count": {
+ "description": "Количество сообщений для лимита"
+ },
+ "strategy": {
+ "description": "Стратегия лимитирования"
+ }
+ }
+ }
+ },
+ "content_safety": {
+ "description": "Безопасность контента",
+ "content_safety": {
+ "also_use_in_response": {
+ "description": "Проверять также ответы модели"
+ },
+ "baidu_aip": {
+ "enable": {
+ "description": "Использовать Baidu Content Safety",
+ "hint": "Требуется установка библиотеки baidu-aip."
+ },
+ "app_id": {
+ "description": "App ID"
+ },
+ "api_key": {
+ "description": "API Key"
+ },
+ "secret_key": {
+ "description": "Secret Key"
+ }
+ },
+ "internal_keywords": {
+ "enable": {
+ "description": "Проверка по ключевым словам"
+ },
+ "extra_keywords": {
+ "description": "Дополнительные слова",
+ "hint": "Список запрещенных слов, поддерживает регулярные выражения."
+ }
+ }
+ }
+ },
+ "t2i": {
+ "description": "Текст в изображение",
+ "t2i": {
+ "description": "Вывод текста картинкой"
+ },
+ "t2i_word_threshold": {
+ "description": "Порог количества слов для перевода в картинку"
+ }
+ },
+ "others": {
+ "description": "Прочие настройки",
+ "platform_settings": {
+ "ignore_bot_self_message": {
+ "description": "Игнорировать собственные сообщения бота"
+ },
+ "ignore_at_all": {
+ "description": "Игнорировать события @all"
+ },
+ "no_permission_reply": {
+ "description": "Ответ при отсутствии прав у пользователя"
+ }
+ },
+ "platform_specific": {
+ "lark": {
+ "pre_ack_emoji": {
+ "enable": {
+ "description": "[Lark] Пре-эмодзи подтверждения"
+ },
+ "emojis": {
+ "description": "Список эмодзи (Lark Enum Names)",
+ "hint": "Справка по именам эмодзи Lark."
+ }
+ }
+ },
+ "telegram": {
+ "pre_ack_emoji": {
+ "enable": {
+ "description": "[Telegram] Пре-эмодзи подтверждения"
+ },
+ "emojis": {
+ "description": "Список эмодзи (Unicode)",
+ "hint": "Telegram поддерживает ограниченный набор реакций."
+ }
+ }
+ },
+ "discord": {
+ "pre_ack_emoji": {
+ "enable": {
+ "description": "[Discord] Пре-эмодзи подтверждения"
+ },
+ "emojis": {
+ "description": "Список эмодзи (Unicode или имя эмодзи)",
+ "hint": "Введите Unicode эмодзи, напр. 👍, 🤔, ⏳"
+ }
+ }
+ }
+ }
+ }
+ },
+ "plugin_group": {
+ "name": "Плагины",
+ "plugin": {
+ "description": "Управление плагинами",
+ "plugin_set": {
+ "description": "Доступные плагины",
+ "hint": "Все невыключенные плагины включены по умолчанию. Если плагин отключен на странице плагинов, выбор здесь не будет иметь силы."
+ }
+ }
+ },
+ "ext_group": {
+ "name": "Расширения (Extensions)",
+ "segmented_reply": {
+ "description": "Сегментированный ответ",
+ "platform_settings": {
+ "segmented_reply": {
+ "enable": {
+ "description": "Включить сегментированные ответы"
+ },
+ "only_llm_result": {
+ "description": "Сегментировать только ответы LLM"
+ },
+ "interval_method": {
+ "description": "Метод интервала",
+ "hint": "random — случайное время, log — расчет на основе длины сообщения: $y=log_{log\\_base}(x)$, где x — количество знаков, y — секунды."
+ },
+ "interval": {
+ "description": "Случайный интервал времени",
+ "hint": "Формат: минимум,максимум (напр., 1.5,3.5)"
+ },
+ "log_base": {
+ "description": "Основание логарифма",
+ "hint": "Основание для логарифмических интервалов, по умолчанию 2.6. Диапазон: 1.0-10.0."
+ },
+ "words_count_threshold": {
+ "description": "Порог сегментации (количество знаков)",
+ "hint": "Порог количества знаков для сегментированного ответа. Сообщения короче этого лимита будут сегментированы, длиннее — отправлены целиком."
+ },
+ "split_mode": {
+ "description": "Режим разделения",
+ "hint": "Используется для сегментации сообщения. По умолчанию разделяется знаками препинания (точка, вопрос и т.д.). Например, `[。?!]` удалит все точки, вопросительные и восклицательные знаки. re.findall(r'', text)",
+ "labels": [
+ "Регулярное выражение",
+ "Список слов"
+ ]
+ },
+ "regex": {
+ "description": "Регулярное выражение для сегментации",
+ "hint": "Используется для поиска точек разделения с помощью регулярного выражения. Рекомендуется использовать паттерны, соответствующие разделителям."
+ },
+ "split_words": {
+ "description": "Список слов-разделителей",
+ "hint": "Разделять при обнаружении любого слова из списка"
+ },
+ "content_cleanup_rule": {
+ "description": "Регулярное выражение для фильтрации контента",
+ "hint": "Удаляет указанный контент из сегментированных частей. Например, `[。?!]` удалит точки, вопросы и восклицательные знаки."
+ }
+ }
+ }
+ },
+ "ltm": {
+ "description": "Контекстная осведомленность в группах (ранее — Улучшение памяти чата)",
+ "provider_ltm_settings": {
+ "group_icl_enable": {
+ "description": "Включить осведомленность о контексте группы"
+ },
+ "group_message_max_cnt": {
+ "description": "Максимальное количество сообщений"
+ },
+ "image_caption": {
+ "description": "Автоматическое понимание изображений",
+ "hint": "Требуется настройка модели описания изображений для группового чата."
+ },
+ "image_caption_provider_id": {
+ "description": "Модель описания изображений для групп",
+ "hint": "Используется для понимания изображений в контексте группового чата, настраивается отдельно от основной модели."
+ },
+ "active_reply": {
+ "enable": {
+ "description": "Активный ответ"
+ },
+ "method": {
+ "description": "Метод активного ответа"
+ },
+ "possibility_reply": {
+ "description": "Вероятность ответа",
+ "hint": "Значение от 0.0 до 1.0"
+ },
+ "whitelist": {
+ "description": "Белый список для активных ответов",
+ "hint": "Фильтрация отключена, если список пуст. Используйте /sid для получения ID."
+ }
+ }
+ }
+ }
+ },
+ "system_group": {
+ "name": "Система",
+ "system": {
+ "description": "Системные настройки",
+ "t2i_strategy": {
+ "description": "Стратегия текст-в-изображение",
+ "hint": "Стратегия текст-в-изображение. `remote` — удаленный рендеринг, `local` — библиотека PIL. Для локального режима положите font.ttf в data/."
+ },
+ "t2i_endpoint": {
+ "description": "Эндпоинт API сервиса текст-в-изображение",
+ "hint": "Использовать API AstrBot, если пусто"
+ },
+ "t2i_template": {
+ "description": "Пользовательский шаблон текст-в-изображение",
+ "hint": "Если включено, можно использовать свои HTML-шаблоны."
+ },
+ "t2i_active_template": {
+ "description": "Текущий активный шаблон рендеринга",
+ "hint": "Значение управляется на странице шаблонов."
+ },
+ "log_level": {
+ "description": "Уровень логирования консоли",
+ "hint": "Уровень логирования в консоли."
+ },
+ "log_file_enable": {
+ "description": "Включить логирование в файл",
+ "hint": "Записывать логи в файл."
+ },
+ "log_file_path": {
+ "description": "Путь к файлу логов",
+ "hint": "Пути относительно data/, напр. logs/astrbot.log."
+ },
+ "log_file_max_mb": {
+ "description": "Макс. размер файла логов (МБ)",
+ "hint": "Ротация при достижении размера. По умолчанию 20МБ."
+ },
+ "temp_dir_max_size": {
+ "description": "Лимит размера временной директории (МБ)",
+ "hint": "Лимит временной папки (МБ). Система проверяет каждые 10 минут и удаляет старое при переполнении."
+ },
+ "trace_log_enable": {
+ "description": "Включить логирование трассировки",
+ "hint": "Записывать трассировку в отдельный файл."
+ },
+ "trace_log_path": {
+ "description": "Путь к файлу логов трассировки",
+ "hint": "Относительные пути определяются относительно директории данных, например, logs/astrbot.trace.log; абсолютные пути также поддерживаются."
+ },
+ "trace_log_max_mb": {
+ "description": "Макс. размер файла логов трассировки (МБ)",
+ "hint": "Ротация при достижении размера. По умолчанию 20МБ."
+ },
+ "pip_install_arg": {
+ "description": "Дополнительные аргументы установки pip",
+ "hint": "При установке зависимостей можно указать аргументы pip, напр. --break-system-package."
+ },
+ "pypi_index_url": {
+ "description": "URL репозитория PyPI",
+ "hint": "URL репозитория PyPI. По умолчанию: [https://mirrors.aliyun.com/pypi/simple/](https://mirrors.aliyun.com/pypi/simple/)"
+ },
+ "callback_api_base": {
+ "description": "Внешний адрес для Callback API",
+ "hint": "Используется для сервисов, требующих обратных выливов (например, в песочнице)."
+ },
+ "dashboard": {
+ "ssl": {
+ "enable": {
+ "description": "Включить HTTPS для WebUI",
+ "hint": "Если включено, панель управления работает по HTTPS."
+ },
+ "cert_file": {
+ "description": "Путь к файлу сертификата SSL",
+ "hint": "Путь к файлу сертификата (PEM)."
+ },
+ "key_file": {
+ "description": "Путь к ключу SSL",
+ "hint": "Путь к приватному ключу (PEM)."
+ },
+ "ca_certs": {
+ "description": "Путь к сертификату CA SSL",
+ "hint": "Опционально. Путь к сертификату CA."
+ }
+ }
+ },
+ "timezone": {
+ "description": "Часовой пояс",
+ "hint": "Например, Europe/Moscow."
+ },
+ "http_proxy": {
+ "description": "HTTP прокси",
+ "hint": "Формат: http://user:pass@ip:port"
+ },
+ "no_proxy": {
+ "description": "Список исключений прокси"
+ }
+ }
+ },
+ "provider_group": {
+ "provider": {
+ "genie_onnx_model_dir": {
+ "description": "Директория моделей ONNX",
+ "hint": "Путь к директории с файлами моделей ONNX"
+ },
+ "genie_language": {
+ "description": "Язык"
+ },
+ "xai_native_search": {
+ "description": "Включить нативный поиск",
+ "hint": "Если включено, использует Live Search от xAI для веб-запросов (тарифицируется отдельно). Применимо только к провайдерам xAI."
+ },
+ "rerank_api_base": {
+ "description": "Base URL API модели Rerank",
+ "hint": "AstrBot добавляет /v1/rerank к URL запроса."
+ },
+ "rerank_api_key": {
+ "description": "API Key",
+ "hint": "Оставьте пустым, если API key не требуется."
+ },
+ "rerank_model": {
+ "description": "Имя модели Rerank"
+ },
+ "return_documents": {
+ "description": "Возвращать исходные документы в результатах Rerank",
+ "hint": "По умолчанию false для снижения сетевой нагрузки."
+ },
+ "instruct": {
+ "description": "Описание задачи для Rerank",
+ "hint": "Эффективно только для моделей qwen3-rerank. Рекомендуется писать на английском."
+ },
+ "launch_model_if_not_running": {
+ "description": "Автозапуск модели",
+ "hint": "Если модель не запущена в Xinference, попытаться запустить её автоматически. Рекомендуется отключать в продакшене."
+ },
+ "modalities": {
+ "description": "Возможности модели",
+ "hint": "Поддерживаемые модальности. Если модель не поддерживает изображения, снимите галочку с 'Image'.",
+ "labels": [
+ "Текст",
+ "Изображение",
+ "Инструменты"
+ ]
+ },
+ "custom_headers": {
+ "description": "Заголовки запроса",
+ "hint": "Пары ключ/значение будут добавлены в заголовки запроса (default_headers). Значения должны быть строками."
+ },
+ "custom_extra_body": {
+ "description": "Параметры тела запроса",
+ "hint": "Добавление дополнительных параметров в запрос (temperature, top_p и др.).",
+ "template_schema": {
+ "temperature": {
+ "description": "Температура",
+ "hint": "Контролирует случайность, обычно от 0 до 2. Чем выше, тем более случайные ответы.",
+ "name": "Температура"
+ },
+ "top_p": {
+ "description": "Top-p семплирование",
+ "hint": "Параметр ядерного семплирования (Nucleus sampling), обычно 0-1.",
+ "name": "Top-p"
+ },
+ "max_tokens": {
+ "description": "Макс. токенов",
+ "hint": "Максимальное количество генерируемых токенов.",
+ "name": "Макс. токены"
+ }
+ }
+ },
+ "gpt_weights_path": {
+ "description": "Путь к файлу модели GPT",
+ "hint": "Файл .ckpt. Используйте абсолютный путь без кавычек. Оставьте пустым для использования встроенной модели GPT_SoVITS."
+ },
+ "sovits_weights_path": {
+ "description": "Путь к файлу модели SoVITS",
+ "hint": "Файл .pth. Используйте абсолютный путь без кавычек. Оставьте пустым для использования встроенной модели GPT_SoVITS."
+ },
+ "gsv_default_parms": {
+ "description": "Параметры GPT_SoVITS по умолчанию",
+ "hint": "Путь к эталонному аудио и текст обязательны; остальные параметры опциональны.",
+ "gsv_ref_audio_path": {
+ "description": "Путь к эталонному аудио",
+ "hint": "Обязательно! Используйте абсолютный путь без кавычек."
+ },
+ "gsv_prompt_text": {
+ "description": "Текст эталонного аудио",
+ "hint": "Обязательно! Укажите содержание эталонного аудио."
+ },
+ "gsv_prompt_lang": {
+ "description": "Язык текста эталонного аудио",
+ "hint": "Язык текста эталонного аудио; по умолчанию китайский."
+ },
+ "gsv_aux_ref_audio_paths": {
+ "description": "Пути к вспомогательным эталонным аудио",
+ "hint": "Вспомогательные файлы эталонного аудио; опционально."
+ },
+ "gsv_text_lang": {
+ "description": "Язык текста",
+ "hint": "По умолчанию китайский."
+ },
+ "gsv_top_k": {
+ "description": "Разнообразие речи",
+ "hint": ""
+ },
+ "gsv_top_p": {
+ "description": "Порог ядерного семплирования",
+ "hint": ""
+ },
+ "gsv_temperature": {
+ "description": "Случайность речи",
+ "hint": ""
+ },
+ "gsv_text_split_method": {
+ "description": "Метод разделения текста",
+ "hint": "Варианты: `cut0` без разделения, `cut1` каждые 4 предложения, `cut2` каждые 50 знаков, `cut3` по китайской точке, `cut4` по английской точке, `cut5` по знакам препинания."
+ },
+ "gsv_batch_size": {
+ "description": "Размер пакета (Batch size)",
+ "hint": ""
+ },
+ "gsv_batch_threshold": {
+ "description": "Порог пакета (Batch threshold)",
+ "hint": "API Key"
+ },
+ "gsv_split_bucket": {
+ "description": "Разделять текст на корзины для параллельной обработки",
+ "hint": "API Base URL"
+ },
+ "gsv_speed_factor": {
+ "description": "Скорость воспроизведения речи",
+ "hint": "1 — исходная скорость."
+ },
+ "gsv_fragment_interval": {
+ "description": "Интервал между сегментами речи",
+ "hint": "Скорость речи для синтеза, диапазон [0.5, 2], по умолчанию 1.0. Большее значение — быстрее."
+ },
+ "gsv_streaming_mode": {
+ "description": "Включить потоковый режим",
+ "hint": "голос"
+ },
+ "gsv_seed": {
+ "description": "Случайное число (Seed)",
+ "hint": "Для воспроизводимости результатов."
+ },
+ "gsv_parallel_infer": {
+ "description": "Параллельный вывод (Inference)",
+ "hint": "reference_id"
+ },
+ "gsv_repetition_penalty": {
+ "description": "Штраф за повторение",
+ "hint": "API Key"
+ },
+ "gsv_media_type": {
+ "description": "Тип медиафайла",
+ "hint": "Рекомендуется: wav"
+ }
+ },
+ "embedding_dimensions": {
+ "description": "Размерность эмбеддингов",
+ "hint": "Размерность векторов эмбеддингов. Зависит от модели. Должно быть указано верно для работы векторной базы данных."
+ },
+ "embedding_model": {
+ "description": "Модель эмбеддингов",
+ "hint": "Имя модели эмбеддингов."
+ },
+ "embedding_api_key": {
+ "description": "API Base URL"
+ },
+ "embedding_api_base": {
+ "description": "Адрес прокси-сервера"
+ },
+ "openai_embedding": {
+ "hint": "OpenAI Embedding автоматически добавляет /v1 при запросе."
+ },
+ "gemini_embedding": {
+ "hint": "Gemini Embedding не требует ручного добавления /v1beta."
+ },
+ "volcengine_cluster": {
+ "description": "Кластер Volcengine",
+ "hint": "Для моделей клонирования голоса выберите volcano_icl или volcano_icl_concurr; по умолчанию volcano_tts."
+ },
+ "volcengine_voice_type": {
+ "description": "Голос Volcengine",
+ "hint": "Введите ID голоса (Voice_type)."
+ },
+ "volcengine_speed_ratio": {
+ "description": "Скорость речи",
+ "hint": "Скорость речи, от 0.2 до 3.0, по умолчанию 1.0."
+ },
+ "volcengine_volume_ratio": {
+ "description": "Громкость",
+ "hint": "Громкость, от 0.0 до 2.0, по умолчанию 1.0."
+ },
+ "azure_tts_voice": {
+ "description": "Стиль голоса",
+ "hint": "Системное имя голоса"
+ },
+ "azure_tts_style": {
+ "description": "Стиль",
+ "hint": "Стиль речи. Может выражать эмоции (счастье, сочувствие, спокойствие)."
+ },
+ "azure_tts_role": {
+ "description": "Роль (опционально)",
+ "hint": "Ролевая модель. Голос может имитировать разные возрасты и пол без смены имени голоса. Если роль не поддерживается, атрибут игнорируется."
+ },
+ "azure_tts_rate": {
+ "description": "Скорость речи",
+ "hint": "Контролирует скорость речи. От 0.5x до 2x от оригинала."
+ },
+ "azure_tts_volume": {
+ "description": "Громкость речи",
+ "hint": "Контролирует громкость. От 0.0 до 100.0. По умолчанию 100.0."
+ },
+ "azure_tts_region": {
+ "description": "Регион API",
+ "hint": "Регион обработки данных Azure TTS."
+ },
+ "azure_tts_subscription_key": {
+ "description": "Ключ подписки (Subscription Key)",
+ "hint": "Ключ подписки Azure TTS (не токен)."
+ },
+ "dashscope_tts_voice": {
+ "description": "Голос"
+ },
+ "gm_resp_image_modal": {
+ "description": "Включить визуальную модальность",
+ "hint": "Если включено, ответы могут содержать изображения. Требует поддержки моделью. Совет: для генерации изображений отключите 'Распознавание участников'."
+ },
+ "gm_native_search": {
+ "description": "Включить нативный поиск",
+ "hint": "Если включено, инструменты функций отключаются. Проверьте лимиты бесплатной квоты."
+ },
+ "gm_native_coderunner": {
+ "description": "Включить нативный исполнитель кода",
+ "hint": "Если включено, инструменты функций отключаются."
+ },
+ "gm_url_context": {
+ "description": "Включить контекст URL",
+ "hint": "Если включено, инструменты функций отключаются."
+ },
+ "gm_safety_settings": {
+ "description": "Фильтры безопасности",
+ "hint": "Настройка уровня фильтрации контента. См. документацию Gemini API.",
+ "harassment": {
+ "description": "Харрасмент",
+ "hint": "Негативные или вредные комментарии"
+ },
+ "hate_speech": {
+ "description": "Язык вражды",
+ "hint": "Грубый, неуважительный или нецензурный контент"
+ },
+ "sexually_explicit": {
+ "description": "Сексуально откровенный контент",
+ "hint": "Упоминания сексуальных актов или другой непристойный контент"
+ },
+ "dangerous_content": {
+ "description": "Опасный контент",
+ "hint": "Контент, поощряющий или способствующий вредному поведению"
+ }
+ },
+ "gm_thinking_config": {
+ "description": "Настройки рассуждения (Thinking)",
+ "budget": {
+ "description": "Бюджет рассуждения",
+ "hint": "Указывает модели количество токенов рассуждения. См. документацию Google."
+ },
+ "level": {
+ "description": "Уровень рассуждения",
+ "hint": "Рекомендуется для моделей Gemini 3+. Позволяет контролировать процесс рассуждения."
+ }
+ },
+ "anth_thinking_config": {
+ "description": "Настройки рассуждения (Thinking)",
+ "type": {
+ "description": "Тип рассуждения",
+ "hint": "Установите 'adaptive' для Opus 4.6+ / Sonnet 4.6+ (рекомендуется)."
+ },
+ "budget": {
+ "description": "Бюджет рассуждения",
+ "hint": "Параметр budget_tokens (минимум 1024). Устарело для моделей 4.6+."
+ },
+ "effort": {
+ "description": "Уровень усилий",
+ "hint": "Контролирует глубину рассуждений в режиме 'adaptive'."
+ }
+ },
+ "minimax-group-id": {
+ "description": "Группа пользователей",
+ "hint": "Доступно в Управлении аккаунтом -> Основная информация."
+ },
+ "minimax-langboost": {
+ "description": "Целевой язык/диалект",
+ "hint": "Улучшает распознавание и качество речи для определенных языков/диалектов."
+ },
+ "minimax-voice-speed": {
+ "description": "Скорость речи",
+ "hint": "API Key"
+ },
+ "minimax-voice-vol": {
+ "description": "Громкость",
+ "hint": "Громкость синтеза от 0 до 10. Чем выше, тем громче."
+ },
+ "minimax-voice-pitch": {
+ "description": "Высота голоса",
+ "hint": "Высота голоса от -12 до 12."
+ },
+ "minimax-is-timber-weight": {
+ "description": "Включить смешанные голоса",
+ "hint": "Смешивание до четырех голосов с весами. Если включено, настройки одиночного голоса игнорируются."
+ },
+ "minimax-timber-weight": {
+ "description": "Смешанные голоса",
+ "hint": "Список голосов и их весов (JSON-строка). См. документацию API."
+ },
+ "minimax-voice-id": {
+ "description": "Одиночный голос",
+ "hint": "ID одиночного голоса; см. официальную документацию."
+ },
+ "minimax-voice-emotion": {
+ "description": "Эмоция",
+ "hint": "Эмоция речи. 'auto' выбирает эмоцию на основе текста."
+ },
+ "minimax-voice-latex": {
+ "description": "Читать формулы LaTeX",
+ "hint": "Чтение формул LaTeX (требуется правильное форматирование)."
+ },
+ "minimax-voice-english-normalization": {
+ "description": "Нормализация английского текста",
+ "hint": "Улучшает чтение чисел, но немного увеличивает задержку."
+ },
+ "rag_options": {
+ "description": "Опции RAG",
+ "hint": "Настройки извлечения из базы знаний. В приложениях Bailian отключает многоэтапные диалоги.",
+ "pipeline_ids": {
+ "description": "Список ID баз знаний",
+ "hint": "Извлечение из указанных баз данных Bailian."
+ },
+ "file_ids": {
+ "description": "ID неструктурированных документов",
+ "hint": "Извлечение из указанных документов Bailian."
+ },
+ "output_reference": {
+ "description": "Выводить ссылки на источники",
+ "hint": "Добавлять источники в конец ответа. По умолчанию False."
+ }
+ },
+ "sensevoice_hint": {
+ "description": "Развертывание SenseVoice",
+ "hint": "Перед включением установите необходимые библиотеки: funasr, torch и др. Также требуется ffmpeg."
+ },
+ "is_emotion": {
+ "description": "Распознавание эмоций",
+ "hint": "Включить распознавание эмоций (радость, грусть, гнев и т.д.)."
+ },
+ "stt_model": {
+ "description": "Имя модели",
+ "hint": "Имя модели на ModelScope."
+ },
+ "variables": {
+ "description": "Фиксированные переменные воркфлоу",
+ "hint": "Входные переменные для воркфлоу. Можно также задавать через /set в чате."
+ },
+ "dashscope_app_type": {
+ "description": "Тип приложения",
+ "hint": "Тип приложения Bailian."
+ },
+ "timeout": {
+ "description": "Таймаут (сек)",
+ "hint": "Максимальное время ожидания ответа."
+ },
+ "openai-tts-voice": {
+ "description": "API Base URL",
+ "hint": "Голоса OpenAI TTS: alloy, echo и др."
+ },
+ "fishaudio-tts-character": {
+ "description": "Персонаж",
+ "hint": "Персонаж Fishaudio. По умолчанию Klee."
+ },
+ "fishaudio-tts-reference-id": {
+ "description": "Coze API Key",
+ "hint": "ID модели Fishaudio; используется вместо имени роли."
+ },
+ "whisper_hint": {
+ "description": "Заметки по локальному развертыванию Whisper",
+ "hint": "Перед включением установите openai-whisper и ffmpeg."
+ },
+ "id": {
+ "description": "ID провайдера"
+ },
+ "type": {
+ "description": "Тип провайдера"
+ },
+ "provider_type": {
+ "description": "Тип возможностей провайдера"
+ },
+ "enable": {
+ "description": "Включить"
+ },
+ "key": {
+ "description": "Ключ Coze API для доступа к сервисам Coze."
+ },
+ "api_base": {
+ "description": "Bot ID"
+ },
+ "proxy": {
+ "description": "API Base URL",
+ "hint": "Индивидуальный прокси для этого провайдера."
+ },
+ "model": {
+ "description": "Имя модели",
+ "hint": "Имя модели, напр. gpt-4o-mini."
+ },
+ "max_context_tokens": {
+ "description": "Размер окна контекста модели",
+ "hint": "Максимальное количество токенов контекста. Если 0 — автозаполнение."
+ },
+ "dify_api_key": {
+ "description": "Базовый URL для Coze API. По умолчанию: https://api.coze.cn",
+ "hint": "API-ключ Dify (обязательно)."
+ },
+ "dify_api_base": {
+ "description": "API Base URL",
+ "hint": "Base URL API Dify. По умолчанию: https://api.dify.ai/v1"
+ },
+ "dify_api_type": {
+ "description": "Тип приложения Dify",
+ "hint": "Тип API Dify (chat, agent, workflow и т.д.)."
+ },
+ "dify_workflow_output_key": {
+ "description": "Имя выходной переменной воркфлоу Dify",
+ "hint": "Имя выходной переменной для типа 'workflow'."
+ },
+ "dify_query_input_key": {
+ "description": "Имя переменной ввода промпта",
+ "hint": "Имя переменной для текста сообщения."
+ },
+ "coze_api_key": {
+ "description": "Coze API Key",
+ "hint": "Coze API key for accessing Coze services."
+ },
+ "bot_id": {
+ "description": "Bot ID",
+ "hint": "Bot ID Coze, полученный на платформе."
+ },
+ "coze_api_base": {
+ "description": "API Base URL",
+ "hint": "Base URL for the Coze API. Default: https://api.coze.cn"
+ },
+ "deerflow_api_base": {
+ "description": "API Base URL",
+ "hint": "URL шлюза DeerFlow. По умолчанию: http://127.0.0.1:2026"
+ },
+ "deerflow_api_key": {
+ "description": "API-ключ DeerFlow",
+ "hint": "Опционально. Заполните, если шлюз защищен Bearer-авторизацией."
+ },
+ "deerflow_auth_header": {
+ "description": "Заголовок Authorization",
+ "hint": "Опционально. Свой заголовок Authorization; приоритетнее ключа."
+ },
+ "deerflow_assistant_id": {
+ "description": "ID ассистента",
+ "hint": "Assistant ID для LangGraph. По умолчанию lead_agent."
+ },
+ "deerflow_model_name": {
+ "description": "Переопределение имени модели",
+ "hint": "Опционально. Переопределяет модель DeerFlow."
+ },
+ "deerflow_thinking_enabled": {
+ "description": "Включить режим рассуждения (Thinking)"
+ },
+ "deerflow_plan_mode": {
+ "description": "Включить режим планирования (Plan)",
+ "hint": "Управляет is_plan_mode в DeerFlow."
+ },
+ "deerflow_subagent_enabled": {
+ "description": "Включить субагента",
+ "hint": "Управляет subagent_enabled в DeerFlow."
+ },
+ "deerflow_max_concurrent_subagents": {
+ "description": "Макс. параллельных субагентов",
+ "hint": "Максимум параллельных субагентов. По умолчанию 3."
+ },
+ "deerflow_recursion_limit": {
+ "description": "Лимит рекурсии",
+ "hint": "Лимит рекурсии для LangGraph."
+ },
+ "auto_save_history": {
+ "description": "История диалогов управляется Coze",
+ "hint": "Если включено, Coze управляет историей. Локальный контекст AstrBot будет работать в режиме чтения."
+ }
+ }
+ },
+ "help": {
+ "documentation": "Официальная документация",
+ "support": "Группа поддержки",
+ "helpText": "Непонятно, как настроить? См. {documentation} или {support}.",
+ "helpPrefix": "Непонятно, как настроить? См.",
+ "helpMiddle": "или",
+ "helpSuffix": "."
+ }
+}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/ru-RU/features/config.json b/dashboard/src/i18n/locales/ru-RU/features/config.json
new file mode 100644
index 000000000..7c456ab9d
--- /dev/null
+++ b/dashboard/src/i18n/locales/ru-RU/features/config.json
@@ -0,0 +1,129 @@
+{
+ "title": "Конфигурация",
+ "subtitle": "Управление системными настройками",
+ "editor": {
+ "visual": "Визуальный редактор",
+ "code": "Редактор кода",
+ "revertCode": "Отменить изменения",
+ "applyConfig": "Применить",
+ "applyTip": "Кнопка «Применить» временно фиксирует изменения в визуальном редакторе. Чтобы сохранить их на постоянной основе, нажмите кнопку «Сохранить» в правом нижнем углу."
+ },
+ "actions": {
+ "save": "Сохранить",
+ "delete": "Удалить",
+ "add": "Добавить",
+ "reset": "Сбросить настройки",
+ "export": "Экспорт",
+ "import": "Импорт",
+ "validate": "Проверить"
+ },
+ "help": {
+ "documentation": "Документация",
+ "support": "Поддержка",
+ "helpText": "Нужна помощь? См. {documentation} или обратитесь в {support}.",
+ "helpPrefix": "Нужна помощь? См.",
+ "helpMiddle": "или обратитесь в",
+ "helpSuffix": "."
+ },
+ "messages": {
+ "configApplied": "Настройки применены образно. Нажмите «Сохранить» для окончательной записи.",
+ "configApplyError": "Ошибка применения: некорректный формат JSON.",
+ "unsavedChangesNotice": "Есть несохраненные изменения. Пожалуйста, нажмите «Сохранить», чтобы они вступили в силу.",
+ "saveSuccess": "Настройки успешно сохранены",
+ "saveError": "Ошибка при сохранении",
+ "loadError": "Ошибка при загрузке настроек",
+ "deleteSuccess": "Удалено",
+ "deleteError": "Ошибка удаления",
+ "updateSuccess": "Обновлено",
+ "updateError": "Ошибка обновления"
+ },
+ "sections": {
+ "general": "Основные",
+ "advanced": "Расширенные",
+ "security": "Безопасность",
+ "appearance": "Внешний вид",
+ "notification": "Уведомления"
+ },
+ "general": {
+ "botName": "Имя бота",
+ "language": "Язык интерфейса",
+ "timezone": "Часовой пояс",
+ "autoSave": "Автосохранение",
+ "debugMode": "Режим отладки"
+ },
+ "advanced": {
+ "logLevel": "Уровень логирования",
+ "maxConnections": "Макс. соединений",
+ "timeout": "Тайм-аут",
+ "retryAttempts": "Попытки повтора",
+ "cacheSize": "Размер кэша"
+ },
+ "security": {
+ "apiKey": "Ключ API",
+ "allowedHosts": "Разрешенные хосты",
+ "rateLimit": "Лимит запросов",
+ "encryption": "Шифрование"
+ },
+ "configSelection": {
+ "selectConfig": "Выбор конфигурации",
+ "normalConfig": "Обычная",
+ "systemConfig": "Системная"
+ },
+ "search": {
+ "placeholder": "Поиск по настройкам (поле/описание/подсказка)",
+ "noResult": "Совпадений не найдено"
+ },
+ "configManagement": {
+ "title": "Управление конфигурациями",
+ "description": "AstrBot поддерживает несколько конфигураций для разных ботов. По умолчанию используется «default».",
+ "newConfig": "Новая конфигурация",
+ "editConfig": "Изменить конфигурацию",
+ "manageConfigs": "Управление файлами...",
+ "configName": "Имя",
+ "fillConfigName": "Введите имя конфигурации",
+ "confirmDelete": "Вы уверены, что хотите удалить конфигурацию «{name}»? Это действие необратимо.",
+ "pleaseEnterName": "Пожалуйста, введите имя",
+ "createFailed": "Ошибка создания конфигурации",
+ "deleteFailed": "Ошибка удаления",
+ "updateFailed": "Ошибка обновления"
+ },
+ "buttons": {
+ "cancel": "Отмена",
+ "create": "Создать",
+ "update": "Обновить"
+ },
+ "codeEditor": {
+ "title": "Редактирование файла"
+ },
+ "fileUpload": {
+ "button": "Файлы",
+ "dialogTitle": "Загруженные файлы",
+ "dropzone": "Загрузить файлы",
+ "allowedTypes": "Разрешенные типы: {types}",
+ "empty": "Файлов нет",
+ "statusMissing": "Файл отсутствует",
+ "statusUnconfigured": "Не в конфиге",
+ "uploadSuccess": "Загружено файлов: {count}",
+ "uploadFailed": "Ошибка загрузки",
+ "loadFailed": "Ошибка получения списка файлов",
+ "fileTooLarge": "Файл слишком велик (макс. {max} МБ): {name}",
+ "deleteSuccess": "Файл удален",
+ "deleteFailed": "Ошибка удаления",
+ "addToConfig": "Добавлено в конфигурацию",
+ "fileCount": "Файлов: {count}",
+ "done": "Готово"
+ },
+ "unsavedChangesWarning": {
+ "dialogTitle": "Несохраненные изменения",
+ "leavePage": "У вас есть несохраненные изменения. Сохранить перед уходом?",
+ "switchConfig": "Переключение конфигурации приведет к потере несохраненных изменений. Сохранить?",
+ "options": {
+ "save": "Сохранить",
+ "saveAndSwitch": "Сохранить и переключить",
+ "discardAndSwitch": "Сбросить и переключить",
+ "closeCard": "Закрыть",
+ "confirm": "ОК",
+ "cancel": "Отмена"
+ }
+ }
+}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/ru-RU/features/console.json b/dashboard/src/i18n/locales/ru-RU/features/console.json
new file mode 100644
index 000000000..1bbd45d34
--- /dev/null
+++ b/dashboard/src/i18n/locales/ru-RU/features/console.json
@@ -0,0 +1,18 @@
+{
+ "title": "Логи платформы",
+ "autoScroll": {
+ "enabled": "Автопрокрутка включена",
+ "disabled": "Автопрокрутка выключена"
+ },
+ "pipInstall": {
+ "button": "Установить pip-пакет",
+ "dialogTitle": "Установка Pip-пакета",
+ "packageLabel": "*Имя пакета, например: llmtuner",
+ "mirrorLabel": "Использовать зеркало PyPI (опционально)",
+ "mirrorHint": "Приоритет зеркала PyPI > настройки «Зеркало репозитория PyPI»",
+ "installButton": "Установить"
+ },
+ "debugHint": {
+ "text": "Для отображения Debug-логов необходимо установить соответствующий уровень в «Конфигурация → Система → Уровень логирования»"
+ }
+}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/ru-RU/features/conversation.json b/dashboard/src/i18n/locales/ru-RU/features/conversation.json
new file mode 100644
index 000000000..33ebefa74
--- /dev/null
+++ b/dashboard/src/i18n/locales/ru-RU/features/conversation.json
@@ -0,0 +1,102 @@
+{
+ "title": "Управление диалогами",
+ "subtitle": "Просмотр и управление историей сообщений",
+ "filters": {
+ "title": "Фильтры",
+ "platform": "ID бота",
+ "type": "Тип",
+ "search": "Поиск по ключевым словам",
+ "reset": "Сбросить"
+ },
+ "history": {
+ "title": "История",
+ "refresh": "Обновить"
+ },
+ "batch": {
+ "deleteSelected": "Удалить выбранные ({count})",
+ "exportSelected": "Экспорт выбранных ({count})"
+ },
+ "pagination": {
+ "itemsPerPage": "на странице",
+ "showingItems": "Показано {start}-{end} из {total}"
+ },
+ "table": {
+ "headers": {
+ "title": "Заголовок диалога",
+ "platform": "ID бота",
+ "type": "Тип сообщения",
+ "cid": "ID диалога",
+ "umo": "Источник сообщения",
+ "sessionId": "ID сессии",
+ "createdAt": "Создан",
+ "updatedAt": "Обновлен",
+ "actions": "Действия"
+ }
+ },
+ "actions": {
+ "view": "Просмотр",
+ "edit": "Редактировать",
+ "delete": "Удалить"
+ },
+ "messageTypes": {
+ "group": "Группа",
+ "friend": "ЛС",
+ "unknown": "Неизвестно"
+ },
+ "status": {
+ "noTitle": "Без заголовка",
+ "unknown": "Неизвестно",
+ "noData": "История диалогов пуста",
+ "emptyContent": "Содержимое диалога пусто",
+ "audioNotSupported": "Ваш браузер не поддерживает воспроизведение аудио."
+ },
+ "dialogs": {
+ "view": {
+ "title": "Детали диалога",
+ "editMode": "Режим редактирования",
+ "previewMode": "Режим просмотра",
+ "saveChanges": "Сохранить изменения",
+ "close": "Закрыть",
+ "confirmClose": "У вас есть несохраненные изменения. Вы уверены, что хотите закрыть?"
+ },
+ "edit": {
+ "title": "Изменить информацию",
+ "titleLabel": "Заголовок диалога",
+ "titlePlaceholder": "Введите заголовок",
+ "cancel": "Отмена",
+ "save": "Сохранить"
+ },
+ "delete": {
+ "title": "Подтверждение удаления",
+ "message": "Вы уверены, что хотите удалить диалог «{title}»? Это действие необратимо.",
+ "cancel": "Отмена",
+ "confirm": "Удалить"
+ },
+ "batchDelete": {
+ "title": "Массовое удаление",
+ "message": "Вы уверены, что хотите удалить {count} выбранных диалогов? Это действие необратимо!",
+ "andMore": "и еще {count}",
+ "cancel": "Отмена",
+ "confirm": "Удалить всё",
+ "warning": "Внимание: удаление нельзя будет отменить!"
+ }
+ },
+ "messages": {
+ "fetchError": "Не удалось загрузить список диалогов",
+ "saveSuccess": "Сохранено",
+ "saveError": "Ошибка сохранения",
+ "deleteSuccess": "Удалено",
+ "deleteError": "Ошибка удаления",
+ "historyError": "Не удалось загрузить историю диалога",
+ "historySaveSuccess": "История сохранена",
+ "historySaveError": "Ошибка сохранения истории",
+ "invalidJson": "Некорректный формат JSON",
+ "noItemSelected": "Сначала выберите диалоги для удаления",
+ "batchDeleteSuccess": "Успешно удалено {count} диалогов",
+ "batchDeleteError": "Ошибка массового удаления",
+ "batchDeletePartial": "Удаление завершено: успешно {deleted}, ошибок {failed}",
+ "exportSuccess": "Экспорт завершен",
+ "exportError": "Ошибка экспорта",
+ "noItemSelectedForExport": "Сначала выберите диалоги для экспорта"
+ }
+}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/ru-RU/features/cron.json b/dashboard/src/i18n/locales/ru-RU/features/cron.json
new file mode 100644
index 000000000..5bc98ab13
--- /dev/null
+++ b/dashboard/src/i18n/locales/ru-RU/features/cron.json
@@ -0,0 +1,66 @@
+{
+ "page": {
+ "title": "Запланированные задачи",
+ "beta": "Экспериментальные функции",
+ "subtitle": "Управление будущими задачами AstrBot. Бот автоматически проснется, выполнит задачу и отправит результат. Требуется включить «Проактивные способности» в конфигурации.",
+ "proactive": {
+ "supported": "Отправка результатов поддерживается на платформах: {platforms}",
+ "unsupported": "Нет платформ, поддерживающих проактивные сообщения. Включите их в настройках платформ."
+ }
+ },
+ "actions": {
+ "create": "Новая задача",
+ "refresh": "Обновить",
+ "delete": "Удалить",
+ "cancel": "Отмена",
+ "submit": "Создать"
+ },
+ "table": {
+ "title": "Список задач",
+ "empty": "Задач пока нет.",
+ "headers": {
+ "name": "Имя",
+ "type": "Тип",
+ "cron": "Cron",
+ "session": "ID сессии",
+ "nextRun": "Следующий запуск",
+ "lastRun": "Последний запуск",
+ "note": "Описание",
+ "actions": "Действия"
+ },
+ "type": {
+ "once": "Разовая",
+ "recurring": "Повторяющаяся",
+ "activeAgent": "Активный агент",
+ "workflow": "Рабочий процесс",
+ "unknown": "{type}"
+ },
+ "timezoneLocal": "Местное время",
+ "notAvailable": "—"
+ },
+ "form": {
+ "title": "Создать задачу",
+ "chatHint": "Вы можете ставить задачи прямо в чате, AstrBot создаст их автоматически без заполнения этой формы.",
+ "runOnce": "Разовая задача",
+ "name": "Имя задачи",
+ "note": "Описание",
+ "cron": "Cron-выражения",
+ "cronPlaceholder": "0 9 * * *",
+ "runAt": "Время запуска",
+ "session": "Целевая сессия (platform_id:message_type:session_id)",
+ "timezone": "Часовой пояс (опционально, напр. Europe/Moscow)",
+ "enabled": "Включено"
+ },
+ "messages": {
+ "loadFailed": "Ошибка загрузки задач",
+ "updateFailed": "Ошибка обновления",
+ "deleteSuccess": "Удалено",
+ "deleteFailed": "Ошибка удаления",
+ "sessionRequired": "Укажите сессию",
+ "noteRequired": "Заполните описание",
+ "cronRequired": "Укажите Cron-выражение",
+ "runAtRequired": "Выберите время запуска",
+ "createSuccess": "Задача создана",
+ "createFailed": "Ошибка создания"
+ }
+}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/ru-RU/features/dashboard.json b/dashboard/src/i18n/locales/ru-RU/features/dashboard.json
new file mode 100644
index 000000000..b4ecd50ab
--- /dev/null
+++ b/dashboard/src/i18n/locales/ru-RU/features/dashboard.json
@@ -0,0 +1,65 @@
+{
+ "title": "Логи платформы",
+ "subtitle": "Мониторинг и статистика в реальном времени",
+ "lastUpdate": "Последнее обновление",
+ "status": {
+ "loading": "Загрузка...",
+ "dataError": "Ошибка получения данных",
+ "noticeError": "Ошибка получения объявлений",
+ "online": "В сети",
+ "uptime": "Время работы",
+ "memoryUsage": "Память"
+ },
+ "stats": {
+ "totalMessage": {
+ "title": "Всего сообщений",
+ "subtitle": "Все сообщения со всех платформ"
+ },
+ "onlinePlatform": {
+ "title": "Платформы",
+ "subtitle": "Количество подключенных платформ"
+ },
+ "runningTime": {
+ "title": "Время работы",
+ "subtitle": "Общее время работы системы",
+ "format": "{hours} ч. {minutes} мин. {seconds} сек."
+ },
+ "memoryUsage": {
+ "title": "Память",
+ "subtitle": "Использование оперативной памяти",
+ "cpuLoad": "Загрузка CPU",
+ "status": {
+ "good": "Отлично",
+ "normal": "Нормально",
+ "high": "Высокая"
+ }
+ }
+ },
+ "charts": {
+ "messageTrend": {
+ "title": "Тренды сообщений",
+ "subtitle": "Изменение количества сообщений во времени",
+ "totalMessages": "Всего сообщений",
+ "dailyAverage": "В среднем за день",
+ "growthRate": "Скорость роста",
+ "timeLabel": "Время",
+ "messageCount": "Кол-во сообщений",
+ "timeRanges": {
+ "1day": "За 1 день",
+ "3days": "За 3 дня",
+ "1week": "За 7 дней",
+ "1month": "За 30 дней"
+ }
+ },
+ "platformStat": {
+ "title": "Статистика по платформам",
+ "subtitle": "Распределение сообщений по платформам",
+ "total": "Всего",
+ "noData": "Нет данных по платформам",
+ "messageUnit": "шт.",
+ "platformCount": "Кол-во платформ",
+ "mostActive": "Самый активный",
+ "totalPercentage": "Доля от общего числа"
+ }
+ }
+}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/ru-RU/features/extension.json b/dashboard/src/i18n/locales/ru-RU/features/extension.json
new file mode 100644
index 000000000..2ff06f573
--- /dev/null
+++ b/dashboard/src/i18n/locales/ru-RU/features/extension.json
@@ -0,0 +1,358 @@
+{
+ "title": "Плагины",
+ "subtitle": "Управление и настройка расширений системы",
+ "tabs": {
+ "installedPlugins": "Плагины AstrBot",
+ "market": "Магазин плагинов",
+ "installedMcpServers": "MCP",
+ "skills": "Навыки",
+ "handlersOperation": "Управление поведением"
+ },
+ "titles": {
+ "installedAstrBotPlugins": "Установленные плагины AstrBot"
+ },
+ "failedPlugins": {
+ "title": "Ошибка загрузки ({count})",
+ "hint": "Эти плагины не удалось загрузить. Вы можете попробовать перезагрузить их или удалить.",
+ "columns": {
+ "plugin": "Плагин",
+ "error": "Ошибка"
+ }
+ },
+ "search": {
+ "placeholder": "Поиск плагинов...",
+ "marketPlaceholder": "Поиск в магазине..."
+ },
+ "filters": {
+ "all": "Все"
+ },
+ "views": {
+ "card": "Плитка",
+ "list": "Список"
+ },
+ "buttons": {
+ "showSystemPlugins": "Показать системные",
+ "hideSystemPlugins": "Скрыть системные",
+ "install": "Установить",
+ "uninstall": "Удалить",
+ "update": "Обновить",
+ "reload": "Перезагрузить",
+ "enable": "Включить",
+ "disable": "Выключить",
+ "configure": "Настроить",
+ "viewInfo": "Детали",
+ "viewDocs": "Документация",
+ "viewRepo": "Репозиторий",
+ "close": "Закрыть",
+ "save": "Сохранить",
+ "saveAndClose": "Сохранить и закрыть",
+ "cancel": "Отмена",
+ "actions": "Действия",
+ "back": "Назад",
+ "selectFile": "Выбрать файл",
+ "refresh": "Обновить",
+ "updateAll": "Обновить все",
+ "deleteSource": "Удалить источник",
+ "reshuffle": "Мне повезет!"
+ },
+ "status": {
+ "enabled": "Включен",
+ "disabled": "Выключен",
+ "system": "Системный",
+ "loading": "Загрузка...",
+ "installed": "Установлен",
+ "unknown": "Неизвестно"
+ },
+ "tooltips": {
+ "enable": "Включить",
+ "disable": "Выключить",
+ "reload": "Перезагрузить",
+ "configure": "Настроить",
+ "viewInfo": "Просмотр поведения",
+ "viewDocs": "Документация",
+ "update": "Обновить",
+ "uninstall": "Удалить"
+ },
+ "table": {
+ "headers": {
+ "name": "Имя",
+ "description": "Описание",
+ "version": "Версия",
+ "author": "Автор",
+ "status": "Статус",
+ "actions": "Действия",
+ "stars": "Звезды",
+ "lastUpdate": "Обновлен",
+ "tags": "Теги",
+ "eventType": "Тип события",
+ "specificType": "Тип",
+ "trigger": "Триггер"
+ }
+ },
+ "empty": {
+ "noPlugins": "Плагины не найдены",
+ "noPluginsDesc": "Попробуйте установить новые плагины или включите отображение системных."
+ },
+ "market": {
+ "recommended": "🥳 Рекомендуем",
+ "allPlugins": "📦 Все плагины",
+ "showFullName": "Полное имя",
+ "devDocs": "Документация для разработчиков",
+ "submitRepo": "Добавить репозиторий",
+ "customSource": "Свои источники",
+ "source": "Источник",
+ "availableSources": "Доступные источники",
+ "sourceManagement": "Управление источниками",
+ "addSource": "Добавить источник",
+ "sourceName": "Имя",
+ "sourceUrl": "Исходный URL",
+ "defaultSource": "Источник по умолчанию",
+ "removeSource": "Удалить источник",
+ "confirmRemoveSource": "Вы уверены, что хотите удалить этот источник плагинов?",
+ "sourceAdded": "Источник успешно добавлен",
+ "sourceRemoved": "Источник удален",
+ "sourceError": "Ошибка операции",
+ "selectSource": "Выбрать источник",
+ "currentSource": "Текущий источник",
+ "editSource": "Изменить источник",
+ "sourceUpdated": "Источник обновлен",
+ "defaultOfficialSource": "Официальный источник",
+ "sourceExists": "Этот источник уже есть в списке",
+ "installPlugin": "Установить плагин",
+ "randomPlugins": "🎲 Случайные плагины",
+ "showRandomPlugins": "Показать случайные",
+ "hideRandomPlugins": "Скрыть случайные",
+ "sourceSafetyWarning": "Даже при использовании источников по умолчанию мы не можем гарантировать 100% безопасность и стабильность сторонних плагинов. Пожалуйста, будьте внимательны."
+ },
+ "sort": {
+ "by": "Сортировать по",
+ "default": "По умолчанию",
+ "installTime": "Дате установки",
+ "name": "Имени",
+ "stars": "Звездам",
+ "author": "Автору",
+ "updated": "Дате обновления",
+ "updateStatus": "Статусу обновления",
+ "ascending": "По возрастанию",
+ "descending": "По убыванию"
+ },
+ "tags": {
+ "danger": "Опасно"
+ },
+ "dialogs": {
+ "error": {
+ "title": "Ошибка",
+ "checkConsole": "Подробности смотрите в логах платформы"
+ },
+ "config": {
+ "title": "Настройка плагина",
+ "noConfig": "У этого плагина нет настраиваемых параметров"
+ },
+ "loading": {
+ "title": "Загрузка...",
+ "logs": "Логи"
+ },
+ "uninstall": {
+ "title": "Подтверждение удаления",
+ "message": "Вы уверены, что хотите удалить этот плагин?",
+ "deleteConfig": "Удалить файл конфигурации плагина",
+ "deleteData": "Удалить сохраненные данные плагина",
+ "configHint": "Конфиг находится в data/config",
+ "dataHint": "Данные находятся в data/plugin_data и data/plugins_data"
+ },
+ "install": {
+ "title": "Установка плагина",
+ "fromFile": "Из файла",
+ "fromUrl": "По ссылке",
+ "supportPlatformsCount": "Поддерживает платформ: {count}"
+ },
+ "danger_warning": {
+ "title": "Внимание!",
+ "message": "Этот плагин может содержать небезопасный код или функции, которые могут привести к нестабильности системы или потере данных. Вы уверены, что хотите продолжить установку?",
+ "confirm": "Продолжить",
+ "cancel": "Отмена"
+ },
+ "versionCompatibility": {
+ "title": "Предупреждение о версии",
+ "message": "Требуемая плагином версия AstrBot не совпадает с вашей текущей версией. Вы можете продолжить установку на свой страх и риск.",
+ "confirm": "Игнорировать и установить",
+ "cancel": "Отмена"
+ },
+ "forceUpdate": {
+ "title": "Новых версий не найдено",
+ "message": "Новых версий не обнаружено. Выполнить принудительную переустановку из удаленного репозитория?",
+ "confirm": "Принудительно"
+ },
+ "updateAllConfirm": {
+ "title": "Обновить всё",
+ "message": "Обновить все плагины ({count} шт.)? Это может занять некоторое время.",
+ "confirm": "Подтвердить"
+ }
+ },
+ "messages": {
+ "uninstalling": "Удаление",
+ "refreshing": "Обновление списка плагинов...",
+ "refreshSuccess": "Список плагинов обновлен",
+ "refreshFailed": "Ошибка при обновлении списка",
+ "operationFailed": "Ошибка операции",
+ "reloadSuccess": "Перезагрузка завершена",
+ "reloadFailed": "Ошибка перезагрузки",
+ "updateSuccess": "Обновление завершено",
+ "addSuccess": "Успешно добавлено",
+ "saveSuccess": "Сохранено",
+ "deleteSuccess": "Удалено",
+ "installing": "Установка из файла...",
+ "installingFromUrl": "Установка по ссылке...",
+ "installFailed": "Ошибка установки:",
+ "getMarketDataFailed": "Ошибка получения данных магазина:",
+ "hasUpdate": "Доступно обновление:",
+ "confirmDelete": "Вы уверены, что хотите удалить плагин?",
+ "fillUrlOrFile": "Укажите ссылку или выберите файл",
+ "dontFillBoth": "Пожалуйста, используйте либо ссылку, либо файл, но не оба сразу",
+ "supportedFormats": "Поддерживаются файлы плагинов в формате .zip",
+ "updateAllSuccess": "Все плагины успешно обновлены",
+ "updateAllFailed": "Ошибок при обновлении: {failed} из {total}:",
+ "fillSourceNameAndUrl": "Пожалуйста, введите имя и адрес источника",
+ "invalidUrl": "Введите корректный URL",
+ "enterJsonUrl": "Введите URL, возвращающий список плагинов в формате JSON"
+ },
+ "upload": {
+ "fromFile": "Загрузить файл",
+ "fromUrl": "Указать ссылку",
+ "selectFile": "Выбрать файл",
+ "enterUrl": "Ссылка на репозиторий"
+ },
+ "skills": {
+ "modeLocal": "Локальные навыки",
+ "modeNeo": "Навыки Neo",
+ "actions": "Действия",
+ "upload": "Загрузить навыки",
+ "refresh": "Обновить",
+ "empty": "Навыки не найдены",
+ "emptyHint": "Пожалуйста, загрузите архив с навыками",
+ "uploadDialogTitle": "Загрузка навыков",
+ "uploadHint": "Поддерживается массовая загрузка zip-архивов. Вы также можете перетащить файлы в это окно. Система автоматически проверит структуру каждого архива.",
+ "structureRequirement": "Архив должен содержать одну корневую папку (например, `skillname/`), внутри которой обязательно должен находиться файл `SKILL.md`.",
+ "abilityMultiple": "Поддержка массовой загрузки",
+ "abilityValidate": "Автопроверка `SKILL.md`",
+ "abilitySkip": "Пропуск дубликатов",
+ "selectFile": "Выбрать файл",
+ "selectFiles": "Выбрать файлы",
+ "dropzoneTitle": "Перетащите zip-файлы сюда",
+ "dropzoneAction": "или нажмите, чтобы выбрать файлы на компьютере",
+ "dropzoneHint": "Система проверит структуру архивов перед загрузкой",
+ "fileListTitle": "Очередь загрузки",
+ "fileListEmpty": "Здесь будет отображаться статус проверки и загрузки файлов",
+ "uploading": "Загрузка...",
+ "batchResultTitle": "Результаты загрузки",
+ "batchResultSummary": "Всего: {total}, успешно: {success}",
+ "batchSuccessList": "Успешно загружено",
+ "batchFailedList": "Ошибка загрузки",
+ "confirm": "ОК",
+ "confirmUpload": "Начать загрузку",
+ "cancel": "Отмена",
+ "statusWaiting": "В очереди",
+ "statusUploading": "Загрузка...",
+ "statusSuccess": "Готово",
+ "statusError": "Ошибка структуры",
+ "statusSkipped": "Пропущено",
+ "summaryTotal": "Всего: {count}",
+ "summaryReady": "Готовы: {count}",
+ "summarySuccess": "Успешно: {count}",
+ "summaryFailed": "Ошибок: {count}",
+ "summarySkipped": "Дубликатов: {count}",
+ "validationReady": "Ожидает загрузки (проверка структуры будет выполнена автоматически)",
+ "validationZipOnly": "Допускаются только zip-архивы",
+ "validationDuplicate": "Файл уже есть в списке, пропуск",
+ "validationUploading": "Проверка и загрузка...",
+ "validationUploadFailed": "Ошибка загрузки, попробуйте еще раз",
+ "validationUploadedAs": "Установлено как {name}",
+ "validationNoResult": "Результат не получен, проверьте логи платформы",
+ "noDescription": "Нет описания",
+ "path": "Путь",
+ "uploadSuccess": "Успешно загружено",
+ "uploadFailed": "Ошибка загрузки",
+ "download": "Скачать",
+ "downloadSuccess": "Скачивание начато",
+ "downloadFailed": "Ошибка скачивания",
+ "loadFailed": "Не удалось загрузить навыки",
+ "updateSuccess": "Обновлено",
+ "updateFailed": "Ошибка обновления",
+ "deleteTitle": "Подтверждение удаления",
+ "deleteMessage": "Вы уверены, что хотите удалить этот навык?",
+ "deleteSuccess": "Удалено",
+ "deleteFailed": "Ошибка удаления",
+ "neoSkillKey": "Фильтр по ключу",
+ "neoStatus": "Статус кандидата",
+ "neoStage": "Этап публикации",
+ "neoFilterHint": "Фильтрация записей о публикации",
+ "neoAll": "Все",
+ "neoCandidates": "Кандидаты Neo",
+ "neoReleases": "Релизы Neo",
+ "neoLoadFailed": "Ошибка загрузки данных Neo Skills",
+ "neoPass": "Одобрить",
+ "neoReject": "Отклонить",
+ "neoEvaluateSuccess": "Оценка обновлена",
+ "neoEvaluateFailed": "Ошибка обновления оценки",
+ "neoPromoteSuccess": "Опубликовано",
+ "neoPromoteFailed": "Ошибка публикации",
+ "neoRollback": "Откат",
+ "neoRollbackSuccess": "Откат выполнен",
+ "neoRollbackFailed": "Ошибка отката",
+ "neoDeactivate": "Деактивация",
+ "neoDeactivateSuccess": "Деактивировано",
+ "neoDeactivateFailed": "Ошибка деактивации",
+ "neoSync": "Синхронизация",
+ "neoSyncSuccess": "Синхронизировано",
+ "neoSyncFailed": "Ошибка синхронизации",
+ "neoDelete": "Удалить",
+ "neoDeleteSuccess": "Удалено",
+ "neoDeleteFailed": "Ошибка удаления",
+ "neoPayloadTitle": "Детали Neo Payload",
+ "neoPayloadFailed": "Ошибка чтения Payload",
+ "runtimeNoneWarning": "Среда выполнения Computer Use не задана. Навыки могут не работать, так как нет активного окружения.",
+ "runtimeHint": "Установите среду выполнения в «local» или «sandbox» в настройках способностей использования компьютера.",
+ "neoRuntimeRequired": "Neo Skills доступны только в среде sandbox с драйвером shipyard_neo.",
+ "sourceLocalOnly": "Локальный навык",
+ "sourceSandboxOnly": "Предустановленный Sandbox навык",
+ "sourceBoth": "Локальный + Sandbox",
+ "sandboxDiscoveryPending": "Предустановленные Sandbox навыки не найдены. Запустите сессию Sandbox хотя бы один раз.",
+ "sandboxPresetReadonly": "Предустановленные навыки Sandbox доступны только для чтения и не могут быть удалены здесь."
+ },
+ "card": {
+ "actions": {
+ "pluginConfig": "Настройки",
+ "uninstallPlugin": "Удалить",
+ "reloadPlugin": "Перезагрузить",
+ "togglePlugin": "Плагин",
+ "viewHandlers": "Действия",
+ "updateTo": "Обновить до",
+ "reinstall": "Переустановить"
+ },
+ "status": {
+ "hasUpdate": "Доступно обновление",
+ "disabled": "Плагин выключен",
+ "handlersCount": "действий",
+ "supportPlatform": "Платформы",
+ "supportPlatformsCount": "Платформ: {count}",
+ "astrbotVersion": "Требуемая версия AstrBot"
+ },
+ "alt": {
+ "logo": "логотип",
+ "extensionIcon": "иконка расширения"
+ },
+ "errors": {
+ "confirmNotRegistered": "$confirm не зарегистрирован"
+ }
+ },
+ "conflicts": {
+ "title": "Конфликт команд",
+ "message": "Обнаружены конфликтующие команды. Это может привести к некорректной работе. Рекомендуется разрешить конфликты в панели «Управление командами».",
+ "pairs": "конфликтующих пар",
+ "goToManage": "Управление",
+ "later": "Позже"
+ },
+ "pluginChangelog": {
+ "menuTitle": "Журнал изменений"
+ }
+}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/ru-RU/features/knowledge-base/detail.json b/dashboard/src/i18n/locales/ru-RU/features/knowledge-base/detail.json
new file mode 100644
index 000000000..10d2109bd
--- /dev/null
+++ b/dashboard/src/i18n/locales/ru-RU/features/knowledge-base/detail.json
@@ -0,0 +1,118 @@
+{
+ "title": "Детали базы знаний",
+ "backToList": "К списку",
+ "tabs": {
+ "overview": "Обзор",
+ "documents": "Документы",
+ "retrieval": "Поиск",
+ "sessions": "Сессии",
+ "settings": "Настройки"
+ },
+ "overview": {
+ "title": "Информация",
+ "name": "Название",
+ "description": "Описание",
+ "emoji": "Иконка",
+ "createdAt": "Создана",
+ "updatedAt": "Обновлена",
+ "stats": "Статистика",
+ "docCount": "Количество документов",
+ "chunkCount": "Количество фрагментов",
+ "embeddingModel": "Embedding модель",
+ "rerankModel": "Rerank модель",
+ "notSet": "не выбрано"
+ },
+ "documents": {
+ "title": "Список документов",
+ "upload": "Загрузить",
+ "empty": "Документов нет",
+ "name": "Имя файла",
+ "type": "Тип",
+ "size": "Размер",
+ "chunks": "Фрагменты",
+ "createdAt": "Дата загрузки",
+ "actions": "Действия",
+ "view": "Смотреть",
+ "delete": "Удалить",
+ "deleteConfirm": "Вы уверены, что хотите удалить «{name}»?",
+ "deleteWarning": "Это удалит файл и все его фрагменты из индекса.",
+ "uploading": "Загрузка...",
+ "uploadSuccess": "Файл успешно загружен",
+ "uploadFailed": "Ошибка загрузки",
+ "deleteSuccess": "Файл удален",
+ "deleteFailed": "Ошибка удаления"
+ },
+ "upload": {
+ "title": "Добавление контента",
+ "selectFile": "Файл",
+ "dropzone": "Нажмите или перетащите файл сюда",
+ "supportedFormats": "Форматы: ",
+ "maxSize": "Максимум: 128MB",
+ "chunkSettings": "Фрагментация",
+ "batchSettings": "Пакетная обработка",
+ "cleaningSettings": "Очистка данных",
+ "enableCleaning": "Включить очистку контента",
+ "cleaningProvider": "Сервис для очистки",
+ "cleaningProviderHint": "LLM провайдер для суммаризации и извлечения смыслов из веб-страниц",
+ "chunkSize": "Размер чанка",
+ "chunkSizeHint": "Символов в блоке (по умолчанию: 512)",
+ "chunkOverlap": "Перекрытие",
+ "chunkOverlapHint": "Перекрытие между блоками (по умолчанию: 50)",
+ "batchSize": "Размер пакета",
+ "batchSizeHint": "Блоков за один запрос (по умолчанию: 32)",
+ "tasksLimit": "Лимит задач",
+ "tasksLimitHint": "Макс. параллельных потоков (по умолчанию: 3)",
+ "maxRetries": "Попытки",
+ "maxRetriesHint": "Повторов при сбое (по умолчанию: 3)",
+ "cancel": "Отмена",
+ "submit": "Загрузить",
+ "fileRequired": "Пожалуйста, выберите файл",
+ "fileUpload": "Загрузка файла",
+ "fromUrl": "Из URL",
+ "urlPlaceholder": "Ссылка на веб-страницу",
+ "urlRequired": "Введите URL",
+ "urlHint": "Контент будет автоматически извлечен со страницы. Убедитесь, что сайт разрешает доступ роботам.",
+ "beta": "Бета-версия"
+ },
+ "retrieval": {
+ "title": "Поиск и проверка",
+ "subtitle": "Проверьте качество поиска (Dense & Sparse) по вашей базе знаний",
+ "query": "Тестовый запрос",
+ "queryPlaceholder": "Что вы хотите найти?",
+ "search": "Найти",
+ "searching": "Ищем...",
+ "results": "Результаты поиска",
+ "noResults": "Релевантный контент не найден",
+ "tryDifferentQuery": "Попробуйте изменить формулировку запроса",
+ "settings": "Параметры поиска",
+ "topK": "Количество результатов",
+ "topKHint": "Сколько фрагментов возвращать",
+ "enableRerank": "Включить Rerank",
+ "enableRerankHint": "Применить переранжирование для повышения точности",
+ "score": "Вес (Score)",
+ "document": "Документ",
+ "chunk": "Фрагмент #{index}",
+ "content": "Текст",
+ "charCount": "{count} симв.",
+ "searchSuccess": "Поиск завершен, найдено: {count}",
+ "searchFailed": "Ошибка выполнения поиска",
+ "queryRequired": "Введите поисковый запрос"
+ },
+ "settings": {
+ "title": "Общие настройки базы",
+ "basic": "Основные",
+ "retrieval": "Поиск",
+ "chunkSize": "Размер чанка",
+ "chunkOverlap": "Перекрытие",
+ "topKDense": "Вернуть (Dense)",
+ "topKSparse": "Вернуть (Sparse)",
+ "topMFinal": "Итоговый результат",
+ "enableRerank": "Включить Rerank",
+ "embeddingProvider": "Провайдер Embedding",
+ "rerankProvider": "Провайдер Rerank",
+ "save": "Сохранить",
+ "saveSuccess": "Настройки сохранены",
+ "saveFailed": "Ошибка сохранения",
+ "tips": "Внимание! Изменение этих параметров повлияет на будущую выдачу базы знаний."
+ }
+}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/ru-RU/features/knowledge-base/document.json b/dashboard/src/i18n/locales/ru-RU/features/knowledge-base/document.json
new file mode 100644
index 000000000..7fcb30ee9
--- /dev/null
+++ b/dashboard/src/i18n/locales/ru-RU/features/knowledge-base/document.json
@@ -0,0 +1,55 @@
+{
+ "title": "Просмотр документа",
+ "backToKB": "К базе знаний",
+ "info": {
+ "title": "Информация о документе",
+ "name": "Имя файла",
+ "type": "Формат",
+ "size": "Размер",
+ "chunkCount": "Количество фрагментов",
+ "createdAt": "Загружен"
+ },
+ "chunks": {
+ "title": "Фрагменты текста",
+ "empty": "Фрагменты не найдены",
+ "index": "Индекс",
+ "content": "Текст",
+ "charCount": "Символов",
+ "actions": "Действия",
+ "view": "Детали",
+ "edit": "Изменить",
+ "delete": "Удалить",
+ "preview": "Обзор",
+ "search": "Поиск по документу",
+ "searchPlaceholder": "Найти во фрагментах...",
+ "showing": "Показано",
+ "deleteConfirm": "Удалить этот фрагмент?",
+ "deleteSuccess": "Фрагмент удален",
+ "deleteFailed": "Ошибка удаления"
+ },
+ "edit": {
+ "title": "Редактирование фрагмента",
+ "content": "Текст",
+ "cancel": "Отмена",
+ "save": "Сохранить",
+ "saveSuccess": "Фрагмент обновлен",
+ "saveFailed": "Ошибка сохранения"
+ },
+ "delete": {
+ "title": "Удаление",
+ "confirmText": "Вы уверены?",
+ "warning": "Удаление фрагмента может ухудшить качество ответов AI по этой теме.",
+ "cancel": "Отмена",
+ "confirm": "Удалить",
+ "deleteSuccess": "Удаление выполнено",
+ "deleteFailed": "Ошибка удаления"
+ },
+ "view": {
+ "title": "Детальный просмотр",
+ "index": "Индекс",
+ "content": "Текст",
+ "charCount": "Символов",
+ "vecDocId": "ID вектора",
+ "close": "Закрыть"
+ }
+}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/ru-RU/features/knowledge-base/index.json b/dashboard/src/i18n/locales/ru-RU/features/knowledge-base/index.json
new file mode 100644
index 000000000..17fef3cc1
--- /dev/null
+++ b/dashboard/src/i18n/locales/ru-RU/features/knowledge-base/index.json
@@ -0,0 +1,67 @@
+{
+ "title": "Управление базами знаний",
+ "subtitle": "Централизованное управление всеми знаниями AstrBot",
+ "list": {
+ "title": "Мои базы знаний",
+ "subtitle": "Все доступные коллекции знаний",
+ "create": "Создать базу",
+ "refresh": "Обновить",
+ "empty": "Баз знаний пока нет",
+ "loading": "Загрузка...",
+ "documents": "док.",
+ "chunks": "фрагм.",
+ "sessionConfig": "Профиль"
+ },
+ "card": {
+ "edit": "Изменить",
+ "delete": "Удалить",
+ "open": "Открыть",
+ "docCount": "Документов: {count}",
+ "chunkCount": "Фрагментов: {count}"
+ },
+ "create": {
+ "title": "Создание базы знаний",
+ "nameLabel": "Название",
+ "namePlaceholder": "Придумайте имя для базы",
+ "descriptionLabel": "Описание",
+ "descriptionPlaceholder": "Для чего нужна эта база?",
+ "emojiLabel": "Иконка",
+ "embeddingModelLabel": "Embedding модель",
+ "rerankModelLabel": "Rerank модель (опционально)",
+ "providerInfo": "Провайдер: {id} | Размерность: {dimensions}",
+ "rerankProviderInfo": "Провайдер: {id}",
+ "cancel": "Отмена",
+ "submit": "Создать",
+ "nameRequired": "Введите название базы знаний"
+ },
+ "edit": {
+ "title": "Редактирование",
+ "submit": "Сохранить"
+ },
+ "delete": {
+ "title": "Удаление",
+ "confirmText": "Вы уверены, что хотите удалить базу знаний «{name}»?",
+ "warning": "Это действие необратимо. Все документы, фрагменты и настройки будут навсегда удалены.",
+ "cancel": "Отмена",
+ "confirm": "Удалить"
+ },
+ "emoji": {
+ "title": "Выберите иконку",
+ "close": "Закрыть",
+ "categories": {
+ "books": "Книги и документы",
+ "emotions": "Эмоции",
+ "objects": "Вещи",
+ "symbols": "Символы"
+ }
+ },
+ "messages": {
+ "createSuccess": "База знаний создана",
+ "createFailed": "Ошибка создания",
+ "updateSuccess": "Обновлено успешно",
+ "updateFailed": "Ошибка обновления",
+ "deleteSuccess": "Удалено успешно",
+ "deleteFailed": "Ошибка удаления",
+ "loadError": "Не удалось загрузить список"
+ }
+}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/ru-RU/features/migration.json b/dashboard/src/i18n/locales/ru-RU/features/migration.json
new file mode 100644
index 000000000..4d41dfce8
--- /dev/null
+++ b/dashboard/src/i18n/locales/ru-RU/features/migration.json
@@ -0,0 +1,18 @@
+{
+ "dialog": {
+ "title": "Помощник по миграции",
+ "warning": "👋 Добро пожаловать в v4.0.0! В этой версии мы оптимизировали формат хранения данных. Обнаружена необходимость миграции базы данных.",
+ "loading": "Загрузка списка платформ...",
+ "loadError": "Ошибка загрузки, попробуйте еще раз",
+ "noPlatforms": "Конфигурации платформ не найдены",
+ "retry": "Повторить",
+ "startMigration": "Начать миграцию",
+ "migrating": "Выполняется миграция...",
+ "migratingSubtitle": "Пожалуйста, подождите. Не закрывайте это окно до завершения процесса.",
+ "migrationError": "Ошибка миграции",
+ "success": "Миграция успешно завершена!",
+ "completed": "Миграция выполнена",
+ "restartRecommended": "Рекомендуется перезапустить приложение, чтобы все изменения вступили в силу.",
+ "restartNow": "Перезапустить сейчас"
+ }
+}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/ru-RU/features/persona.json b/dashboard/src/i18n/locales/ru-RU/features/persona.json
new file mode 100644
index 000000000..e6e58ad7f
--- /dev/null
+++ b/dashboard/src/i18n/locales/ru-RU/features/persona.json
@@ -0,0 +1,146 @@
+{
+ "page": {
+ "description": "Управление настройками и поведением персонажей"
+ },
+ "buttons": {
+ "create": "Создать персонажа",
+ "createFirst": "Создать первого персонажа",
+ "edit": "Изменить",
+ "delete": "Удалить",
+ "cancel": "Отмена",
+ "save": "Сохранить",
+ "move": "Переместить",
+ "addDialogPair": "Добавить пример диалога"
+ },
+ "labels": {
+ "presetDialogs": "Примеры диалогов ({count})",
+ "createdAt": "Создан",
+ "updatedAt": "Обновлен"
+ },
+ "form": {
+ "personaId": "ID персонажа",
+ "systemPrompt": "Системный промпт",
+ "customErrorMessage": "Свое сообщение об ошибке (опционально)",
+ "customErrorMessageHelp": "Это сообщение будет отправлено пользователю при сбое запроса к LLM. Если оставить пустым, будет использовано системное сообщение по умолчанию.",
+ "presetDialogs": "Примеры диалогов",
+ "presetDialogsHelp": "Добавьте примеры взаимодействия, чтобы помочь AI лучше понять свою роль и стиль общения.",
+ "userMessage": "Сообщение пользователя",
+ "assistantMessage": "Ответ AI",
+ "tools": "Инструменты / MCP серверы",
+ "toolsHelp": "Выберите инструменты, доступные этому персонажу. Инструменты позволяют AI взаимодействовать с внешним миром: искать в интернете, выполнять расчеты и т.д.",
+ "toolsSelection": "Выбор инструментов",
+ "selectAllTools": "Выбрать все",
+ "clearAllTools": "Очистить всё",
+ "allSelected": "Выбрано всё",
+ "mcpServersQuickSelect": "Быстрый выбор MCP серверов",
+ "searchTools": "Поиск инструментов",
+ "selectedTools": "Выбранные инструменты",
+ "noToolsAvailable": "Нет доступных инструментов",
+ "noToolsFound": "Инструменты не найдены",
+ "loadingTools": "Загрузка инструментов...",
+ "allToolsAvailable": "Использовать все доступные инструменты",
+ "noToolsSelected": "Инструменты не выбраны",
+ "skills": "Навыки (Skills)",
+ "skillsHelp": "Выберите навыки, доступные этому персонажу. Навыки предоставляют AI готовые сценарии и правила работы.",
+ "skillsAllAvailable": "По умолчанию использовать все навыки",
+ "skillsSelectSpecific": "Выбрать определенные навыки",
+ "searchSkills": "Поиск навыков",
+ "selectedSkills": "Выбранные навыки",
+ "noSkillsAvailable": "Нет доступных навыков",
+ "noSkillsFound": "Навыки не найдены",
+ "loadingSkills": "Загрузка навыков...",
+ "allSkillsAvailable": "Использовать все доступные навыки",
+ "noSkillsSelected": "Навыки не выбраны",
+ "skillsRuntimeNoneWarning": "Среда выполнения Computer Use не задана. Навыки могут не работать, так как нет активного окружения.",
+ "createInFolder": "Будет создан в папке «{folder}»",
+ "rootFolder": "Все персонажи"
+ },
+ "dialog": {
+ "create": {
+ "title": "Создание персонажа"
+ },
+ "edit": {
+ "title": "Редактирование персонажа"
+ }
+ },
+ "empty": {
+ "title": "Персонажи не настроены",
+ "description": "Самое время создать одного!",
+ "folderEmpty": "Папка пуста",
+ "folderEmptyDescription": "Создайте нового персонажа или папку, чтобы начать"
+ },
+ "validation": {
+ "required": "Это поле обязательно для заполнения",
+ "minLength": "Минимум {min} символов",
+ "alphanumeric": "Разрешены только латинские буквы, цифры, подчёркивания и дефисы",
+ "dialogRequired": "{type} не может быть пустым",
+ "personaIdExists": "Персонаж с таким ID уже существует"
+ },
+ "messages": {
+ "loadError": "Не удалось загрузить список персонажей",
+ "saveSuccess": "Сохранено",
+ "saveError": "Ошибка сохранения",
+ "deleteConfirm": "Вы уверены, что хотите удалить персонажа «{id}»? Это действие необратимо.",
+ "deleteSuccess": "Удалено",
+ "deleteError": "Ошибка удаления"
+ },
+ "persona": {
+ "personasTitle": "Персонаж",
+ "toolsCount": "инстр.",
+ "skillsCount": "навыков",
+ "contextMenu": {
+ "moveTo": "Переместить в..."
+ },
+ "messages": {
+ "moveSuccess": "Персонаж перемещен",
+ "moveError": "Не удалось переместить персонажа"
+ }
+ },
+ "folder": {
+ "sidebarTitle": "Папки",
+ "rootFolder": "Корень",
+ "foldersTitle": "Папки",
+ "noFolders": "Папок нет",
+ "createButton": "Новая папка",
+ "searchPlaceholder": "Поиск папок...",
+ "form": {
+ "name": "Имя папки",
+ "description": "Описание (опционально)"
+ },
+ "validation": {
+ "nameRequired": "Имя папки не может быть пустым"
+ },
+ "contextMenu": {
+ "open": "Открыть",
+ "rename": "Переименовать",
+ "moveTo": "Переместить в...",
+ "delete": "Удалить"
+ },
+ "createDialog": {
+ "title": "Создать папку",
+ "createButton": "Создать"
+ },
+ "renameDialog": {
+ "title": "Переименовать папку"
+ },
+ "deleteDialog": {
+ "title": "Удаление папки",
+ "message": "Вы уверены, что хотите удалить папку «{name}»?",
+ "warning": "Все персонажи из этой папки будут перемещены в корневой каталог."
+ },
+ "messages": {
+ "createSuccess": "Папка создана",
+ "createError": "Ошибка создания папки",
+ "renameSuccess": "Папка переименована",
+ "renameError": "Ошибка переименования папки",
+ "deleteSuccess": "Папка удалена",
+ "deleteError": "Ошибка удаления папки"
+ }
+ },
+ "moveDialog": {
+ "title": "Перемещение",
+ "description": "Выберите папку для «{name}»",
+ "success": "Объект перемещен",
+ "error": "Ошибка перемещения"
+ }
+}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/ru-RU/features/platform.json b/dashboard/src/i18n/locales/ru-RU/features/platform.json
new file mode 100644
index 000000000..04c7613a9
--- /dev/null
+++ b/dashboard/src/i18n/locales/ru-RU/features/platform.json
@@ -0,0 +1,135 @@
+{
+ "title": "Боты",
+ "subtitle": "Управление адаптерами платформ для подключения к мессенджерам",
+ "adapters": "Адаптеры платформ",
+ "addAdapter": "Создать бота",
+ "emptyText": "Боты не настроены. Нажмите «Создать бота», чтобы начать.",
+ "viewWebhook": "Показать Webhook",
+ "webhookCopied": "URL скопирован в буфер обмена",
+ "webhookCopyFailed": "Не удалось скопировать, сделайте это вручную",
+ "webhookDialog": {
+ "title": "Адрес Webhook",
+ "description": "Используйте этот адрес для обратных вызовов. Убедитесь, что ваш AstrBot доступен из интернета. Рекомендуется указать «Внешний URL для Webhook» в Конфигурация -> Система.",
+ "close": "Закрыть"
+ },
+ "details": {
+ "adapterType": "Тип адаптера",
+ "token": "Токен",
+ "description": "Описание"
+ },
+ "logs": {
+ "title": "Логи платформы",
+ "expand": "Развернуть",
+ "collapse": "Свернуть"
+ },
+ "dialog": {
+ "add": "Добавить",
+ "edit": "Изменить",
+ "adapter": "Бот",
+ "refresh": "Обновить",
+ "cancel": "Отмена",
+ "save": "Сохранить",
+ "addPlatform": "Создать бота",
+ "connectTitle": "Подключение к {name}",
+ "viewTutorial": "Открыть руководство",
+ "noTemplates": "Шаблоны не найдены",
+ "idConflict": {
+ "title": "Конфликт ID",
+ "message": "Бот с ID «{id}» уже существует. Пожалуйста, используйте уникальный ID.",
+ "confirm": "Понятно"
+ },
+ "securityWarning": {
+ "title": "Безопасность",
+ "aiocqhttpTokenMissing": "Для защиты соединения крайне рекомендуется установить ws_reverse_token. Работа без токена небезопасна.",
+ "learnMore": "Подробнее"
+ },
+ "invalidPlatformId": "ID платформы не может содержать символы ':' или '!'."
+ },
+ "createDialog": {
+ "step1Title": "Выберите мессенджер",
+ "step1Hint": "Куда вы хотите подключить бота? (QQ, Telegram, Discord, WeChat и др.)",
+ "platformTypeLabel": "Платформа",
+ "configFileTitle": "Файл конфигурации",
+ "optional": "опционально",
+ "configHint": "Как настроить бота? Конфиг содержит модель, персонажа, базу знаний и набор плагинов.",
+ "configDefaultHint": "По умолчанию используется профиль «default». Вы сможете изменить его позже.",
+ "useExistingConfig": "Использовать существующий конфиг",
+ "selectConfigLabel": "Выберите профиль",
+ "createNewConfig": "Создать новый профиль",
+ "newConfigNameLabel": "Имя нового профиля",
+ "newConfigTitle": "Создание нового профиля",
+ "newConfigLoadFailed": "Не удалось загрузить шаблон конфигурации",
+ "addRouteRule": "Добавить правило маршрутизации",
+ "viewMode": "Просмотр",
+ "editMode": "Редактирование",
+ "noRouteRules": "Правила маршрутизации не заданы, будет использоваться профиль по умолчанию",
+ "sessionIdPlaceholder": "ID сессии или *",
+ "allSessions": "Все сессии",
+ "configMissing": "Файл конфигурации не найден",
+ "routeHint": "* При получении сообщения AstrBot ищет первое совпадение в списке сверху вниз. Используйте слэш-команду /sid, чтобы узнать ID текущей сессии. Если совпадений нет, используется профиль по умолчанию.",
+ "warningContinue": "Игнорировать и создать",
+ "warningEditAgain": "Вернуться к редактированию",
+ "configDrawerTitle": "Управление профилями",
+ "configDrawerIdLabel": "ID",
+ "configTableHeaders": {
+ "configId": "ID связанного профиля",
+ "scope": "Область применения"
+ },
+ "routeTableHeaders": {
+ "source": "Источник (тип:ID)",
+ "config": "Файл конфига",
+ "actions": "Действия"
+ },
+ "messageTypeOptions": {
+ "all": "Все сообщения",
+ "group": "Групповые (GroupMessage)",
+ "friend": "Личные (FriendMessage)"
+ },
+ "messageTypeLabels": {
+ "all": "Все",
+ "group": "Группа",
+ "friend": "ЛС"
+ }
+ },
+ "messages": {
+ "updateSuccess": "Обновлено!",
+ "addSuccess": "Добавлено!",
+ "deleteSuccess": "Удалено!",
+ "statusUpdateSuccess": "Статус обновлен!",
+ "deleteConfirm": "Вы уверены, что хотите удалить этого бота?",
+ "configNotFoundOpenConfig": "Целевой конфиг не найден. Открыта страница настроек для проверки.",
+ "updateMissingPlatformId": "Ошибка обновления: отсутствует ID платформы.",
+ "platformUpdateFailed": "Не удалось обновить платформу.",
+ "addSuccessWithConfig": "Бот успешно добавлен, профиль обновлен",
+ "configIdMissing": "Не удалось получить ID конфигурации.",
+ "routingUpdateFailed": "Ошибка обновления маршрутов: {message}",
+ "createConfigFailed": "Ошибка создания профиля: {message}",
+ "platformIdMissing": "Не удалось получить ID платформы.",
+ "routingSaveFailed": "Ошибка сохранения маршрутов: {message}"
+ },
+ "status": {
+ "enabled": "Включен",
+ "disabled": "Выключен",
+ "connecting": "Подключение",
+ "connected": "Подключен",
+ "disconnected": "Отключен",
+ "error": "Ошибка"
+ },
+ "runtimeStatus": {
+ "running": "Работает",
+ "error": "Ошибка",
+ "pending": "Ожидание",
+ "stopped": "Остановлен",
+ "unknown": "Неизвестно",
+ "errors": "ошибок"
+ },
+ "errorDialog": {
+ "title": "Детали ошибки",
+ "platformId": "ID платформы",
+ "errorCount": "Кол-во ошибок",
+ "lastError": "Последняя ошибка",
+ "occurredAt": "Время",
+ "traceback": "Стек вызовов",
+ "close": "Закрыть"
+ }
+}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/ru-RU/features/provider.json b/dashboard/src/i18n/locales/ru-RU/features/provider.json
new file mode 100644
index 000000000..1287bfbd4
--- /dev/null
+++ b/dashboard/src/i18n/locales/ru-RU/features/provider.json
@@ -0,0 +1,151 @@
+{
+ "title": "Провайдеры моделей",
+ "subtitle": "Настройка AI моделей для диалогов. Также поддерживает Dify, Coze, а также внешние Agent-сервисы.",
+ "providers": {
+ "title": "Сервис-провайдеры",
+ "settings": "Настройки",
+ "addProvider": "Добавить провайдера",
+ "providerType": "Тип провайдера",
+ "tabs": {
+ "all": "Все",
+ "chatCompletion": "Диалоги",
+ "agentRunner": "Агенты",
+ "speechToText": "STT (Речь -> Текст)",
+ "textToSpeech": "TTS (Текст -> Речь)",
+ "embedding": "Эмбеддинги",
+ "rerank": "Rerank (Ранжирование)"
+ },
+ "empty": {
+ "all": "Провайдеры не добавлены. Нажмите «Добавить провайдера», чтобы начать.",
+ "typed": "Провайдеры типа «{type}» не найдены."
+ },
+ "description": {
+ "openai": "Поддерживаются все провайдеры, совместимые с OpenAI API.",
+ "vllm_rerank": "Также поддерживает Jina AI, Cohere, PPIO и другие.",
+ "default": "Преобразование речи в текст"
+ }
+ },
+ "availability": {
+ "title": "Доступность провайдеров",
+ "subtitle": "Статус определяется путем выполнения тестового запроса. Может взиматься плата согласно тарифу API.",
+ "refresh": "Проверить статус",
+ "noData": "Нажмите «Проверить статус», чтобы узнать доступность моделей",
+ "available": "Доступен",
+ "unavailable": "Недоступен",
+ "pending": "Проверка...",
+ "errorMessage": "Ошибка",
+ "test": "Тест"
+ },
+ "logs": {
+ "title": "Логи сервиса",
+ "expand": "Развернуть",
+ "collapse": "Свернуть"
+ },
+ "dialogs": {
+ "addProvider": {
+ "title": "Новый провайдер",
+ "tabs": {
+ "basic": "Диалоги",
+ "agentRunner": "Агенты",
+ "speechToText": "Преобразование текста в речь",
+ "textToSpeech": "Переранжирование",
+ "embedding": "Эмбеддинги",
+ "rerank": "API Key"
+ },
+ "noTemplates": "Шаблоны для этого типа не найдены"
+ },
+ "config": {
+ "addTitle": "Добавить",
+ "editTitle": "Изменить",
+ "provider": "Провайдер",
+ "cancel": "Отмена",
+ "save": "Сохранить"
+ },
+ "settings": {
+ "title": "Общие настройки провайдеров",
+ "sessionSeparation": {
+ "title": "Изоляция провайдеров по сессиям",
+ "description": "Позволяет выбирать независимых провайдеров для генерации текста, TTS и STT в каждой конкретной сессии."
+ },
+ "close": "Закрыть"
+ }
+ },
+ "messages": {
+ "success": {
+ "update": "Обновлено!",
+ "add": "Добавлено!",
+ "delete": "Удалено!",
+ "statusUpdate": "Статус обновлен!",
+ "sessionSeparation": "Настройки изоляции сохранены"
+ },
+ "error": {
+ "sessionSeparation": "Не удалось загрузить настройки изоляции",
+ "fetchStatus": "Не удалось получить статус провайдеров",
+ "testError": "Тест {id} провален: {error}"
+ },
+ "confirm": {
+ "delete": "Вы уверены, что хотите удалить провайдера «{id}»?"
+ }
+ },
+ "providerTypes": {
+ "title": "Тип провайдера"
+ },
+ "providerSources": {
+ "title": "Источник провайдера",
+ "add": "Добавить",
+ "empty": "Источники не найдены",
+ "selectHint": "Пожалуйста, выберите источник провайдера",
+ "selectCreated": "Выбрать существующий источник",
+ "save": "Сохранить конфиг",
+ "saveAndFetchModels": "Сохранить и загрузить модели",
+ "fetchModels": "Загрузить список моделей",
+ "saveSuccess": "Источник успешно сохранен",
+ "saveError": "Ошибка сохранения источника",
+ "deleteConfirm": "Вы уверены, что хотите удалить источник «{id}»? Все связанные конфигурации моделей будут удалены.",
+ "deleteSuccess": "Источник удален",
+ "deleteError": "Ошибка удаления",
+ "enabled": "Включен",
+ "disabled": "Выключен",
+ "advancedConfig": "Расширенные настройки...",
+ "fields": {
+ "name": "Имя",
+ "apiKey": "Base URL",
+ "baseUrl": "Base URL"
+ },
+ "hints": {
+ "id": "Уникальный ID источника",
+ "key": "Ваш серетный API-ключ",
+ "apiBase": "Адрес API точки входа (Endpoint URL)",
+ "proxy": "Прокси сервер (HTTP/HTTPS), напр. http://127.0.0.1:7890. Используется только для запросов к этому провайдеру."
+ },
+ "labels": {
+ "proxy": "Прокси"
+ }
+ },
+ "models": {
+ "available": "Доступные модели",
+ "configured": "Настроенные модели",
+ "empty": "Модели не настроены. Нажмите «Загрузить список моделей» выше.",
+ "noModelsFound": "Модели не найдены",
+ "fetchError": "Не удалось получить список моделей",
+ "addSuccess": "Модель {model} успешно добавлена",
+ "deleteConfirm": "Вы уверены, что хотите удалить модель «{id}»?",
+ "deleteSuccess": "Модель удалена",
+ "deleteError": "Ошибка удаления модели",
+ "testSuccess": "Тест модели «{id}» пройден успешно",
+ "testError": "Тест модели провален",
+ "searchPlaceholder": "Поиск по имени или ID",
+ "manualAddButton": "Добавить вручную",
+ "manualDialogTitle": "Произвольная модель",
+ "manualDialogModelLabel": "Код модели (напр. gpt-4o-mini)",
+ "manualDialogPreviewLabel": "Отображаемый ID (авто)",
+ "manualDialogPreviewHint": "Будет выглядеть как: SourceID/ModelID",
+ "manualModelRequired": "Укажите ID модели",
+ "manualModelExists": "Эта модель уже добавлена",
+ "configure": "Настроить",
+ "tooltips": {
+ "providerId": "ID провайдера",
+ "modelId": "ID модели"
+ }
+ }
+}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/ru-RU/features/session-management.json b/dashboard/src/i18n/locales/ru-RU/features/session-management.json
new file mode 100644
index 000000000..19c3a9aa5
--- /dev/null
+++ b/dashboard/src/i18n/locales/ru-RU/features/session-management.json
@@ -0,0 +1,130 @@
+{
+ "title": "Управление сессиями",
+ "subtitle": "Настройка индивидуальных правил для конкретных диалогов. Эти правила имеют приоритет над глобальной конфигурацией.",
+ "buttons": {
+ "refresh": "Обновить",
+ "edit": "Изменить",
+ "editRule": "Редактировать правило",
+ "deleteAllRules": "Удалить все правила",
+ "addRule": "Добавить правило",
+ "save": "Сохранить",
+ "cancel": "Отмена",
+ "delete": "Удалить",
+ "clear": "Очистить",
+ "next": "Далее",
+ "editCustomName": "Изменить заметку",
+ "batchDelete": "Массовое удаление"
+ },
+ "customRules": {
+ "title": "Пользовательские правила",
+ "rulesCount": "правил",
+ "hasRules": "Настроено",
+ "noRules": "Индивидуальных правил нет",
+ "noRulesDesc": "Нажмите «Добавить правило», чтобы задать настройки для конкретного диалога",
+ "serviceConfig": "Сервис",
+ "pluginConfig": "Плагины",
+ "kbConfig": "База знаний",
+ "providerConfig": "Модель",
+ "configured": "Настроено",
+ "noCustomName": "Без заметки"
+ },
+ "quickEditName": {
+ "title": "Редактирование заметки"
+ },
+ "search": {
+ "placeholder": "Поиск сессии..."
+ },
+ "table": {
+ "headers": {
+ "umoInfo": "Источник (UMO)",
+ "rulesOverview": "Обзор правил",
+ "actions": "Действия"
+ }
+ },
+ "persona": {
+ "none": "Из конфигурации"
+ },
+ "provider": {
+ "followConfig": "Из конфигурации"
+ },
+ "addRule": {
+ "title": "Добавление правила",
+ "description": "Выберите источник сообщения (UMO) для настройки. Индивидуальные правила приоритетнее глобальных. Используйте команду /sid в чате, чтобы узнать информацию об источнике.",
+ "selectUmo": "Выберите сессию",
+ "noUmos": "Нет доступных сессий"
+ },
+ "ruleEditor": {
+ "title": "Редактор правил",
+ "description": "Настройте поведение для этой сессии. Настройки ниже перекроют глобальный конфиг.",
+ "serviceConfig": {
+ "title": "Сервисные настройки",
+ "sessionEnabled": "Обрабатывать сообщения",
+ "llmEnabled": "Использовать LLM",
+ "ttsEnabled": "Использовать TTS",
+ "customName": "Заметка для сессии"
+ },
+ "providerConfig": {
+ "title": "Выбор моделей",
+ "chatProvider": "Чат-модель",
+ "sttProvider": "STT (Распознавание)",
+ "ttsProvider": "TTS (Озвучка)"
+ },
+ "personaConfig": {
+ "title": "Персона",
+ "selectPersona": "Выберите Persona",
+ "hint": "При выборе Persona все диалоги из этого источника будут использовать именно её."
+ },
+ "pluginConfig": {
+ "title": "Плагины",
+ "disabledPlugins": "Отключенные плагины",
+ "hint": "Выберите плагины, которые нужно ОТКЛЮЧИТЬ в этой сессии. Остальные останутся активными."
+ },
+ "kbConfig": {
+ "title": "База знаний",
+ "selectKbs": "Выбор баз знаний",
+ "topK": "Количество результатов (Top K)",
+ "enableRerank": "Использовать Rerank"
+ }
+ },
+ "deleteConfirm": {
+ "title": "Подтверждение",
+ "message": "Удалить все настройки для этой сессии? Будут применены глобальные настройки."
+ },
+ "batchDeleteConfirm": {
+ "title": "Массовое удаление",
+ "message": "Удалить {count} выбранных правил? Будут применены глобальные настройки."
+ },
+ "batchOperations": {
+ "title": "Массовые операции",
+ "hint": "Быстрое изменение настроек для группы сессий",
+ "scope": "Область применения",
+ "scopeSelected": "Выбранные",
+ "scopeAll": "Все сессии",
+ "scopeGroup": "Все группы",
+ "scopePrivate": "Личные диалоги",
+ "llmStatus": "Статус LLM",
+ "ttsStatus": "Статус TTS",
+ "chatProvider": "Чат-модель",
+ "ttsProvider": "TTS-модель",
+ "apply": "Применить"
+ },
+ "status": {
+ "enabled": "Включено",
+ "disabled": "Выключено"
+ },
+ "messages": {
+ "refreshSuccess": "Данные обновлены",
+ "loadError": "Ошибка загрузки",
+ "saveSuccess": "Настройки сохранены",
+ "saveError": "Ошибка сохранения",
+ "clearSuccess": "Очищено",
+ "clearError": "Ошибка очистки",
+ "deleteSuccess": "Удалено",
+ "deleteError": "Ошибка удаления",
+ "noChanges": "Изменений не обнаружено",
+ "batchDeleteSuccess": "Массовое удаление выполнено",
+ "batchDeleteError": "Ошибка массового удаления",
+ "batchUpdateError": "Ошибка пакетного обновления",
+ "batchUpdateSuccess": "Пакетное обновление успешно выполнено"
+ }
+}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/ru-RU/features/settings.json b/dashboard/src/i18n/locales/ru-RU/features/settings.json
new file mode 100644
index 000000000..29b826fff
--- /dev/null
+++ b/dashboard/src/i18n/locales/ru-RU/features/settings.json
@@ -0,0 +1,180 @@
+{
+ "network": {
+ "title": "Сеть",
+ "githubProxy": {
+ "title": "Зеркало GitHub",
+ "subtitle": "Адрес для ускорения загрузки плагинов и обновлений AstrBot. Особенно актуально для пользователей из Китая. Все адреса предоставляются как есть, если обновление не удается — проверьте доступность выбранного зеркала.",
+ "label": "Выбрать ускоритель GitHub"
+ },
+ "proxySelector": {
+ "title": "Ускорение GitHub",
+ "noProxy": "Не использовать",
+ "useProxy": "Включить",
+ "testConnection": "Проверить соединение",
+ "available": "Доступен",
+ "unavailable": "Недоступен",
+ "custom": "Свой вариант"
+ }
+ },
+ "theme": {
+ "title": "Тема оформления",
+ "subtitle": "Настройка основных и дополнительных цветов. Изменения вступают в силу немедленно и сохраняются в браузере.",
+ "customize": {
+ "title": "Цвета темы",
+ "primary": "Основной",
+ "secondary": "Дополнительный",
+ "reset": "Сбросить"
+ }
+ },
+ "system": {
+ "title": "Система",
+ "restart": {
+ "title": "Перезапуск",
+ "subtitle": "Выполнить мягкий перезапуск AstrBot",
+ "button": "Перезагрузить"
+ },
+ "migration": {
+ "title": "Миграция данных в v4.0.0",
+ "subtitle": "Если у вас возникли проблемы с совместимостью данных после обновления, запустите помощник вручную.",
+ "button": "Запустить миграцию"
+ },
+ "backup": {
+ "title": "Резервное копирование",
+ "subtitle": "Важнейший инструмент для безопасного переноса данных между серверами.",
+ "button": "Управление бэкапами"
+ }
+ },
+ "sidebar": {
+ "title": "Боковая панель",
+ "customize": {
+ "title": "Настройка меню",
+ "subtitle": "Перетаскивайте элементы, чтобы изменить их порядок или скрыть в группе «Дополнительно». Настройки сохраняются локально в браузере.",
+ "reset": "Сбросить порядок",
+ "mainItems": "Основные разделы",
+ "moreItems": "Дополнительно"
+ }
+ },
+ "backup": {
+ "dialog": {
+ "title": "Резервное копирование"
+ },
+ "tabs": {
+ "export": "Экспорт",
+ "import": "Импорт",
+ "list": "Список копий"
+ },
+ "export": {
+ "title": "Создать резервную копию",
+ "description": "Экспорт всех данных в ZIP-архив, включая базы данных, базу знаний, конфигурации и вложения.",
+ "includes": "Включает: основную БД, векторные индексы знаний, файлы конфигурации, медиа-вложения.",
+ "button": "Начать экспорт",
+ "processing": "Экспорт...",
+ "wait": "Пожалуйста, подождите, мы упаковываем данные...",
+ "completed": "Готово!",
+ "download": "Скачать архив",
+ "another": "Создать новый",
+ "failed": "Ошибка экспорта",
+ "retry": "Повторить"
+ },
+ "import": {
+ "title": "Восстановление из копии",
+ "warning": "⚠️ Внимание! Импорт полностью удалит и перезапишет текущие данные! Убедитесь, что у вас есть копия текущего состояния.",
+ "selectFile": "Выберите ZIP-архив",
+ "uploadAndCheck": "Загрузить и проверить",
+ "uploading": "Загрузка...",
+ "uploadWait": "Файл передается на сервер...",
+ "uploadInit": "Инициализация...",
+ "uploadingChunks": "Передача фрагментов...",
+ "uploadComplete": "Загружено, идет сборка...",
+ "checking": "Проверка структуры...",
+ "invalidBackup": "Некорректный файл резервной копии",
+ "backupContents": "Состав архива",
+ "tables": "таблиц БД",
+ "knowledgeBases": "баз знаний",
+ "configFiles": "конфигов",
+ "confirmImport": "Подтвердите импорт",
+ "button": "Начать восстановление",
+ "processing": "Восстановление...",
+ "wait": "Идет процесс развертывания данных...",
+ "completed": "Восстановление успешно завершено!",
+ "restartRequired": "Данные восстановлены. Необходимо немедленно перезапустить AstrBot для вступления изменений в силу.",
+ "restartNow": "Перезапустить сейчас",
+ "failed": "Ошибка импорта",
+ "retry": "Повторить",
+ "version": {
+ "backupVersion": "Версия бэкапа",
+ "currentVersion": "Текущая версия",
+ "backupTime": "Дата создания",
+ "matchTitle": "✅ Версии совпадают",
+ "matchMessage": "Импорт перезапишет все текущие данные, включая:\n• Основную БД (чаты, настройки)\n• Базы знаний\n• Плагины и их данные\n• Файлы конфигурации\n\nЭто действие необратимо! Продолжить?",
+ "minorDiffTitle": "⚠️ Разница в минорной версии",
+ "minorDiffMessage": "Разница в минорных версиях обычно допустима, но структура данных могла немного измениться. Все текущие данные будут удалены!\n\nПродолжить импорт?",
+ "majorDiffTitle": "⛔ Импорт невозможен",
+ "majorDiffMessage": "Версии основного выпуска различаются. Импорт между мажорными версиями может привести к фатальному повреждению данных.\nИспользуйте AstrBot той же основной версии."
+ }
+ },
+ "list": {
+ "empty": "Резервные копии не найдены",
+ "refresh": "Обновить список",
+ "confirmDelete": "Вы уверены, что хотите безвозвратно удалить эту копию?",
+ "uploaded": "Загружено",
+ "restore": "Восстановить из этого файла",
+ "rename": "Переименовать",
+ "renameTitle": "Переименование файла",
+ "newName": "Новое имя",
+ "renameHint": "Разрешены буквы, цифры, точки, дефисы и подчеркивания",
+ "renameRequired": "Введите имя файла",
+ "renameInvalidChars": "Имя содержит недопустимые символы",
+ "renameFailed": "Ошибка переименования",
+ "ftpHint": "Для больших архивов вы можете загружать их напрямую в папку data/backups через FTP/SFTP."
+ }
+ },
+ "apiKey": {
+ "title": "API Keys",
+ "manageTitle": "Ключи доступа разработчика",
+ "subtitle": "Управление токенами для доступа к открытому HTTP API AstrBot.",
+ "name": "Имя ключа",
+ "expiresInDays": "Срок действия",
+ "expiryOptions": {
+ "day1": "1 день",
+ "day7": "7 дней",
+ "day30": "30 дней",
+ "day90": "90 дней",
+ "permanent": "Бессрочно"
+ },
+ "permanentWarning": "Бессрочные ключи менее безопасны. Пожалуйста, храните их в надежном месте.",
+ "scopes": "Область доступа (Scopes)",
+ "create": "Создать API Key",
+ "revoke": "Отозвать",
+ "delete": "Удалить",
+ "copy": "Копировать",
+ "docsLink": "Документация API",
+ "plaintextHint": "Обязательно сохраните ключ сейчас. После закрытия окна вы больше не сможете увидеть его значение.",
+ "empty": "Ключи не созданы",
+ "status": {
+ "active": "Активен",
+ "inactive": "Неактивен"
+ },
+ "table": {
+ "name": "Имя",
+ "prefix": "Префикс",
+ "scopes": "Права",
+ "status": "Статус",
+ "lastUsed": "Использован",
+ "createdAt": "Создан",
+ "actions": "Действия"
+ },
+ "messages": {
+ "loadFailed": "Не удалось загрузить ключи",
+ "scopeRequired": "Выберите хотя бы одну область доступа",
+ "createSuccess": "API Key создан",
+ "createFailed": "Ошибка создания ключа",
+ "revokeSuccess": "Ключ отозван",
+ "revokeFailed": "Ошибка отзыва ключа",
+ "deleteSuccess": "Ключ удален",
+ "deleteFailed": "Ошибка удаления ключа",
+ "copySuccess": "Ключ скопирован",
+ "copyFailed": "Ошибка копирования"
+ }
+ }
+}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/ru-RU/features/subagent.json b/dashboard/src/i18n/locales/ru-RU/features/subagent.json
new file mode 100644
index 000000000..368bd2046
--- /dev/null
+++ b/dashboard/src/i18n/locales/ru-RU/features/subagent.json
@@ -0,0 +1,65 @@
+{
+ "page": {
+ "title": "Оркестрация SubAgent",
+ "beta": "Экспериментально",
+ "subtitle": "Основной LLM может напрямую использовать свои инструменты или делегировать задачи SubAgent через handoff."
+ },
+ "actions": {
+ "refresh": "Обновить",
+ "save": "Сохранить",
+ "add": "Добавить SubAgent",
+ "delete": "Удалить",
+ "close": "Закрыть"
+ },
+ "switches": {
+ "enable": "Включить оркестрацию SubAgent",
+ "enableHint": "Включить функциональность под-агентов",
+ "dedupe": "Дедупликация инструментов основного LLM (скрывать инструменты, дублируемые SubAgent)",
+ "dedupeHint": "Удалить дублирующиеся инструменты из основного агента"
+ },
+ "description": {
+ "disabled": "Выключено: SubAgent отключен; основной LLM подключает инструменты согласно правилам персонажа (все по умолчанию) и вызывает их напрямую.",
+ "enabled": "Включено: основной LLM сохраняет свои инструменты и подключает инструменты делегирования transfer_to_*. При дедупликации инструменты, пересекающиеся с SubAgent, удаляются из основного набора."
+ },
+ "section": {
+ "title": "Субагенты",
+ "globalSettings": "Глобальные настройки"
+ },
+ "cards": {
+ "statusEnabled": "Включено",
+ "statusDisabled": "Отключено",
+ "unnamed": "Безымянный SubAgent",
+ "transferPrefix": "передать_{name}",
+ "switchLabel": "Включить",
+ "previewTitle": "Предпросмотр: инструмент handoff, видимый основному LLM",
+ "personaChip": "Персонаж: {id}",
+ "personaPreview": "ПРЕДПРОСМОТР ПЕРСОНАЖА"
+ },
+ "form": {
+ "nameLabel": "Имя агента (используется для transfer_to_{name})",
+ "nameHint": "Используйте строчные латинские буквы и подчеркивания; имя должно быть глобально уникальным.",
+ "providerLabel": "Chat Provider (опционально)",
+ "providerHint": "Оставьте пустым, чтобы использовать глобальный провайдер по умолчанию.",
+ "personaLabel": "Выберите персонажа",
+ "personaHint": "SubAgent наследует системные настройки и инструменты выбранного персонажа.",
+ "descriptionLabel": "Описание для основного LLM (используется для принятия решения о handoff)",
+ "descriptionHint": "Отображается как описание инструмента transfer_to_* — будьте кратки и ясны."
+ },
+ "messages": {
+ "loadConfigFailed": "Не удалось загрузить конфигурацию",
+ "loadPersonaFailed": "Не удалось загрузить список персонажей",
+ "nameMissing": "У SubAgent отсутствует имя",
+ "nameInvalid": "Недопустимое имя SubAgent: только строчные латинские буквы/цифры/подчеркивания, должно начинаться с буквы",
+ "nameDuplicate": "Дублирующееся имя SubAgent: {name}",
+ "personaMissing": "У SubAgent {name} не выбран персонаж",
+ "saveSuccess": "Успешно сохранено",
+ "saveFailed": "Ошибка сохранения",
+ "nameRequired": "Имя обязательно",
+ "namePattern": "Только строчные буквы, цифры и подчеркивание"
+ },
+ "empty": {
+ "title": "Агенты не настроены",
+ "subtitle": "Добавьте первого под-агента, чтобы начать",
+ "action": "Создать первого агента"
+ }
+}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/ru-RU/features/tool-use.json b/dashboard/src/i18n/locales/ru-RU/features/tool-use.json
new file mode 100644
index 000000000..f37707e8f
--- /dev/null
+++ b/dashboard/src/i18n/locales/ru-RU/features/tool-use.json
@@ -0,0 +1,195 @@
+{
+ "title": "Инструменты и функции",
+ "subtitle": "Управление MCP-серверами и доступными функциями",
+ "tooltip": {
+ "info": "Что такое Function Calling и MCP?",
+ "marketplace": "Обзор и установка MCP-серверов от сообщества",
+ "serverConfig": "Конфигурация MCP-серверов (stdio) поддерживает следующие поля:\ncommand: имя команды (например, python или uv)\nargs: массив аргументов (например, [\"run\", \"server.py\"])\nenv: объект переменных окружения (например, {\"api_key\": \"abc\"})\ncwd: рабочий каталог (например, /path/to/server)\nencoding: кодировка вывода (по умолчанию utf-8)\nПодробности см. в документации MCP.\n⚠️ Если вы используете Docker, устанавливайте сервера в смонтированную директорию data."
+ },
+ "tabs": {
+ "local": "Локальные сервера",
+ "marketplace": "Магазин MCP"
+ },
+ "mcpServers": {
+ "title": "MCP Сервера",
+ "buttons": {
+ "refresh": "Обновить",
+ "add": "Добавить сервер",
+ "useTemplateStdio": "Шаблон Stdio",
+ "useTemplateStreamableHttp": "Шаблон Streamable HTTP",
+ "useTemplateSse": "Шаблон SSE",
+ "sync": "Синхронизировать"
+ },
+ "empty": "MCP-сервера не найдены. Нажмите «Добавить сервер».",
+ "status": {
+ "noTools": "Нет доступных инструментов",
+ "availableTools": "Доступные инструменты",
+ "configSummary": "Конфигурация: {keys}",
+ "noConfig": "Конфигурация не задана"
+ }
+ },
+ "functionTools": {
+ "title": "Функции (Tools)",
+ "buttons": {
+ "view": "Показать инструменты"
+ },
+ "search": "Поиск по функциям",
+ "empty": "Доступные инструменты не найдены",
+ "description": "Описание функции",
+ "parameters": "Параметры",
+ "noParameters": "У этого инструмента нет параметров",
+ "table": {
+ "paramName": "Параметр",
+ "type": "Тип",
+ "description": "Описание",
+ "required": "Обяз.",
+ "origin": "Источник",
+ "originName": "Имя источника",
+ "actions": "Действия"
+ }
+ },
+ "marketplace": {
+ "title": "Магазин MCP-серверов",
+ "search": "Поиск по магазину",
+ "buttons": {
+ "refresh": "Обновить",
+ "detail": "Инфо",
+ "import": "Импорт"
+ },
+ "loading": "Загрузка списка серверов...",
+ "empty": "Доступных MCP-серверов не найдено",
+ "status": {
+ "availableTools": "Инструментов: {count}",
+ "noToolsInfo": "Нет данных об инструментах"
+ }
+ },
+ "dialogs": {
+ "addServer": {
+ "title": "Добавление MCP-сервера",
+ "editTitle": "Редактирование MCP-сервера",
+ "fields": {
+ "name": "Название сервера",
+ "nameRequired": "Название обязательно",
+ "enable": "Включить сервер",
+ "config": "Конфигурация сервера"
+ },
+ "errors": {
+ "configEmpty": "Конфигурация не может быть пустой",
+ "jsonFormat": "Ошибка формата JSON: {error}",
+ "jsonParse": "Ошибка разбора JSON: {error}"
+ },
+ "buttons": {
+ "cancel": "Отмена",
+ "save": "Сохранить",
+ "testConnection": "Тест связи",
+ "sync": "Синхронизировать"
+ },
+ "tips": {
+ "timeoutConfig": "Тайм-аут вызова инструментов настраивается отдельно на странице конфигурации"
+ }
+ },
+ "serverDetail": {
+ "title": "Детали сервера",
+ "installConfig": "Конфигурация установки",
+ "availableTools": "Список инструментов",
+ "buttons": {
+ "close": "Закрыть",
+ "importConfig": "Импортировать конфиг"
+ }
+ },
+ "confirmDelete": "Вы уверены, что хотите удалить сервер «{name}»?",
+ "syncProvider": {
+ "title": "Синхронизация MCP",
+ "subtitle": "Загрузка конфигурации MCP-серверов от провайдера",
+ "steps": {
+ "selectProvider": "Шаг 1: Провайдер",
+ "configureAuth": "Шаг 2: Авторизация",
+ "syncServers": "Шаг 3: Синхронизация"
+ },
+ "providers": {
+ "modelscope": "ModelScope",
+ "description": "ModelScope — это сообщество моделей с открытым исходным кодом, предоставляющее различные MCP-сервера для AI-сервисов"
+ },
+ "fields": {
+ "provider": "Выберите провайдера",
+ "accessToken": "Токен доступа",
+ "tokenRequired": "Токен обязателен",
+ "tokenHint": "Введите ваш токен доступа ModelScope"
+ },
+ "buttons": {
+ "cancel": "Отмена",
+ "previous": "Назад",
+ "next": "Далее",
+ "sync": "Начать",
+ "getToken": "Получить токен"
+ },
+ "status": {
+ "selectProvider": "Пожалуйста, выберите провайдера MCP-серверов",
+ "enterToken": "Введите токен для продолжения",
+ "readyToSync": "Готов к синхронизации"
+ },
+ "messages": {
+ "syncSuccess": "MCP-сервера успешно синхронизированы!",
+ "syncError": "Ошибка синхронизации: {error}",
+ "tokenHelp": "Как получить токен ModelScope? Нажмите кнопку справа для инструкции"
+ }
+ }
+ },
+ "messages": {
+ "getServersError": "Ошибка получения списка серверов: {error}",
+ "getToolsError": "Ошибка получения списка инструментов: {error}",
+ "saveSuccess": "Настройки сохранены!",
+ "saveError": "Ошибка сохранения: {error}",
+ "deleteSuccess": "Сервер удален успешно!",
+ "deleteError": "Ошибка удаления: {error}",
+ "updateSuccess": "Обновлено успешно!",
+ "updateError": "Ошибка обновления: {error}",
+ "getMarketError": "Не удалось загрузить магазин MCP: {error}",
+ "importError": {
+ "noConfig": "У этого сервера нет доступной конфигурации",
+ "invalidFormat": "Неверный формат конфигурации",
+ "failed": "Импорт не удался: {error}"
+ },
+ "configParseError": "Ошибка разбора конфигурации: {error}",
+ "noAvailableConfig": "Конфигурация отсутствует",
+ "toggleToolSuccess": "Статус инструмента изменен!",
+ "toggleToolError": "Не удалось изменить статус: {error}",
+ "testError": "Ошибка теста связи: {error}"
+ },
+ "syncProvider": {
+ "title": "Синхронизация серверов MCP",
+ "subtitle": "Синхронизировать конфигурации серверов MCP от провайдеров с локальными",
+ "steps": {
+ "selectProvider": "Шаг 1: Выберите провайдер",
+ "configureAuth": "Шаг 2: Настройте аутентификацию",
+ "syncServers": "Шаг 3: Синхронизируйте серверы"
+ },
+ "providers": {
+ "modelscope": "ModelScope",
+ "description": "ModelScope — это сообщество открытых моделей, предоставляющее серверы MCP для различных сервисов машинного обучения и ИИ"
+ },
+ "fields": {
+ "provider": "Выберите провайдер",
+ "accessToken": "Токен доступа",
+ "tokenRequired": "Требуется токен доступа",
+ "tokenHint": "Введите ваш токен доступа ModelScope"
+ },
+ "buttons": {
+ "cancel": "Отмена",
+ "previous": "Назад",
+ "next": "Далее",
+ "sync": "Начать синхронизацию",
+ "getToken": "Получить токен"
+ },
+ "status": {
+ "selectProvider": "Пожалуйста, выберите провайдер сервера MCP",
+ "enterToken": "Введите токен доступа для продолжения",
+ "readyToSync": "Готово к синхронизации конфигураций серверов"
+ },
+ "messages": {
+ "syncSuccess": "Серверы MCP успешно синхронизированы!",
+ "syncError": "Ошибка синхронизации: {error}",
+ "tokenHelp": "Как получить токен доступа ModelScope? Нажмите кнопку справа для получения инструкций"
+ }
+ }
+}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/ru-RU/features/trace.json b/dashboard/src/i18n/locales/ru-RU/features/trace.json
new file mode 100644
index 000000000..484985bab
--- /dev/null
+++ b/dashboard/src/i18n/locales/ru-RU/features/trace.json
@@ -0,0 +1,10 @@
+{
+ "title": "Трассировка (Trace)",
+ "autoScroll": {
+ "enabled": "Автопрокрутка: ВКЛ",
+ "disabled": "Автопрокрутка: ВЫКЛ"
+ },
+ "hint": "В данный момент записываются только вызовы моделей основного агента AstrBot. Система будет совершенствоваться.",
+ "recording": "Запись...",
+ "paused": "Пауза"
+}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/ru-RU/features/welcome.json b/dashboard/src/i18n/locales/ru-RU/features/welcome.json
new file mode 100644
index 000000000..ea7d3043a
--- /dev/null
+++ b/dashboard/src/i18n/locales/ru-RU/features/welcome.json
@@ -0,0 +1,37 @@
+{
+ "greeting": {
+ "morning": "Доброе утро, добро пожаловать в AstrBot",
+ "afternoon": "Добрый день, добро пожаловать в AstrBot",
+ "evening": "Добрый вечер, добро пожаловать в AstrBot",
+ "newYear": "С Новым Годом!"
+ },
+ "subtitle": "Сначала пройдите базовое руководство. Настройку платформ и провайдеров моделей можно завершить позже.",
+ "announcement": {
+ "title": "Объявление"
+ },
+ "onboard": {
+ "title": "Быстрый старт",
+ "subtitle": "Вы можете выполнить первичную настройку прямо здесь.",
+ "step1Title": "Настройка платформ",
+ "step1Desc": "Подключите AstrBot к QQ, Lark, WeChat, Telegram и другим мессенджерам.",
+ "step2Title": "Настройка AI моделей",
+ "step2Desc": "Выберите и настройте AI провайдеров для AstrBot.",
+ "configure": "Настроить",
+ "skip": "Пропустить",
+ "pending": "Ожидает",
+ "completed": "Готово",
+ "skipped": "Пропущено",
+ "platformLoadFailed": "Ошибка загрузки конфигурации платформ",
+ "providerLoadFailed": "Ошибка загрузки конфигурации провайдеров",
+ "providerUpdateFailed": "Ошибка обновления провайдера по умолчанию в файле default",
+ "providerDefaultUpdated": "Провайдер {id} установлен по умолчанию в файле default"
+ },
+ "resources": {
+ "title": "Ресурсы",
+ "githubDesc": "Поставьте нам звезду на GitHub!",
+ "docsTitle": "Документация",
+ "docsDesc": "Официальная документация AstrBot.",
+ "afdianTitle": "Afdian",
+ "afdianDesc": "Поддержите команду AstrBot через Afdian."
+ }
+}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/ru-RU/messages/errors.json b/dashboard/src/i18n/locales/ru-RU/messages/errors.json
new file mode 100644
index 000000000..90ea43c85
--- /dev/null
+++ b/dashboard/src/i18n/locales/ru-RU/messages/errors.json
@@ -0,0 +1,39 @@
+{
+ "network": {
+ "timeout": "Время ожидания запроса истекло, попробуйте позже",
+ "connection": "Ошибка сетевого соединения. Проверьте интернет",
+ "server": "Внутренняя ошибка сервера. Обратитесь в поддержку",
+ "unavailable": "Сервис временно недоступен",
+ "forbidden": "Доступ запрещен"
+ },
+ "validation": {
+ "required": "Это поле обязательно для заполнения",
+ "invalid": "Неверный формат ввода",
+ "tooLong": "Введено слишком много символов",
+ "tooShort": "Введено слишком мало символов",
+ "email": "Укажите корректный email",
+ "url": "Укажите корректный URL",
+ "number": "Введите числовое значение"
+ },
+ "auth": {
+ "unauthorized": "Авторизация не выполнена, войдите снова",
+ "forbidden": "Недостаточно прав для выполнения операции",
+ "tokenExpired": "Сессия истекла, пожалуйста, войдите заново",
+ "invalidCredentials": "Неверное имя пользователя или пароль"
+ },
+ "file": {
+ "uploadFailed": "Загрузка файла не удалась",
+ "invalidFormat": "Неподдерживаемый формат файла",
+ "tooLarge": "Файл слишком большой",
+ "notFound": "Файл не найден"
+ },
+ "operation": {
+ "failed": "Операция не удалась",
+ "cancelled": "Операция отменена",
+ "notSupported": "Действие не поддерживается",
+ "conflict": "Конфликт операций, попробуйте позже"
+ },
+ "browser": {
+ "audioNotSupported": "Ваш браузер не поддерживает воспроизведение аудио."
+ }
+}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/ru-RU/messages/success.json b/dashboard/src/i18n/locales/ru-RU/messages/success.json
new file mode 100644
index 000000000..1501d5cb2
--- /dev/null
+++ b/dashboard/src/i18n/locales/ru-RU/messages/success.json
@@ -0,0 +1,23 @@
+{
+ "operation": {
+ "saved": "Сохранено",
+ "created": "Создано",
+ "updated": "Обновлено успешно",
+ "deleted": "Удалено",
+ "uploaded": "Загружено",
+ "downloaded": "Скачано",
+ "imported": "Импорт завершен",
+ "exported": "Экспорт завершен",
+ "copied": "Скопировано в буфер",
+ "sent": "Отправлено"
+ },
+ "connection": {
+ "connected": "Подключено",
+ "authenticated": "Вход выполнен",
+ "synchronized": "Синхронизация завершена"
+ },
+ "validation": {
+ "valid": "Проверка пройдена",
+ "completed": "Готово"
+ }
+}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/ru-RU/messages/validation.json b/dashboard/src/i18n/locales/ru-RU/messages/validation.json
new file mode 100644
index 000000000..07d061579
--- /dev/null
+++ b/dashboard/src/i18n/locales/ru-RU/messages/validation.json
@@ -0,0 +1,25 @@
+{
+ "required": "Это поле обязательно",
+ "email": "Введите корректный email",
+ "url": "Введите корректный URL",
+ "number": "Введите число",
+ "min": "Минимальное значение: {min}",
+ "max": "Максимальное значение: {max}",
+ "minLength": "Минимум {length} симв.",
+ "maxLength": "Максимум {length} симв.",
+ "pattern": "Неверный формат",
+ "unique": "Такое значение уже существует",
+ "confirm": "Значения не совпадают",
+ "fileSize": "Размер файла не должен превышать {size}MB",
+ "fileType": "Неподдерживаемый тип файла",
+ "required_field": "Заполните обязательные поля",
+ "invalid_format": "Некорректный формат",
+ "password_too_short": "Пароль должен быть не менее 8 символов",
+ "password_too_weak": "Пароль слишком слабый",
+ "invalid_phone": "Некорректный номер телефона",
+ "invalid_date": "Некорректная дата",
+ "date_range": "Неверный диапазон дат",
+ "upload_failed": "Загрузка не удалась",
+ "network_error": "Ошибка сети, попробуйте снова",
+ "operation_cannot_be_undone": "⚠️ Это действие нельзя отменить, будьте осторожны!"
+}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/zh-CN/features/config-metadata.json b/dashboard/src/i18n/locales/zh-CN/features/config-metadata.json
index e5eea63fd..be5299518 100644
--- a/dashboard/src/i18n/locales/zh-CN/features/config-metadata.json
+++ b/dashboard/src/i18n/locales/zh-CN/features/config-metadata.json
@@ -3,7 +3,7 @@
"name": "AI 配置",
"agent_runner": {
"description": "Agent 执行方式",
- "hint": "选择 AI 对话的执行器,默认为 AstrBot 内置 Agent 执行器,可使用 AstrBot 内的知识库、人格、工具调用功能。如果不打算接入 Dify 或 Coze 等第三方 Agent 执行器,不需要修改此节。",
+ "hint": "选择 AI 对话的执行器,默认为 AstrBot 内置 Agent 执行器,可使用 AstrBot 内的知识库、人格、工具调用功能。如果不打算接入 Dify、Coze、DeerFlow 等第三方 Agent 执行器,不需要修改此节。",
"provider_settings": {
"enable": {
"description": "启用",
@@ -15,7 +15,8 @@
"内置 Agent",
"Dify",
"Coze",
- "阿里云百炼应用"
+ "阿里云百炼应用",
+ "DeerFlow"
]
},
"coze_agent_runner_provider_id": {
@@ -26,6 +27,9 @@
},
"dashscope_agent_runner_provider_id": {
"description": "阿里云百炼应用 Agent 执行器提供商 ID"
+ },
+ "deerflow_agent_runner_provider_id": {
+ "description": "DeerFlow Agent 执行器提供商 ID"
}
}
},
@@ -160,6 +164,22 @@
"booter": {
"description": "沙箱环境驱动器"
},
+ "shipyard_neo_endpoint": {
+ "description": "Shipyard Neo API Endpoint",
+ "hint": "Shipyard Neo(Bay) 服务的 API 地址,默认 http://127.0.0.1:8114。"
+ },
+ "shipyard_neo_access_token": {
+ "description": "Shipyard Neo 访问令牌",
+ "hint": "Bay 的 API Key(sk-bay-...)。留空时自动从 credentials.json 发现。"
+ },
+ "shipyard_neo_profile": {
+ "description": "Shipyard Neo Profile",
+ "hint": "Shipyard Neo 沙箱 profile,例如 python-default。"
+ },
+ "shipyard_neo_ttl": {
+ "description": "Shipyard Neo Sandbox 存活时间(秒)",
+ "hint": "Shipyard Neo 沙箱的生存时间(秒)。"
+ },
"shipyard_endpoint": {
"description": "Shipyard API Endpoint",
"hint": "Shipyard 服务的 API 访问地址。"
@@ -353,7 +373,8 @@
"hint": "可选的 Discord 活动名称。留空则不设置活动。"
},
"discord_command_register": {
- "description": "是否自动将插件指令注册为 Discord 斜杠指令"
+ "description": "注册 Discord 指令",
+ "hint": "启用后,自动将插件指令注册为 Discord 斜杠指令"
},
"discord_proxy": {
"description": "Discord 代理地址",
@@ -522,7 +543,7 @@
},
"unified_webhook_mode": {
"description": "统一 Webhook 模式",
- "hint": "启用后,将使用 AstrBot 统一 Webhook 入口,无需单独开启端口。回调地址为 /api/platform/webhook/{webhook_uuid}。"
+ "hint": "Webhook 模式下使用 AstrBot 统一 Webhook 入口,无需单独开启端口。回调地址为 /api/platform/webhook/{webhook_uuid}。"
},
"webhook_uuid": {
"description": "Webhook UUID",
@@ -532,13 +553,41 @@
"description": "企业微信智能机器人的名字",
"hint": "请务必填写正确,否则无法使用一些指令。"
},
+ "wecom_ai_bot_connection_mode": {
+ "description": "企业微信智能机器人连接模式",
+ "hint": "Webhook 回调模式需要配置 Token/EncodingAESKey;长连接模式需要配置 BotID/Secret。"
+ },
"wecomaibot_friend_message_welcome_text": {
"description": "企业微信智能机器人私聊欢迎语",
- "hint": "当用户当天进入智能机器人单聊会话,回复欢迎语,如 “💭 思考中...”。留空则不回复。"
+ "hint": "可选。当用户当天进入智能机器人单聊会话,回复欢迎语,如 “💭 思考中...”。留空则不回复。"
},
"wecomaibot_init_respond_text": {
"description": "企业微信智能机器人初始响应文本",
- "hint": "当机器人收到消息时,首先回复的文本内容。留空则不设置。"
+ "hint": "可选。当机器人收到消息时,首先回复的文本内容。留空则不设置。"
+ },
+ "wecomaibot_token": {
+ "description": "企业微信智能机器人 Token",
+ "hint": "用于 Webhook 回调模式的身份验证。"
+ },
+ "wecomaibot_encoding_aes_key": {
+ "description": "企业微信智能机器人 EncodingAESKey",
+ "hint": "用于 Webhook 回调模式的消息加密解密。"
+ },
+ "wecomaibot_ws_bot_id": {
+ "description": "长连接 BotID",
+ "hint": "企业微信智能机器人长连接模式凭证 BotID。"
+ },
+ "wecomaibot_ws_secret": {
+ "description": "长连接 Secret",
+ "hint": "企业微信智能机器人长连接模式凭证 Secret。"
+ },
+ "wecomaibot_ws_url": {
+ "description": "长连接 WebSocket 地址",
+ "hint": "默认值为 wss://openws.work.weixin.qq.com,一般无需修改。"
+ },
+ "wecomaibot_heartbeat_interval": {
+ "description": "长连接心跳间隔",
+ "hint": "长连接模式心跳间隔(秒),建议 30 秒。"
},
"wpp_active_message_poll": {
"description": "是否启用主动消息轮询",
@@ -561,11 +610,56 @@
},
"msg_push_webhook_url": {
"description": "企业微信消息推送 Webhook URL",
- "hint": "用于主动消息推送,请在企微群->消息推送得到 URL。强烈建议设置此项以带来更好的消息发送体验。"
+ "hint": "可选。用于主动消息推送,请在企微群->消息推送得到 URL。建议设置此项以带来更好的消息发送体验。"
},
"only_use_webhook_url_to_send": {
"description": "仅使用 Webhook 发送消息",
- "hint": "启用后,企业微信智能机器人的所有回复都改为通过消息推送 Webhook 发送。消息推送 Webhook 支持更多的消息类型(如图片、文件等)。如果不需要打字机效果,强烈建议使用此选项。"
+ "hint": "可选。启用后,企业微信智能机器人的所有回复都改为通过消息推送 Webhook 发送。消息推送 Webhook 支持更多的消息类型(如图片、文件等)。如果不需要打字机效果,强烈建议使用此选项。"
+ },
+ "kook_bot_token": {
+ "description": "机器人 Token",
+ "type": "string",
+ "hint": "必填项。从 KOOK 开发者平台获取的机器人 Token"
+ },
+ "kook_bot_nickname": {
+ "description": "Bot Nickname",
+ "type": "string",
+ "hint": "可选项。若发送者昵称与此值一致,将忽略该消息。"
+ },
+ "kook_reconnect_delay": {
+ "description": "重连延迟",
+ "type": "int",
+ "hint": "重连延迟时间(秒),使用指数退避策略"
+ },
+ "kook_max_reconnect_delay": {
+ "description": "最大重连延迟",
+ "type": "int",
+ "hint": "重连延迟的最大值(秒)"
+ },
+ "kook_max_retry_delay": {
+ "description": "最大重试延迟",
+ "type": "int",
+ "hint": "重试的最大延迟时间(秒)"
+ },
+ "kook_heartbeat_interval": {
+ "description": "心跳间隔",
+ "type": "int",
+ "hint": "心跳检测间隔时间(秒)"
+ },
+ "kook_heartbeat_timeout": {
+ "description": "心跳超时时间",
+ "type": "int",
+ "hint": "心跳检测超时时间(秒)"
+ },
+ "kook_max_heartbeat_failures": {
+ "description": "最大心跳失败次数",
+ "type": "int",
+ "hint": "允许的最大心跳失败次数,超过后断开连接"
+ },
+ "kook_max_consecutive_failures": {
+ "description": "最大连续失败次数",
+ "type": "int",
+ "hint": "允许的最大连续失败次数,超过后停止重试"
}
},
"general": {
@@ -720,6 +814,17 @@
"hint": "Telegram 仅支持固定反应集合,参考:[https://gist.github.com/Soulter/3f22c8e5f9c7e152e967e8bc28c97fc9](https://gist.github.com/Soulter/3f22c8e5f9c7e152e967e8bc28c97fc9)"
}
}
+ },
+ "discord": {
+ "pre_ack_emoji": {
+ "enable": {
+ "description": "[Discord] 启用预回应表情"
+ },
+ "emojis": {
+ "description": "表情列表(Unicode 或自定义表情名)",
+ "hint": "填写 Unicode 表情符号,例如:👍、🤔、⏳"
+ }
+ }
}
}
}
@@ -771,7 +876,8 @@
]
},
"regex": {
- "description": "分段正则表达式"
+ "description": "分段正则表达式",
+ "hint": "用于按正则规则识别分段点。建议使用能匹配分隔符的表达式。"
},
"split_words": {
"description": "分段词列表",
@@ -1366,6 +1472,45 @@
"description": "API Base URL",
"hint": "Coze API 的基础 URL 地址,默认为 https://api.coze.cn"
},
+ "deerflow_api_base": {
+ "description": "API Base URL",
+ "hint": "DeerFlow API 网关地址,默认为 http://127.0.0.1:2026"
+ },
+ "deerflow_api_key": {
+ "description": "DeerFlow API Key",
+ "hint": "可选。若 DeerFlow 网关配置了 Bearer 鉴权,则在此填写。"
+ },
+ "deerflow_auth_header": {
+ "description": "Authorization Header",
+ "hint": "可选。自定义 Authorization 请求头,优先级高于 DeerFlow API Key。"
+ },
+ "deerflow_assistant_id": {
+ "description": "Assistant ID",
+ "hint": "LangGraph assistant_id,默认为 lead_agent。"
+ },
+ "deerflow_model_name": {
+ "description": "模型名称覆盖",
+ "hint": "可选。覆盖 DeerFlow 默认模型(对应 runtime context 的 model_name)。"
+ },
+ "deerflow_thinking_enabled": {
+ "description": "启用思考模式"
+ },
+ "deerflow_plan_mode": {
+ "description": "启用计划模式",
+ "hint": "对应 DeerFlow 的 is_plan_mode。"
+ },
+ "deerflow_subagent_enabled": {
+ "description": "启用子智能体",
+ "hint": "对应 DeerFlow 的 subagent_enabled。"
+ },
+ "deerflow_max_concurrent_subagents": {
+ "description": "子智能体最大并发数",
+ "hint": "对应 DeerFlow 的 max_concurrent_subagents。仅在启用子智能体时生效,默认 3。"
+ },
+ "deerflow_recursion_limit": {
+ "description": "递归深度上限",
+ "hint": "对应 LangGraph recursion_limit。"
+ },
"auto_save_history": {
"description": "由 Coze 管理对话记录",
"hint": "启用后,将由 Coze 进行对话历史记录管理, 此时 AstrBot 本地保存的上下文不会生效(仅供浏览), 对 AstrBot 的上下文进行的操作也不会生效。如果为禁用, 则使用 AstrBot 管理上下文。"
@@ -1380,4 +1525,4 @@
"helpMiddle": "或",
"helpSuffix": "。"
}
-}
+}
\ No newline at end of file
diff --git a/dashboard/src/i18n/locales/zh-CN/features/extension.json b/dashboard/src/i18n/locales/zh-CN/features/extension.json
index 2208d42ff..f42173ffa 100644
--- a/dashboard/src/i18n/locales/zh-CN/features/extension.json
+++ b/dashboard/src/i18n/locales/zh-CN/features/extension.json
@@ -11,10 +11,21 @@
"titles": {
"installedAstrBotPlugins": "已安装的 AstrBot 插件"
},
+ "failedPlugins": {
+ "title": "加载失败插件({count})",
+ "hint": "这些插件加载失败,仍可尝试重载或直接卸载。",
+ "columns": {
+ "plugin": "插件",
+ "error": "错误"
+ }
+ },
"search": {
"placeholder": "搜索插件...",
"marketPlaceholder": "搜索市场插件..."
},
+ "filters": {
+ "all": "全部"
+ },
"views": {
"card": "卡片视图",
"list": "列表视图"
@@ -109,13 +120,19 @@
"sourceExists": "该插件源已存在",
"installPlugin": "安装插件",
"randomPlugins": "🎲 随机插件",
+ "showRandomPlugins": "显示随机插件",
+ "hideRandomPlugins": "隐藏随机插件",
"sourceSafetyWarning": "即使是默认插件源,我们也不能完全保证插件的稳定性和安全性,使用前请谨慎核查。"
},
"sort": {
+ "by": "排序方式",
"default": "默认排序",
+ "installTime": "最后修改时间",
+ "name": "名称",
"stars": "Star数",
"author": "作者名",
"updated": "更新时间",
+ "updateStatus": "更新状态",
"ascending": "升序",
"descending": "降序"
},
@@ -177,7 +194,9 @@
"refreshing": "正在刷新插件列表...",
"refreshSuccess": "插件列表已刷新!",
"refreshFailed": "刷新插件列表时发生错误",
+ "operationFailed": "操作失败",
"reloadSuccess": "重载成功",
+ "reloadFailed": "重载失败",
"updateSuccess": "更新成功!",
"addSuccess": "添加成功!",
"saveSuccess": "保存成功!",
@@ -204,19 +223,58 @@
"enterUrl": "输入插件仓库链接"
},
"skills": {
+ "modeLocal": "本地 Skills",
+ "modeNeo": "Neo Skills",
+ "actions": "操作",
"upload": "上传 Skills",
"refresh": "刷新",
"empty": "暂无 Skills",
"emptyHint": "请上传 Skills 压缩包",
"uploadDialogTitle": "上传 Skills",
- "uploadHint": "请上传 zip 压缩包,解压后为 skill_name/ 目录,且包含 SKILL.md",
+ "uploadHint": "支持批量上传 zip 技能包,也支持拖拽批量上传 zip 技能包。系统会自动校验目录结构,并给出逐个文件的结果。",
+ "structureRequirement": "常见失败原因是压缩包结构不正确。每个 zip 必须只包含一个顶层目录,例如 `skillname/`,且该目录下必须存在 `SKILL.md`。",
+ "abilityMultiple": "支持一次上传多个zip文件",
+ "abilityValidate": "自动校验 `SKILL.md`",
+ "abilitySkip": "自动跳过重复文件",
"selectFile": "选择文件",
- "confirmUpload": "上传",
+ "selectFiles": "选择文件(可多选)",
+ "dropzoneTitle": "拖拽多个 zip 文件到这里",
+ "dropzoneAction": "或者点击之后在文件夹中选择多个文件",
+ "dropzoneHint": "支持批量上传,系统会自动校验目录结构",
+ "fileListTitle": "待处理文件",
+ "fileListEmpty": "选择文件后会在这里显示校验结果与上传状态",
+ "uploading": "正在上传...",
+ "batchResultTitle": "批量上传结果",
+ "batchResultSummary": "共 {total} 个文件,成功 {success} 个",
+ "batchSuccessList": "上传成功",
+ "batchFailedList": "上传失败",
+ "confirm": "确定",
+ "confirmUpload": "开始上传",
"cancel": "取消",
+ "statusWaiting": "待上传",
+ "statusUploading": "上传中",
+ "statusSuccess": "已上传",
+ "statusError": "校验失败",
+ "statusSkipped": "已跳过",
+ "summaryTotal": "共 {count} 个文件",
+ "summaryReady": "待处理 {count}",
+ "summarySuccess": "成功 {count}",
+ "summaryFailed": "失败 {count}",
+ "summarySkipped": "跳过 {count}",
+ "validationReady": "等待上传,上传时会自动校验目录结构",
+ "validationZipOnly": "仅支持 zip 技能包",
+ "validationDuplicate": "同名文件已在列表中,已跳过",
+ "validationUploading": "正在校验并上传...",
+ "validationUploadFailed": "上传失败,请重试",
+ "validationUploadedAs": "已安装为 {name}",
+ "validationNoResult": "未收到校验结果,请检查平台日志",
"noDescription": "无描述",
"path": "路径",
"uploadSuccess": "上传成功",
"uploadFailed": "上传失败",
+ "download": "下载",
+ "downloadSuccess": "下载成功",
+ "downloadFailed": "下载失败",
"loadFailed": "加载 Skills 失败",
"updateSuccess": "更新成功",
"updateFailed": "更新失败",
@@ -224,8 +282,42 @@
"deleteMessage": "确定要删除该 Skill 吗?",
"deleteSuccess": "删除成功",
"deleteFailed": "删除失败",
+ "neoSkillKey": "skill_key 过滤",
+ "neoStatus": "候选状态",
+ "neoStage": "发布阶段",
+ "neoFilterHint": "筛选候选与发布记录",
+ "neoAll": "全部",
+ "neoCandidates": "Neo Candidates",
+ "neoReleases": "Neo Releases",
+ "neoLoadFailed": "加载 Neo Skills 数据失败",
+ "neoPass": "通过",
+ "neoReject": "拒绝",
+ "neoEvaluateSuccess": "评测更新成功",
+ "neoEvaluateFailed": "评测更新失败",
+ "neoPromoteSuccess": "发布成功",
+ "neoPromoteFailed": "发布失败",
+ "neoRollback": "回滚",
+ "neoRollbackSuccess": "回滚成功",
+ "neoRollbackFailed": "回滚失败",
+ "neoDeactivate": "失活",
+ "neoDeactivateSuccess": "失活成功",
+ "neoDeactivateFailed": "失活失败",
+ "neoSync": "同步",
+ "neoSyncSuccess": "同步成功",
+ "neoSyncFailed": "同步失败",
+ "neoDelete": "删除",
+ "neoDeleteSuccess": "删除成功",
+ "neoDeleteFailed": "删除失败",
+ "neoPayloadTitle": "Neo Payload 详情",
+ "neoPayloadFailed": "读取 Payload 失败",
"runtimeNoneWarning": "Computer Use 运行环境为无,Skills 可能无法正确被 Agent 运行,因为没有启用运行环境。",
- "runtimeHint": "需要在配置的 “使用电脑能力” 中将运行环境设置为 “local” 或 “sandbox” 才能让 AstrBot 正常使用你提供的 Skills。"
+ "runtimeHint": "需要在配置的 “使用电脑能力” 中将运行环境设置为 “local” 或 “sandbox” 才能让 AstrBot 正常使用你提供的 Skills。",
+ "neoRuntimeRequired": "Neo Skills 仅在运行环境为 sandbox 且沙箱驱动为 shipyard_neo 时可用。",
+ "sourceLocalOnly": "本地 Skill",
+ "sourceSandboxOnly": "Sandbox 预置 Skill",
+ "sourceBoth": "本地 + Sandbox",
+ "sandboxDiscoveryPending": "尚未发现 Sandbox 预置 Skill。请至少启动一次 Sandbox 会话后再查看。",
+ "sandboxPresetReadonly": "Sandbox 预置 Skill 在此处为只读,无法在本地 Skills 页面删除或启用/禁用。"
},
"card": {
"actions": {
diff --git a/dashboard/src/i18n/locales/zh-CN/features/persona.json b/dashboard/src/i18n/locales/zh-CN/features/persona.json
index b2484844e..d3eec49a5 100644
--- a/dashboard/src/i18n/locales/zh-CN/features/persona.json
+++ b/dashboard/src/i18n/locales/zh-CN/features/persona.json
@@ -20,6 +20,8 @@
"form": {
"personaId": "人格 ID",
"systemPrompt": "系统提示词",
+ "customErrorMessage": "自定义报错回复信息(可选)",
+ "customErrorMessageHelp": "当该人格的 LLM 请求失败(例如连接失败)时,优先发送这条报错回复;留空则发送默认报错信息。",
"presetDialogs": "预设对话",
"presetDialogsHelp": "添加一些预设的对话来帮助机器人更好地理解角色设定。",
"userMessage": "用户消息",
diff --git a/dashboard/src/i18n/translations.ts b/dashboard/src/i18n/translations.ts
index d72cc9114..fa15e619f 100644
--- a/dashboard/src/i18n/translations.ts
+++ b/dashboard/src/i18n/translations.ts
@@ -42,7 +42,7 @@ import zhCNErrors from './locales/zh-CN/messages/errors.json';
import zhCNSuccess from './locales/zh-CN/messages/success.json';
import zhCNValidation from './locales/zh-CN/messages/validation.json';
-// 英文翻译
+// English translation
import enUSCommon from './locales/en-US/core/common.json';
import enUSActions from './locales/en-US/core/actions.json';
import enUSStatus from './locales/en-US/core/status.json';
@@ -83,6 +83,47 @@ import enUSErrors from './locales/en-US/messages/errors.json';
import enUSSuccess from './locales/en-US/messages/success.json';
import enUSValidation from './locales/en-US/messages/validation.json';
+// Russian translation
+import ruRUCommon from './locales/ru-RU/core/common.json';
+import ruRUActions from './locales/ru-RU/core/actions.json';
+import ruRUStatus from './locales/ru-RU/core/status.json';
+import ruRUNavigation from './locales/ru-RU/core/navigation.json';
+import ruRUHeader from './locales/ru-RU/core/header.json';
+import ruRUShared from './locales/ru-RU/core/shared.json';
+
+import ruRUChat from './locales/ru-RU/features/chat.json';
+import ruRUExtension from './locales/ru-RU/features/extension.json';
+import ruRUConversation from './locales/ru-RU/features/conversation.json';
+import ruRUSessionManagement from './locales/ru-RU/features/session-management.json';
+import ruRUToolUse from './locales/ru-RU/features/tool-use.json';
+import ruRUProvider from './locales/ru-RU/features/provider.json';
+import ruRUPlatform from './locales/ru-RU/features/platform.json';
+import ruRUConfig from './locales/ru-RU/features/config.json';
+import ruRUConfigMetadata from './locales/ru-RU/features/config-metadata.json';
+import ruRUConsole from './locales/ru-RU/features/console.json';
+import ruRUTrace from './locales/ru-RU/features/trace.json';
+import ruRUAbout from './locales/ru-RU/features/about.json';
+import ruRUSettings from './locales/ru-RU/features/settings.json';
+import ruRUAuth from './locales/ru-RU/features/auth.json';
+import ruRUChart from './locales/ru-RU/features/chart.json';
+import ruRUDashboard from './locales/ru-RU/features/dashboard.json';
+import ruRUCron from './locales/ru-RU/features/cron.json';
+import ruRUAlkaidIndex from './locales/ru-RU/features/alkaid/index.json';
+import ruRUAlkaidKnowledgeBase from './locales/ru-RU/features/alkaid/knowledge-base.json';
+import ruRUAlkaidMemory from './locales/ru-RU/features/alkaid/memory.json';
+import ruRUKnowledgeBaseIndex from './locales/ru-RU/features/knowledge-base/index.json';
+import ruRUKnowledgeBaseDetail from './locales/ru-RU/features/knowledge-base/detail.json';
+import ruRUKnowledgeBaseDocument from './locales/ru-RU/features/knowledge-base/document.json';
+import ruRUPersona from './locales/ru-RU/features/persona.json';
+import ruRUMigration from './locales/ru-RU/features/migration.json';
+import ruRUCommand from './locales/ru-RU/features/command.json';
+import ruRUSubagent from './locales/ru-RU/features/subagent.json';
+import ruRUWelcome from './locales/ru-RU/features/welcome.json';
+
+import ruRUErrors from './locales/ru-RU/messages/errors.json';
+import ruRUSuccess from './locales/ru-RU/messages/success.json';
+import ruRUValidation from './locales/ru-RU/messages/validation.json';
+
// 组装翻译对象
export const translations = {
'zh-CN': {
@@ -182,6 +223,55 @@ export const translations = {
success: enUSSuccess,
validation: enUSValidation
}
+ },
+ 'ru-RU': {
+ core: {
+ common: ruRUCommon,
+ actions: ruRUActions,
+ status: ruRUStatus,
+ navigation: ruRUNavigation,
+ header: ruRUHeader,
+ shared: ruRUShared
+ },
+ features: {
+ chat: ruRUChat,
+ extension: ruRUExtension,
+ conversation: ruRUConversation,
+ 'session-management': ruRUSessionManagement,
+ tooluse: ruRUToolUse,
+ provider: ruRUProvider,
+ platform: ruRUPlatform,
+ config: ruRUConfig,
+ 'config-metadata': ruRUConfigMetadata,
+ console: ruRUConsole,
+ trace: ruRUTrace,
+ about: ruRUAbout,
+ settings: ruRUSettings,
+ auth: ruRUAuth,
+ chart: ruRUChart,
+ dashboard: ruRUDashboard,
+ cron: ruRUCron,
+ alkaid: {
+ index: ruRUAlkaidIndex,
+ 'knowledge-base': ruRUAlkaidKnowledgeBase,
+ memory: ruRUAlkaidMemory
+ },
+ 'knowledge-base': {
+ index: ruRUKnowledgeBaseIndex,
+ detail: ruRUKnowledgeBaseDetail,
+ document: ruRUKnowledgeBaseDocument
+ },
+ persona: ruRUPersona,
+ migration: ruRUMigration,
+ command: ruRUCommand,
+ subagent: ruRUSubagent,
+ welcome: ruRUWelcome
+ },
+ messages: {
+ errors: ruRUErrors,
+ success: ruRUSuccess,
+ validation: ruRUValidation
+ }
}
};
diff --git a/dashboard/src/layouts/full/vertical-header/VerticalHeader.vue b/dashboard/src/layouts/full/vertical-header/VerticalHeader.vue
index 9ec2d8945..37f4f4c83 100644
--- a/dashboard/src/layouts/full/vertical-header/VerticalHeader.vue
+++ b/dashboard/src/layouts/full/vertical-header/VerticalHeader.vue
@@ -28,6 +28,7 @@ const authStore = useAuthStore();
const theme = useTheme();
const { t } = useI18n();
const route = useRoute();
+const LAST_BOT_ROUTE_KEY = "astrbot:last_bot_route";
let dialog = ref(false);
let accountWarning = ref(false);
let updateStatusDialog = ref(false);
@@ -147,295 +148,9 @@ async function openDesktopUpdateDialog() {
desktopUpdateChecking.value = true;
desktopUpdateInstalling.value = false;
desktopUpdateHasNewVersion.value = false;
- desktopUpdateCurrentVersion.value = "-";
- desktopUpdateLatestVersion.value = "-";
- desktopUpdateStatus.value = t("core.header.updateDialog.desktopApp.checking");
-
- const bridge = getAppUpdaterBridge();
- if (!bridge) {
- desktopUpdateChecking.value = false;
- desktopUpdateStatus.value = t(
- "core.header.updateDialog.desktopApp.checkFailed",
- );
- return;
- }
-
- try {
- const result = await bridge.checkForAppUpdate();
- if (!result?.ok) {
- desktopUpdateCurrentVersion.value = result?.currentVersion || "-";
- desktopUpdateLatestVersion.value =
- result?.latestVersion || result?.currentVersion || "-";
- desktopUpdateStatus.value =
- result?.reason || t("core.header.updateDialog.desktopApp.checkFailed");
- return;
- }
-
- desktopUpdateCurrentVersion.value = result.currentVersion || "-";
- desktopUpdateLatestVersion.value =
- result.latestVersion || result.currentVersion || "-";
- desktopUpdateHasNewVersion.value = !!result.hasUpdate;
- desktopUpdateStatus.value = result.hasUpdate
- ? t("core.header.updateDialog.desktopApp.hasNewVersion")
- : t("core.header.updateDialog.desktopApp.isLatest");
- } catch (error) {
- console.error(error);
- desktopUpdateStatus.value = t(
- "core.header.updateDialog.desktopApp.checkFailed",
- );
- } finally {
- desktopUpdateChecking.value = false;
- }
+ // ...
}
-async function confirmDesktopUpdate() {
- if (!desktopUpdateHasNewVersion.value || desktopUpdateInstalling.value) {
- return;
- }
-
- const bridge = getAppUpdaterBridge();
- if (!bridge) {
- desktopUpdateStatus.value = t(
- "core.header.updateDialog.desktopApp.installFailed",
- );
- return;
- }
-
- desktopUpdateInstalling.value = true;
- desktopUpdateStatus.value = t(
- "core.header.updateDialog.desktopApp.installing",
- );
-
- try {
- const result = await bridge.installAppUpdate();
- if (result?.ok) {
- desktopUpdateDialog.value = false;
- return;
- }
- desktopUpdateStatus.value =
- result?.reason || t("core.header.updateDialog.desktopApp.installFailed");
- } catch (error) {
- console.error(error);
- desktopUpdateStatus.value = t(
- "core.header.updateDialog.desktopApp.installFailed",
- );
- } finally {
- desktopUpdateInstalling.value = false;
- }
-}
-
-function handleUpdateClick() {
- if (isDesktopReleaseMode.value) {
- void openDesktopUpdateDialog();
- return;
- }
- checkUpdate();
- getReleases();
- updateStatusDialog.value = true;
-}
-
-// 检测是否为预发布版本
-const isPreRelease = (version: string) => {
- const preReleaseKeywords = ["alpha", "beta", "rc", "pre", "preview", "dev"];
- const lowerVersion = version.toLowerCase();
- return preReleaseKeywords.some((keyword) => lowerVersion.includes(keyword));
-};
-
-// 退出登录
-function handleLogout() {
- if (confirm(t("core.common.dialog.confirmMessage"))) {
- authStore.logout();
- }
-}
-
-// 账户修改
-function accountEdit() {
- accountEditStatus.value.loading = true;
- accountEditStatus.value.error = false;
- accountEditStatus.value.success = false;
-
- const passwordHash = password.value ? md5(password.value) : "";
- const newPasswordHash = newPassword.value ? md5(newPassword.value) : "";
- const confirmPasswordHash = confirmPassword.value
- ? md5(confirmPassword.value)
- : "";
-
- axios
- .post("/api/auth/account/edit", {
- password: passwordHash,
- new_password: newPasswordHash,
- confirm_password: confirmPasswordHash,
- new_username: newUsername.value ? newUsername.value : username,
- })
- .then((res) => {
- if (res.data.status == "error") {
- accountEditStatus.value.error = true;
- accountEditStatus.value.message = res.data.message;
- password.value = "";
- newPassword.value = "";
- confirmPassword.value = "";
- return;
- }
- accountEditStatus.value.success = true;
- accountEditStatus.value.message = res.data.message;
- setTimeout(() => {
- dialog.value = !dialog.value;
- const authStore = useAuthStore();
- authStore.logout();
- }, 2000);
- })
- .catch((err) => {
- console.log(err);
- accountEditStatus.value.error = true;
- accountEditStatus.value.message =
- typeof err === "string"
- ? err
- : t("core.header.accountDialog.messages.updateFailed");
- password.value = "";
- newPassword.value = "";
- confirmPassword.value = "";
- })
- .finally(() => {
- accountEditStatus.value.loading = false;
- });
-}
-
-function getVersion() {
- axios
- .get("/api/stat/version")
- .then((res) => {
- botCurrVersion.value = "v" + res.data.data.version;
- dashboardCurrentVersion.value = res.data.data?.dashboard_version;
- let change_pwd_hint = res.data.data?.change_pwd_hint;
- if (change_pwd_hint) {
- dialog.value = true;
- accountWarning.value = true;
- localStorage.setItem("change_pwd_hint", "true");
- } else {
- localStorage.removeItem("change_pwd_hint");
- }
- })
- .catch((err) => {
- console.log(err);
- });
-}
-
-function checkUpdate() {
- updateStatus.value = t("core.header.updateDialog.status.checking");
- axios
- .get("/api/update/check")
- .then((res) => {
- hasNewVersion.value = res.data.data.has_new_version;
-
- if (res.data.data.has_new_version) {
- releaseMessage.value = res.data.message;
- updateStatus.value = t("core.header.version.hasNewVersion");
- } else {
- updateStatus.value = res.data.message;
- }
- dashboardHasNewVersion.value = isDesktopReleaseMode.value
- ? false
- : res.data.data.dashboard_has_new_version;
- })
- .catch((err) => {
- if (err.response && err.response.status == 401) {
- console.log("401");
- const authStore = useAuthStore();
- authStore.logout();
- return;
- }
- console.log(err);
- updateStatus.value = err;
- });
-}
-
-function getReleases() {
- return axios
- .get("/api/update/releases")
- .then((res) => {
- releases.value = res.data.data.map((item: any) => {
- item.published_at = new Date(item.published_at).toLocaleString();
- return item;
- });
- })
- .catch((err) => {
- console.log(err);
- });
-}
-
-function switchVersion(version: string) {
- updateStatus.value = t("core.header.updateDialog.status.switching");
- installLoading.value = true;
- axios
- .post("/api/update/do", {
- version: version,
- proxy: getSelectedGitHubProxy(),
- })
- .then((res) => {
- updateStatus.value = res.data.message;
- if (res.data.status == "ok") {
- setTimeout(() => {
- window.location.reload();
- }, 1000);
- }
- })
- .catch((err) => {
- console.log(err);
- updateStatus.value = err;
- })
- .finally(() => {
- installLoading.value = false;
- });
-}
-
-function updateDashboard() {
- updatingDashboardLoading.value = true;
- updateStatus.value = t("core.header.updateDialog.status.updating");
- axios
- .post("/api/update/dashboard")
- .then((res) => {
- updateStatus.value = res.data.message;
- if (res.data.status == "ok") {
- setTimeout(() => {
- window.location.reload();
- }, 1000);
- }
- })
- .catch((err) => {
- console.log(err);
- updateStatus.value = err;
- })
- .finally(() => {
- updatingDashboardLoading.value = false;
- });
-}
-
-function toggleDarkMode() {
- const newTheme =
- customizer.uiTheme === "PurpleThemeDark"
- ? "PurpleTheme"
- : "PurpleThemeDark";
- customizer.SET_UI_THEME(newTheme);
- theme.global.name.value = newTheme;
-}
-
-function openReleaseNotesDialog(body: string, tag: string) {
- selectedReleaseNotes.value = body;
- selectedReleaseTag.value = tag;
- releaseNotesDialog.value = true;
-}
-
-function handleLogoClick() {
- if (customizer.viewMode === "chat") {
- aboutDialog.value = true;
- } else {
- router.push("/about");
- }
-}
-
-getVersion();
-checkUpdate();
-
const commonStore = useCommonStore();
commonStore.createEventSource(); // log
commonStore.getStartTime();
@@ -448,846 +163,96 @@ const viewMode = computed({
},
});
-// 监听 viewMode 变化,切换到 bot 模式时跳转到首页
+// 保存 bot 模式的最後路由
+// 監聽 route 變化,保存最後一次 bot 路由
watch(
- () => customizer.viewMode,
- (newMode, oldMode) => {
- if (newMode === "bot" && oldMode === "chat") {
- // 从 chat 模式切换到 bot 模式时,跳转到首页
- if (route.path !== "/") {
- router.push("/");
+ () => route.fullPath,
+ (newPath) => {
+ if (customizer.viewMode === "bot" && typeof window !== "undefined") {
+ try {
+ localStorage.setItem(LAST_BOT_ROUTE_KEY, newPath);
+ } catch (e) {
+ console.error("Failed to save last bot route to localStorage:", e);
}
}
},
);
-// Merry Christmas! 🎄
-const isChristmas = computed(() => {
- const today = new Date();
- const month = today.getMonth() + 1; // getMonth() 返回 0-11
- const day = today.getDate();
- return month === 12 && day === 25;
-});
-
-// 语言切换相关
-const { languageOptions, currentLanguage, switchLanguage, locale } =
- useLanguageSwitcher();
-const languages = computed(() =>
- languageOptions.value.map((lang) => ({
- code: lang.value,
- name: lang.label,
- flag: lang.flag,
- })),
+// 監聽 viewMode 切換
+watch(
+ () => customizer.viewMode,
+ (newMode, oldMode) => {
+ if (
+ newMode === "bot" &&
+ oldMode === "chat" &&
+ typeof window !== "undefined"
+ ) {
+ // 從 chat 切換回 bot,跳轉到最後一次的 bot 路由
+ let lastBotRoute = "/";
+ try {
+ lastBotRoute = localStorage.getItem(LAST_BOT_ROUTE_KEY) || "/";
+ } catch (e) {
+ console.error("Failed to read last bot route from localStorage:", e);
+ }
+ router.push(lastBotRoute);
+ }
+ },
);
-const currentLocale = computed(() => locale.value);
-const changeLanguage = async (langCode: string) => {
- await switchLanguage(langCode as Locale);
-};
-
-onMounted(async () => {
- const runtimeInfo = await getDesktopRuntimeInfo();
- isDesktopReleaseMode.value = runtimeInfo.isDesktopRuntime;
- if (isDesktopReleaseMode.value) {
- dashboardHasNewVersion.value = false;
- }
-});
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ t("core.header.updateDialog.title") }}
-
- mdi-close
-
-
-
-
-
-
-
-
{{ botCurrVersion }}
- {{ updateStatus }}
-
-
-
-
-
-
-
- {{ t("core.header.updateDialog.tip") }}
- {{ t("core.header.updateDialog.tipContinue") }}
-
-
-
-
-
-
-
-
- mdi-alert-circle-outline
-
-
-
{{
- t("core.header.updateDialog.preReleaseWarning.title")
- }}
-
- {{
- t("core.header.updateDialog.preReleaseWarning.description")
- }}
-
- {{
- t("core.header.updateDialog.preReleaseWarning.issueLink")
- }}
-
-
-
-
-
-
-
- {{ item.tag_name }}
-
- {{ t("core.header.updateDialog.preRelease") }}
-
-
-
-
- {{ t("core.header.updateDialog.table.view") }}
-
-
-
- {{ t("core.header.updateDialog.table.switch") }}
-
-
-
-
-
-
-
-
- {{ t("core.header.updateDialog.dashboardUpdate.title") }}
-
-
- {{
- t("core.header.updateDialog.dashboardUpdate.currentVersion")
- }}
- {{ dashboardCurrentVersion }}
-
-
-
-
-
- {{
- t("core.header.updateDialog.dashboardUpdate.hasNewVersion")
- }}
-
-
- {{ t("core.header.updateDialog.dashboardUpdate.isLatest") }}
-
-
-
-
- {{
- t(
- "core.header.updateDialog.dashboardUpdate.downloadAndUpdate",
- )
- }}
-
-
-
-
-
-
-
- {{ t("core.common.close") }}
-
-
-
-
-
-
-
-
-
- {{ t("core.header.updateDialog.releaseNotes.title") }}:
- {{ selectedReleaseTag }}
-
-
-
-
-
-
-
- {{ t("core.common.close") }}
-
-
-
-
-
-
-
-
- {{ t("core.header.updateDialog.desktopApp.title") }}
-
-
-
- {{ t("core.header.updateDialog.desktopApp.message") }}
-
-
-
- {{ t("core.header.updateDialog.desktopApp.currentVersion") }}
- {{ desktopUpdateCurrentVersion }}
-
-
- {{ t("core.header.updateDialog.desktopApp.latestVersion") }}
- {{
- desktopUpdateLatestVersion
- }}
-
-
-
-
- {{ desktopUpdateStatus }}
-
-
-
-
-
- {{ t("core.common.dialog.cancelButton") }}
-
-
- {{ t("core.common.dialog.confirmButton") }}
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{
- t("core.header.accountDialog.securityWarning")
- }}
-
-
-
- {{ accountEditStatus.message }}
-
-
-
- {{ accountEditStatus.message }}
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ t("core.header.accountDialog.form.defaultCredentials") }}
-
-
-
-
-
-
-
-
- {{ t("core.header.accountDialog.actions.cancel") }}
-
-
- {{ t("core.header.accountDialog.actions.save") }}
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+