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
9.5 KiB
JSON
239 lines
9.5 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": "在 {{count}} 终端上运行“{{name}}”",
|
||
"pasteSuccess": "已将“{{name}}”粘贴到 {{count}} 终端中",
|
||
"admin": {
|
||
"tabTitle": "代码片段",
|
||
"count": "{{count}} 个代码片段",
|
||
"add": "添加代码片段",
|
||
"namePlaceholder": "代码片段名称",
|
||
"contentPlaceholder": "命令内容",
|
||
"folderPlaceholder": "文件夹(可选)",
|
||
"empty": "该用户没有代码片段",
|
||
"deleteConfirm": "删除属于 {{username}} 的代码片段 \"{{name}}\"?",
|
||
"deleted": "代码片段已删除",
|
||
"deleteFailed": "删除代码片段失败",
|
||
"requiredFields": "代码片段名称和内容为必填项",
|
||
"saved": "代码片段已保存",
|
||
"saveFailed": "保存代码片段失败",
|
||
"saving": "保存中...",
|
||
"save": "保存"
|
||
},
|
||
"backToSnippets": "返回片段",
|
||
"settingsTitle": "代码片段设置",
|
||
"settingsDisplayTitle": "展示",
|
||
"settingsBehaviorTitle": "交互",
|
||
"typeCommandHint": "在当前终端中运行。",
|
||
"typeNoteHint": "无需运行即可粘贴到活动终端中。",
|
||
"variablesHint": "变量:$HOST、$USER、$PORT、$NAME、${INPUT_1:Label}",
|
||
"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": "已在 {{count}} 台主机上运行 \"{{name}}\"",
|
||
"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": "快速操作以按钮形式显示在主机指标工具栏中,以便一键执行命令。",
|
||
"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"
|
||
}
|
||
}
|