mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-31 07:35: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>
226 lines
10 KiB
JSON
226 lines
10 KiB
JSON
{
|
|
"permissions": {
|
|
"view": {
|
|
"title": "Xem các quy trình tự động hóa",
|
|
"description": "Xem các quy trình tự động hóa và lịch sử của chúng."
|
|
},
|
|
"create": {
|
|
"title": "Tạo các quy trình tự động hóa",
|
|
"description": "Thêm các quy trình tự động hóa mới."
|
|
},
|
|
"edit": {
|
|
"title": "Chỉnh sửa tự động hóa",
|
|
"description": "Thay đổi các quy trình tự động hóa hiện có."
|
|
},
|
|
"delete": {
|
|
"title": "Xóa các quy trình tự động hóa",
|
|
"description": "Loại bỏ các quy trình tự động hóa."
|
|
},
|
|
"run": {
|
|
"title": "Chạy các quy trình tự động hóa",
|
|
"description": "Kích hoạt quy trình tự động bằng tay."
|
|
}
|
|
},
|
|
"newUi": {
|
|
"sidebar": {
|
|
"automations": {
|
|
"title": "Tự động hóa",
|
|
"tabAutomations": "Tự động hóa",
|
|
"tabRuns": "Chạy",
|
|
"tabChannels": "Kênh",
|
|
"createAutomation": "Tự động hóa mới",
|
|
"backToAutomations": "Quay lại phần Tự động hóa",
|
|
"createTitle": "Tự động hóa mới",
|
|
"editTitle": "Tự động chỉnh sửa",
|
|
"empty": "Hiện chưa có tính năng tự động hóa nào. Hãy tạo một tính năng để phản ứng với một chỉ số, lịch trình hoặc sự kiện nào đó.",
|
|
"emptyRuns": "Chưa có lượt chạy nào.",
|
|
"channelsHint": "Các kênh được thiết lập trong mục Cảnh báo.",
|
|
"noChannelsHint": "Thông báo luôn được gửi đến hộp thư đến của bạn. Thêm kênh trong mục Thông báo để gửi thông báo đến các địa điểm khác nữa.",
|
|
"nameLabel": "Tên",
|
|
"namePlaceholder": "Ví dụ: Dọn dẹp thư mục /data khi nó đầy.",
|
|
"nameRequired": "Tên là bắt buộc",
|
|
"descriptionLabel": "Mô tả",
|
|
"descriptionPlaceholder": "Mô tả tùy chọn",
|
|
"enabledLabel": "Đã bật",
|
|
"concurrencyLabel": "Nếu nó đang chạy",
|
|
"concurrencyHint": "Phải làm gì khi sự cố này xảy ra lần nữa trước khi quá trình chạy cuối cùng hoàn tất?",
|
|
"concurrency": {
|
|
"skip": "Bỏ qua lần chạy mới",
|
|
"queue": "Chờ đợi và chạy theo",
|
|
"allow": "Chạy cả hai cùng một lúc"
|
|
},
|
|
"save": "Lưu",
|
|
"created": "Tự động hóa được tạo",
|
|
"updated": "Tự động hóa đã được lưu",
|
|
"deleted": "Tự động hóa đã bị xóa",
|
|
"deleteConfirm": "Xóa tự động hóa này? Lịch sử chạy của nó cũng bị xóa.",
|
|
"runNow": "Chạy ngay",
|
|
"testRun": "Chạy thử nghiệm",
|
|
"testRunHint": "Nó thực hiện mọi bước nhưng không chạm vào bất cứ thứ gì bên ngoài Termix.",
|
|
"runStarted": "Chạy bắt đầu",
|
|
"runFinished": "Quá trình chạy đã hoàn tất: {{status}}",
|
|
"trigger": "Kích hoạt",
|
|
"steps": "Các bước",
|
|
"addStep": "Thêm bước",
|
|
"removeStep": "Xóa bước",
|
|
"moveUp": "Tiến lên",
|
|
"moveDown": "Di chuyển xuống",
|
|
"noSteps": "Chưa có bước nào. Hãy thêm một bước để mô tả những gì cần xảy ra.",
|
|
"webhookTokenTitle": "URL Webhook",
|
|
"webhookTokenDescription": "Thông tin này chỉ hiển thị một lần. Hãy lưu lại ngay, bạn sẽ không thể khôi phục lại sau này.",
|
|
"copy": "Sao chép",
|
|
"copied": "Đã sao chép",
|
|
"viewJson": "JSON",
|
|
"viewBuilder": "Nhà xây dựng",
|
|
"viewGraph": "Đồ thị",
|
|
"lastRun": "Lần chạy cuối",
|
|
"never": "Chưa bao giờ",
|
|
"duration": "{{seconds}}s",
|
|
"stepOutput": "Đầu ra",
|
|
"stepError": "Lỗi",
|
|
"dryRunBadge": "Chạy thử nghiệm",
|
|
"hostSelector": {
|
|
"trigger": "Máy chủ kích hoạt",
|
|
"host": "Máy chủ cụ thể",
|
|
"fleet": "Hạm đội",
|
|
"all": "Tất cả máy chủ"
|
|
},
|
|
"triggerKinds": {
|
|
"metric_threshold": "Ngưỡng số liệu",
|
|
"host_status": "Máy chủ tăng hoặc giảm",
|
|
"health_check": "Thay đổi trong kiểm tra sức khỏe",
|
|
"schedule": "Theo lịch trình",
|
|
"docker_event": "Sự kiện container",
|
|
"internal_event": "Sự kiện Termix",
|
|
"webhook": "Webhook đến"
|
|
},
|
|
"stepTypes": {
|
|
"notify": "Gửi thông báo",
|
|
"http": "Gọi một URL",
|
|
"run_snippet": "Chạy một đoạn mã",
|
|
"run_command": "Chạy một lệnh",
|
|
"docker": "Kiểm soát một container",
|
|
"tunnel": "Kiểm soát đường hầm",
|
|
"wol": "Đánh thức một chủ nhà",
|
|
"wait": "Chờ đợi",
|
|
"set_var": "Đặt một biến",
|
|
"if": "Nếu/ngược lại",
|
|
"run_automation": "Chạy một quy trình tự động hóa khác",
|
|
"stop": "Bit dừng"
|
|
},
|
|
"statuses": {
|
|
"running": "Đang chạy",
|
|
"success": "Thành công",
|
|
"failed": "Thất bại",
|
|
"timeout": "Hết thời gian",
|
|
"skipped": "Bỏ qua",
|
|
"cancelled": "Đã hủy"
|
|
},
|
|
"fields": {
|
|
"host": "Máy chủ",
|
|
"metric": "Chỉ số",
|
|
"mount": "Điểm gắn kết",
|
|
"operator": "Là",
|
|
"value": "Giá trị",
|
|
"forSeconds": "Duy trì trong (giây)",
|
|
"cooldown": "Thời gian chờ (phút)",
|
|
"cron": "Biểu thức Cron",
|
|
"intervalSeconds": "Mỗi (giây)",
|
|
"timezone": "Múi giờ",
|
|
"timezoneServer": "Thời gian máy chủ",
|
|
"timezoneHint": "Thời gian Cron được đọc trong vùng này. Không áp dụng cho lịch trình theo khoảng thời gian.",
|
|
"container": "Thùng chứa",
|
|
"command": "Lệnh",
|
|
"url": "URL",
|
|
"method": "Phương pháp",
|
|
"body": "Thân hình",
|
|
"channels": "Cũng gửi đến",
|
|
"title": "Tiêu đề",
|
|
"message": "Tin nhắn",
|
|
"snippet": "Đoạn trích",
|
|
"seconds": "Giây",
|
|
"conditionLeftPlaceholder": "Giá trị cần kiểm tra",
|
|
"conditionRightPlaceholder": "So sánh với",
|
|
"variableName": "Tên biến",
|
|
"variableValue": "Giá trị",
|
|
"elevated": "Chạy với quyền sudo",
|
|
"onError": "Nếu điều này thất bại",
|
|
"allowPrivateNetwork": "Cho phép địa chỉ mạng cục bộ",
|
|
"allowPrivateNetworkHint": "Cần thiết cho dịch vụ tự lưu trữ trên mạng LAN của bạn. Mặc định là tắt để ngăn chặn các yêu cầu đến các địa chỉ nội bộ."
|
|
},
|
|
"onError": {
|
|
"stop": "Dừng cuộc chạy",
|
|
"continue": "Tiếp tục"
|
|
},
|
|
"needsPlugin": "Nhu cầu {{plugin}}",
|
|
"needsPluginHint": "Quá trình tự động hóa này sẽ bị bỏ qua cho đến khi tính năng cần thiết được khôi phục.",
|
|
"offBadge": "Tắt",
|
|
"docsLink": "Xem tài liệu",
|
|
"ago": {
|
|
"seconds": "{{count}}giây trước",
|
|
"minutes": "{{count}} phút trước",
|
|
"hours": "{{count}} giờ trước",
|
|
"days": "{{count}} ngày trước"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"nav": {
|
|
"automations": "Tự động hóa"
|
|
},
|
|
"onboarding": {
|
|
"feature_automations": "Tự động hóa",
|
|
"feature_automations_desc": "Thực hiện các bước tự động khi có sự kiện xảy ra và nhận thông báo."
|
|
},
|
|
"maintenance": {
|
|
"title": "Bảo trì",
|
|
"description": "Tạm dừng các hoạt động tự động hóa về trạng thái máy chủ, sức khỏe, số liệu, container và ngắt kết nối đường hầm trong khi công việc đang được tiến hành. Việc giám sát, chạy thủ công và các hoạt động tự động hóa theo lịch trình vẫn tiếp tục.",
|
|
"denied": "Bạn không có quyền xem thông tin bảo trì.",
|
|
"sharedReadOnly": "Máy chủ này được chia sẻ với bạn. Chỉ chủ sở hữu mới có thể thay đổi cài đặt bảo trì.",
|
|
"failed": "Không thể cập nhật bảo trì.",
|
|
"active": "Đang bảo trì",
|
|
"estimated": "Thời gian hoàn thành dự kiến",
|
|
"noAutoEnd": "Bản dự toán không kết thúc quá trình bảo trì. Hãy kết thúc quá trình bảo trì một cách rõ ràng khi công việc hoàn tất.",
|
|
"endConfirm": "Kết thúc bảo trì và tiếp tục các tự động hóa kích hoạt sự kiện cho máy chủ này?",
|
|
"confirmEnd": "Xác nhận kết thúc",
|
|
"cancel": "Hủy",
|
|
"end": "Kết thúc bảo trì",
|
|
"action": "Hành động",
|
|
"startNow": "Bắt đầu ngay bây giờ",
|
|
"schedule": "Lên lịch cho thời gian sau",
|
|
"reason": "Lý do",
|
|
"startUtc": "Lần khởi động đầu tiên (UTC)",
|
|
"repeat": "Lặp lại",
|
|
"once": "Một lần",
|
|
"weekly": "Hàng tuần",
|
|
"monthly": "Hàng tháng",
|
|
"utcHelp": "Lịch trình sử dụng múi giờ UTC suốt cả năm. Lịch trình hàng tháng sẽ bỏ qua các tháng không có ngày đã chọn. Các khung thời gian đã lên kế hoạch không được chồng chéo; việc bảo trì kéo dài sẽ tiếp tục sang các khung thời gian sau đó.",
|
|
"duration": "Thời gian ước tính (phút)",
|
|
"grace": "Thời gian ân hạn (phút)",
|
|
"notify": "Thông báo một lần nếu vẫn ngoại tuyến sau thời gian ước tính cộng thêm thời gian gia hạn.",
|
|
"addSchedule": "Thêm lịch trình",
|
|
"schedules": "Lịch trình",
|
|
"noSchedules": "Không có lịch bảo trì.",
|
|
"completed": "Đã bắt đầu",
|
|
"minutes_one": "{{count}} phút",
|
|
"minutes_other": "{{count}} phút",
|
|
"remove": "Xóa lịch trình",
|
|
"loadFailed": "Không thể cập nhật trạng thái bảo trì. Các thay đổi bị vô hiệu hóa cho đến khi có thể tải lại.",
|
|
"loading": "Đang tải trạng thái bảo trì…"
|
|
},
|
|
"ui": {
|
|
"sidebar": {
|
|
"automations": {
|
|
"options": {
|
|
"connect": "connect",
|
|
"disconnect": "disconnect",
|
|
"offline": "offline",
|
|
"online": "online",
|
|
"failing": "failing",
|
|
"recovered": "recovered"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|