mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-30 23:25:24 +00:00
* fix(sso): send the PKCE verifier for GitHub login (#1534) * fix(remote-desktop): clip cursor overflow without disabling zoom (#1535) * test(remote-desktop): preserve sessions beyond one hour (#1536) * fix(hosts): expose controls for overflowing editor tabs (#1537) * fix(hosts): expose controls for overflowing editor tabs * test(hosts): mock resize observation in admin panel tests * fix(status): skip TCP probes while host sessions are active (#1538) * fix(database): batch session activity persistence (#1539) * docs(api): describe cookie and API key authentication (#1540) * fix(snippets): repair missing note column on SQLite upgrades (#1541) * fix(docker): retain stored SSH credential association (#1543) * fix(file-manager): render transfer toasts without plugin hooks (#1546) * feat(hosts): keep compact row actions inline (#1547) * fix(auth): allow retrying unavailable second-factor interfaces (#1549) * fix(auth): reject unresolved legacy identity provisioning (#1550) * fix(desktop): ship the plugin SDK inside Mac App Store builds (#1551) * fix(tmux): pass full session info to the terminal's session picker (#1552) The tmux.sessions service reduced detected sessions to bare names, but the picker reads session.name, so every entry rendered blank and selecting one sent an empty name, which created a new session instead of attaching. * fix(ssh): read force keyboard-interactive as a boolean when resolving hosts (#1553) The column holds the text "true"/"false", and the resolver passed it through as-is. The string "false" is truthy, so the password provider treated every saved host as forced keyboard-interactive and left the password out. Jump hops are built straight from the resolved host, so a password hop whose server doesn't offer keyboard-interactive failed with "All configured authentication methods failed". * fix(database): batch database saves for bulk host writes (#1554) * fix(database): yield to the event loop between database saves Each SQLite save serializes and encrypts the whole database into new buffers, which V8 only releases once the event loop turns. Boot migrations and bulk host import write plugin settings per host and per key in an awaited loop, so hundreds of full copies piled up and the container ran out of memory. * fix(database): save once per bulk host write instead of once per row On SQLite every repository write force-saves the whole database. Boot plugin data migrations, host defaults materialization and the bulk host routes write one row per host per setting, so they serialized and encrypted the full database hundreds of times in a row. DatabaseSaveTrigger.batched wraps a function so force saves made while it runs collapse into a single save when it finishes. Nested scopes fold into the outer one, and work that outlives its scope saves normally. * feat(hosts): add instance-wide predefined tag suggestions (#1548) * feat(hosts): add shared predefined tag suggestions * style(hosts): format tag catalog routes * test(database): advance fake timers past the save yield (#1555) * fix(i18n): complete Simplified Chinese core and plugin translations (#1542) * fix(i18n): complete Chinese onboarding and navigation labels * fix(i18n): translate remaining Chinese core and plugin interfaces * fix(i18n): translate host editor tab overflow controls * fix(i18n): use consistent Chinese fleet terminology * fix(i18n): localize hardcoded controls and plugin views * fix(i18n): translate built-in homepage widget catalog * test(homepage): follow translated timezone placeholder * fix(i18n): translate plugin-provided homepage widgets * fix(i18n): localize feature settings section titles * fix: 2.8 oidc accounts unable to sign in after upgrading (#1381) * fix: plugins losing the saved ssh login when copying a host (#1391) * fix: fleets, proxmox and automations not getting the host sudo password * fix: host imports running a defaults pass and metrics restart per host (#1384) * fix: high cpu from status probes and full database saves on every sample (#1300) * fix: user data export freezing the server (#1393) * fix: op:// secret references rejected as ssh keys on credentials (#1394) * fix: slow file deletes from the trash lookups on every delete (#1390) * fix: add openapi docs and error handling to host tag routes * test: compare download stream buffers directly so it stops timing out * chore: drop em dash from host row comment * chore: update release notes for 2.9.1 * fix: restore space to add host tags and redesign predefined tags editor * fix: host key silently accepted when the host is missing from the database (#1397) * fix: clearer host login failed status label and fix its translations (#1396) * chore: add host key and status label fixes to release notes * fix: sso and ldap provider dialogs overflowing the screen and using mismatched toggles * chore: increment ver * fix(audit): store plugin entries with no acting user as a null user_id (#1556) Plugin audit entries written outside a request used the literal "system" as user_id. That column references users.id, so the insert was refused (Postgres logs it as an FK violation) and the entry was silently dropped. Write null instead and keep "system" / plugin:<id> in username. * chore: add sso/ldap dialog and audit log fixes to release notes * fix: tunnels and host settings missing from shared hosts on desktop * fix: remote desktop logins missing from shared hosts on desktop * fix: simplify host status to online/offline and keep it live without a refresh * chore: sync Crowdin translations for 2.9.1 --------- Co-authored-by: ZacharyZcR <zacharyzcr1984@gmail.com>
239 lines
14 KiB
JSON
239 lines
14 KiB
JSON
{
|
||
"nav": {
|
||
"snippets": "Откъси"
|
||
},
|
||
"onboarding": {
|
||
"feature_snippets": "Откъси",
|
||
"feature_snippets_desc": "Запазвайте команди, които изпълнявате често, и ги изпращайте към терминал с едно щракване."
|
||
},
|
||
"permissions": {
|
||
"view": {
|
||
"title": "Преглед на фрагменти",
|
||
"description": "Вижте вашите собствени фрагменти, бележки и споделени фрагменти."
|
||
},
|
||
"create": {
|
||
"title": "Създаване на фрагменти",
|
||
"description": "Създавайте нови фрагменти, бележки и папки."
|
||
},
|
||
"edit": {
|
||
"title": "Редактиране на фрагменти",
|
||
"description": "Преименувайте или променете съществуващи фрагменти и папки."
|
||
},
|
||
"delete": {
|
||
"title": "Изтриване на фрагменти",
|
||
"description": "Изтрийте фрагменти и папки."
|
||
},
|
||
"share": {
|
||
"title": "Споделяне на фрагменти",
|
||
"description": "Споделяйте фрагменти и папки с други потребители или роли."
|
||
}
|
||
},
|
||
"settings": {
|
||
"foldersCollapsed": {
|
||
"label": "Свиване на папките по подразбиране",
|
||
"description": "Започнете всяка папка с фрагменти свита, когато отворите панела „Фрагменти“."
|
||
},
|
||
"showCommands": {
|
||
"label": "Показване на команди",
|
||
"description": "Покажете първия ред от командата на всеки фрагмент под неговото име."
|
||
},
|
||
"confirmExecution": {
|
||
"label": "Потвърдете преди стартиране",
|
||
"description": "Попитай преди изпълнението на фрагмент от команда в терминал."
|
||
}
|
||
},
|
||
"cancel": "Отказ",
|
||
"loading": "Зареждане...",
|
||
"searchPlaceholder": "Търсене на фрагменти",
|
||
"newFolder": "Нова папка",
|
||
"newSnippet": "Нов фрагмент",
|
||
"noFolder": "Няма папка",
|
||
"noSnippetsInFolder": "Няма фрагменти в тази папка",
|
||
"noTerminalTabsOpen": "Няма отворен раздел на терминала",
|
||
"run": "Бягане",
|
||
"pasteToTerminal": "Поставяне в терминала",
|
||
"copySuccess": "Копирано в буферната памет",
|
||
"importExport": "Внос / Износ",
|
||
"importFailed": "Импортирането на фрагменти не бе успешно",
|
||
"nameLabel": "Име",
|
||
"namePlaceholder": "Име на фрагмента",
|
||
"descriptionLabel": "Описание",
|
||
"descriptionPlaceholder": "Незадължително описание",
|
||
"folderLabel": "Папка",
|
||
"typeLabel": "Тип",
|
||
"typeCommand": "Команда",
|
||
"typeNote": "Забележка",
|
||
"commandLabel": "Команда",
|
||
"commandPlaceholder": "Команда за изпълнение, например systemctl status $HOST",
|
||
"noteLabel": "Забележка",
|
||
"notePlaceholder": "Текст за поставяне в терминала",
|
||
"createSnippetTitle": "Създаване на фрагмент",
|
||
"createSnippetButton": "Създаване на фрагмент",
|
||
"createSuccess": "Фрагментът е създаден",
|
||
"createFailed": "Създаването на фрагмент не бе успешно",
|
||
"editSnippetTitle": "Редактиране на фрагмент",
|
||
"saveSnippetButton": "Запазване на фрагмент",
|
||
"updateSuccess": "Фрагментът е актуализиран",
|
||
"updateFailed": "Актуализирането на фрагмента не бе успешно",
|
||
"deleteFailed": "Изтриването на фрагмента не бе успешно",
|
||
"createFolderTitle": "Създаване на папка",
|
||
"createFolderButton": "Създаване на папка",
|
||
"folderCreateSuccess": "Папката е създадена",
|
||
"folderCreateFailed": "Създаването на папка не бе успешно",
|
||
"editFolderTitle": "Редактиране на папка",
|
||
"saveFolderButton": "Запазване на папката",
|
||
"folderEditSuccess": "Папката е актуализирана",
|
||
"folderEditFailed": "Актуализирането на папката не бе успешно",
|
||
"folderNameLabel": "Име на папката",
|
||
"folderNamePlaceholder": "Име на папката",
|
||
"folderIconLabel": "Икона",
|
||
"folderDeleteSuccess": "Папката е изтрита",
|
||
"folderDeleteFailed": "Изтриването на папката не бе успешно",
|
||
"confirmRunMessage": "Изпълни „{{name}}“?",
|
||
"confirmRunButton": "Бягане",
|
||
"runSuccess": "Изпълни „{{name}}“ на {{count}} терминал(и)",
|
||
"pasteSuccess": "Поставено е „{{name}}“ в {{count}} терминал(и)",
|
||
"admin": {
|
||
"tabTitle": "Откъси",
|
||
"count": "{{count}} фрагменти",
|
||
"add": "Добавяне на фрагмент",
|
||
"namePlaceholder": "Име на фрагмента",
|
||
"contentPlaceholder": "Съдържание на командата",
|
||
"folderPlaceholder": "Папка (по избор)",
|
||
"empty": "Този потребител няма фрагменти",
|
||
"deleteConfirm": "Да се изтрие ли фрагментът „{{name}}“, принадлежащ на {{username}}?",
|
||
"deleted": "Фрагментът е изтрит",
|
||
"deleteFailed": "Изтриването на фрагмента не бе успешно",
|
||
"requiredFields": "Името и съдържанието на фрагмента са задължителни",
|
||
"saved": "Фрагментът е запазен",
|
||
"saveFailed": "Запазването на фрагмента не бе успешно",
|
||
"saving": "Запазване...",
|
||
"save": "Запазване"
|
||
},
|
||
"backToSnippets": "Обратно към откъси",
|
||
"settingsTitle": "Настройки на фрагмента",
|
||
"settingsDisplayTitle": "Дисплей",
|
||
"settingsBehaviorTitle": "Поведение",
|
||
"typeCommandHint": "Изпълнява се в активния терминал.",
|
||
"typeNoteHint": "Поставя в активния терминал без да се изпълнява.",
|
||
"variablesHint": "Променливи: $HOST, $USER, $PORT, $NAME, ${INPUT_1:Етикет}",
|
||
"doubleClickToRun": "Щракнете двукратно, за да стартирате",
|
||
"sharedBadge": "Споделено",
|
||
"copyToClipboard": "Копиране в клипборда",
|
||
"copyFailed": "Копирането в буферната памет не бе успешно",
|
||
"moreOptions": "Още опции",
|
||
"moreActions": "Още действия",
|
||
"moveToFolder": "Преместване в папка",
|
||
"deleteSnippet": "Изтриване на фрагмент",
|
||
"deleteSnippetConfirm": "Да се изтрие ли фрагментът „{{name}}“?",
|
||
"deleteSuccess": "Фрагментът е изтрит",
|
||
"delete": "Изтриване",
|
||
"folderActions": "Действия с папки",
|
||
"addSnippetHere": "Нов фрагмент тук",
|
||
"deleteFolder": "Изтриване на папка",
|
||
"deleteFolderConfirm": "Да се изтрие ли папка „{{name}}“? Нейните фрагменти ще бъдат преместени извън папката.",
|
||
"createFolderDescription": "Групирайте свързани фрагменти заедно.",
|
||
"editFolderDescription": "Променете името, цвета или иконата на тази папка.",
|
||
"folderColorLabel": "Цвят",
|
||
"loadFailed": "Зареждането на фрагменти не бе успешно",
|
||
"importSkipExisting": "Импортиране (пропускане на съществуващото)",
|
||
"importOverwrite": "Импортиране (презаписване на съществуващо)",
|
||
"importInvalidFile": "Този файл не е валиден експорт на фрагменти",
|
||
"importSuccess": "Импортирано {{imported}}, актуализирано {{updated}}, пропуснато {{skipped}}",
|
||
"exportSnippets": "Експортиране на фрагменти",
|
||
"exportSuccess": "Експортирани фрагменти",
|
||
"exportFailed": "Експортирането на фрагменти не бе успешно",
|
||
"expandAll": "Разгъване на всички папки",
|
||
"collapseAll": "Свиване на всички папки",
|
||
"docsLink": "Документация",
|
||
"clearSearch": "Изчистване на търсенето",
|
||
"noSearchResults": "Няма фрагменти, съответстващи на търсенето ви",
|
||
"emptyTitle": "Все още няма фрагменти",
|
||
"emptyDescription": "Запазете командите, които изпълнявате често, след което ги стартирайте в терминал с едно щракване.",
|
||
"shareSnippet": "Споделяне на фрагмент",
|
||
"shareFolder": "Споделяне на папка",
|
||
"shareExpiry": "Изтича",
|
||
"shareExpiryOptions": {
|
||
"h0": "Никога",
|
||
"h1": "След 1 час",
|
||
"h24": "След 1 ден",
|
||
"h168": "След 7 дни",
|
||
"h720": "След 30 дни"
|
||
},
|
||
"shareButton": "Споделяне",
|
||
"shareSuccess": "Споделено с {{count}}",
|
||
"shareFailed": "Споделянето не бе успешно",
|
||
"shareLoadFailed": "Зареждането на подробностите за споделянето не бе успешно",
|
||
"currentAccess": "Текущ достъп",
|
||
"notSharedYet": "Все още не е споделено с никого",
|
||
"revokeAccess": "Отмяна",
|
||
"revokeSuccess": "Достъпът е отменен",
|
||
"revokeFailed": "Неуспешно отменяне на достъпа",
|
||
"close": "Затвори",
|
||
"targetHostsLabel": "Целеви хостове",
|
||
"targetHostsHint": "Изберете хостове, на които да се изпълни тази команда директно, без да е отворен терминал. Оставете празно, за да се изпълни в активния терминал.",
|
||
"clearTargetHosts": "Изчисти",
|
||
"noHostsAvailable": "Няма налични хостове",
|
||
"searchHosts": "Търсене на хостове",
|
||
"runOnTargets": "Изпълнява се на целеви хостове",
|
||
"executionResultTitle": "Резултати за „{{name}}“",
|
||
"executionResultDescription": "Изход от всеки целеви хост.",
|
||
"executionSuccess": "Успех",
|
||
"executionFailed": "Неуспешно",
|
||
"directRunSuccess": "Изпълни „{{name}}“ на {{count}} хост(ове)",
|
||
"directRunPartialFail": "„{{name}}“ не успя на някои хостове",
|
||
"reorderFailed": "Пренареждането на фрагменти не бе успешно",
|
||
"dropToRemoveFromFolder": "Пуснете тук, за да излезете от папката",
|
||
"shareSnippetTitle": "Сподели „{{name}}“",
|
||
"shareFolderTitle": "Споделяне на папка „{{name}}“",
|
||
"shareWith": "Сподели с",
|
||
"usersTab": "Потребители",
|
||
"rolesTab": "Роли",
|
||
"shareSearchPlaceholder": "Търсене на потребители или роли",
|
||
"shareNoMatches": "Няма съвпадения",
|
||
"shareWithCount": "Сподели с {{count}}",
|
||
"shareFolderHint": "Споделя всеки фрагмент в тази папка. Фрагментите, добавени по-късно, не се споделят автоматично.",
|
||
"shareFolderSummary": "Споделени {{count}} фрагмент(а) в тази папка",
|
||
"grantedBy": "Предоставено от",
|
||
"expired": "Изтекъл",
|
||
"variablesDialogTitle": "Изпълни „{{name}}“",
|
||
"variablesDialogDescription": "Попълнете стойностите, необходими на този фрагмент, преди да го изпълните.",
|
||
"variablesPreviewLabel": "Преглед",
|
||
"variablesConfirmButton": "Бягане",
|
||
"keybindings": {
|
||
"runSnippet": "Изпълнете съществуващия фрагмент",
|
||
"snippetLabel": "Фрагмент",
|
||
"selectSnippet": "Изберете фрагмент",
|
||
"snippetMissing": "фрагмент не е намерен",
|
||
"snippetRequired": "Изберете фрагмент"
|
||
},
|
||
"paletteHintRun": "Изпълняване в активния раздел на терминала",
|
||
"host": {
|
||
"startupTitle": "Стартов фрагмент",
|
||
"quickActionsTitle": "Бързи действия",
|
||
"quickActionsDescription": "Бързите действия се показват като бутони в лентата с инструменти Host Metrics за изпълнение на команди с едно щракване.",
|
||
"noQuickActions": "Все още няма бързи действия.",
|
||
"buttonLabel": "Етикет на бутона",
|
||
"selectSnippet": "Изберете фрагмент...",
|
||
"addQuickAction": "Добавяне на действие",
|
||
"tabTitle": "Откъси",
|
||
"startupDescription": "Изпълнява се в терминала всеки път, когато се свързва с този хост. Променливи като $HOST се попълват; фрагмент, който изисква входни данни, се пропуска.",
|
||
"none": "Няма",
|
||
"removeQuickAction": "Премахване на бързо действие"
|
||
},
|
||
"quickActions": {
|
||
"running": "Изпълнява се {{name}}...",
|
||
"succeeded": "{{name}} завършено успешно",
|
||
"failed": "{{name}} неуспешно",
|
||
"error": "Неуспешно изпълнение на {{name}}"
|
||
},
|
||
"paletteHintPaste": "Поставяне в активния раздел на терминала",
|
||
"targetTerminals": "Влизане",
|
||
"targetTerminalsHint": "по избор, в противен случай активният раздел",
|
||
"selectAll": "Всички",
|
||
"selectNone": "Няма",
|
||
"plugin": {
|
||
"name": "Snippets"
|
||
}
|
||
}
|