Files
Termix/src/ui/locales/translated/vi_VN.json
T
+16 fef8a5f28a release-2.8.0 (#1456)
* Fix private AI custom endpoints (#1299)

* Fix Proxmox credential guest imports (#1300)

* Fix Fleet command results layout (#1301)

* Fix synced client tunnel endpoints (#1302)

* Fix Proxmox sync jump host persistence (#1303)

* Fix command palette keyboard navigation (#1304)

* Add accessible interface font choices (#1306)

* Add selectable host temperature sensors (#1307)

* Improve file manager navigation and compact layout (#1308)

* Add configurable global hotkeys (#1305)

* fix: restore split layout selection (#1310)

* fix: support macOS VNC connections (#1311)

* fix: use matching Undici fetch for private AI providers (#1309)

Co-authored-by: Angad Singh <angad@singhangad.in>

* feat: support additional TOTP authenticators (#1312)

* feat: add VNC display zoom controls (#1314)

* feat: add host context menu actions (#1315)

* fix: force classic auth for macOS VNC (#1313)

* fix: harden HTTP trust boundaries (#1316)

* fix: harden application trust boundaries (#1317)

* fix: verify OPKSSH binary integrity (#1318)

* Fix remote desktop connection timeout (#1319)

* chore(deps): bump node in /docker in the docker-major-updates group (#1321)

Bumps the docker-major-updates group in /docker with 1 update: node.


Updates `node` from 24-slim to 26-slim

---
updated-dependencies:
- dependency-name: node
  dependency-version: 26-slim
  dependency-type: direct:production
  dependency-group: docker-major-updates
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps-dev): bump the dev-patch-updates group with 15 updates (#1322)

Bumps the dev-patch-updates group with 15 updates:

| Package | From | To |
| --- | --- | --- |
| [@codemirror/view](https://github.com/codemirror/view) | `6.43.7` | `6.43.9` |
| [@commitlint/cli](https://github.com/conventional-changelog/commitlint/tree/HEAD/@commitlint/cli) | `21.2.1` | `21.2.2` |
| [@commitlint/config-conventional](https://github.com/conventional-changelog/commitlint/tree/HEAD/@commitlint/config-conventional) | `21.2.0` | `21.2.2` |
| [@testing-library/jest-dom](https://github.com/testing-library/jest-dom) | `7.0.0` | `7.0.1` |
| [@testing-library/user-event](https://github.com/testing-library/user-event) | `14.6.1` | `14.6.5` |
| [@vitest/coverage-v8](https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-v8) | `4.1.10` | `4.1.11` |
| [@vitest/ui](https://github.com/vitest-dev/vitest/tree/HEAD/packages/ui) | `4.1.10` | `4.1.11` |
| [concurrently](https://github.com/open-cli-tools/concurrently) | `10.0.4` | `10.0.5` |
| [cytoscape](https://github.com/cytoscape/cytoscape.js) | `3.34.0` | `3.34.1` |
| [eslint](https://github.com/eslint/eslint) | `10.8.0` | `10.8.1` |
| [eslint-plugin-react-refresh](https://github.com/ArnaudBarre/eslint-plugin-react-refresh) | `0.5.3` | `0.5.4` |
| [react-i18next](https://github.com/i18next/react-i18next) | `17.0.11` | `17.0.12` |
| [sonner](https://github.com/emilkowalski/sonner) | `2.0.7` | `2.0.8` |
| [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) | `8.2.0` | `8.2.2` |
| [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest) | `4.1.10` | `4.1.11` |


Updates `@codemirror/view` from 6.43.7 to 6.43.9
- [Changelog](https://github.com/codemirror/view/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codemirror/view/commits)

Updates `@commitlint/cli` from 21.2.1 to 21.2.2
- [Release notes](https://github.com/conventional-changelog/commitlint/releases)
- [Changelog](https://github.com/conventional-changelog/commitlint/blob/master/@commitlint/cli/CHANGELOG.md)
- [Commits](https://github.com/conventional-changelog/commitlint/commits/v21.2.2/@commitlint/cli)

Updates `@commitlint/config-conventional` from 21.2.0 to 21.2.2
- [Release notes](https://github.com/conventional-changelog/commitlint/releases)
- [Changelog](https://github.com/conventional-changelog/commitlint/blob/master/@commitlint/config-conventional/CHANGELOG.md)
- [Commits](https://github.com/conventional-changelog/commitlint/commits/v21.2.2/@commitlint/config-conventional)

Updates `@testing-library/jest-dom` from 7.0.0 to 7.0.1
- [Release notes](https://github.com/testing-library/jest-dom/releases)
- [Changelog](https://github.com/testing-library/jest-dom/blob/main/CHANGELOG.md)
- [Commits](https://github.com/testing-library/jest-dom/compare/v7.0.0...v7.0.1)

Updates `@testing-library/user-event` from 14.6.1 to 14.6.5
- [Release notes](https://github.com/testing-library/user-event/releases)
- [Changelog](https://github.com/testing-library/user-event/blob/main/CHANGELOG.md)
- [Commits](https://github.com/testing-library/user-event/compare/v14.6.1...v14.6.5)

Updates `@vitest/coverage-v8` from 4.1.10 to 4.1.11
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.11/packages/coverage-v8)

Updates `@vitest/ui` from 4.1.10 to 4.1.11
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.11/packages/ui)

Updates `concurrently` from 10.0.4 to 10.0.5
- [Release notes](https://github.com/open-cli-tools/concurrently/releases)
- [Commits](https://github.com/open-cli-tools/concurrently/compare/v10.0.4...v10.0.5)

Updates `cytoscape` from 3.34.0 to 3.34.1
- [Release notes](https://github.com/cytoscape/cytoscape.js/releases)
- [Commits](https://github.com/cytoscape/cytoscape.js/compare/v3.34.0...v3.34.1)

Updates `eslint` from 10.8.0 to 10.8.1
- [Release notes](https://github.com/eslint/eslint/releases)
- [Commits](https://github.com/eslint/eslint/compare/v10.8.0...v10.8.1)

Updates `eslint-plugin-react-refresh` from 0.5.3 to 0.5.4
- [Release notes](https://github.com/ArnaudBarre/eslint-plugin-react-refresh/releases)
- [Changelog](https://github.com/ArnaudBarre/eslint-plugin-react-refresh/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ArnaudBarre/eslint-plugin-react-refresh/compare/v0.5.3...v0.5.4)

Updates `react-i18next` from 17.0.11 to 17.0.12
- [Changelog](https://github.com/i18next/react-i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/react-i18next/compare/v17.0.11...v17.0.12)

Updates `sonner` from 2.0.7 to 2.0.8
- [Release notes](https://github.com/emilkowalski/sonner/releases)
- [Commits](https://github.com/emilkowalski/sonner/compare/v2.0.7...v2.0.8)

Updates `vite` from 8.2.0 to 8.2.2
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v8.2.2/packages/vite)

Updates `vitest` from 4.1.10 to 4.1.11
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.11/packages/vitest)

---
updated-dependencies:
- dependency-name: "@codemirror/view"
  dependency-version: 6.43.9
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: "@commitlint/cli"
  dependency-version: 21.2.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: "@commitlint/config-conventional"
  dependency-version: 21.2.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: "@testing-library/jest-dom"
  dependency-version: 7.0.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: "@testing-library/user-event"
  dependency-version: 14.6.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: "@vitest/coverage-v8"
  dependency-version: 4.1.11
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: "@vitest/ui"
  dependency-version: 4.1.11
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: concurrently
  dependency-version: 10.0.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: cytoscape
  dependency-version: 3.34.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: eslint
  dependency-version: 10.8.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: eslint-plugin-react-refresh
  dependency-version: 0.5.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: react-i18next
  dependency-version: 17.0.12
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: sonner
  dependency-version: 2.0.8
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: vite
  dependency-version: 8.2.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: vitest
  dependency-version: 4.1.11
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): bump the prod-patch-updates group with 5 updates (#1324)

Bumps the prod-patch-updates group with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [@tanstack/react-virtual](https://github.com/TanStack/virtual/tree/HEAD/packages/react-virtual) | `3.14.9` | `3.14.10` |
| [better-sqlite3](https://github.com/WiseLibs/better-sqlite3) | `13.0.2` | `13.0.3` |
| [jose](https://github.com/panva/jose) | `6.2.8` | `6.2.9` |
| [mysql2](https://github.com/sidorares/node-mysql2) | `3.23.2` | `3.23.4` |
| [ws](https://github.com/websockets/ws) | `8.21.1` | `8.21.3` |


Updates `@tanstack/react-virtual` from 3.14.9 to 3.14.10
- [Release notes](https://github.com/TanStack/virtual/releases)
- [Changelog](https://github.com/TanStack/virtual/blob/main/packages/react-virtual/CHANGELOG.md)
- [Commits](https://github.com/TanStack/virtual/commits/@tanstack/react-virtual@3.14.10/packages/react-virtual)

Updates `better-sqlite3` from 13.0.2 to 13.0.3
- [Release notes](https://github.com/WiseLibs/better-sqlite3/releases)
- [Commits](https://github.com/WiseLibs/better-sqlite3/compare/v13.0.2...v13.0.3)

Updates `jose` from 6.2.8 to 6.2.9
- [Release notes](https://github.com/panva/jose/releases)
- [Changelog](https://github.com/panva/jose/blob/main/CHANGELOG.md)
- [Commits](https://github.com/panva/jose/compare/v6.2.8...v6.2.9)

Updates `mysql2` from 3.23.2 to 3.23.4
- [Release notes](https://github.com/sidorares/node-mysql2/releases)
- [Changelog](https://github.com/sidorares/node-mysql2/blob/master/Changelog.md)
- [Commits](https://github.com/sidorares/node-mysql2/compare/v3.23.2...v3.23.4)

Updates `ws` from 8.21.1 to 8.21.3
- [Release notes](https://github.com/websockets/ws/releases)
- [Commits](https://github.com/websockets/ws/compare/8.21.1...8.21.3)

---
updated-dependencies:
- dependency-name: "@tanstack/react-virtual"
  dependency-version: 3.14.10
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: prod-patch-updates
- dependency-name: better-sqlite3
  dependency-version: 13.0.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: prod-patch-updates
- dependency-name: jose
  dependency-version: 6.2.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: prod-patch-updates
- dependency-name: mysql2
  dependency-version: 3.23.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: prod-patch-updates
- dependency-name: ws
  dependency-version: 8.21.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: prod-patch-updates
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): bump motion in the major-updates group (#1326)

Bumps the major-updates group with 1 update: [motion](https://github.com/motiondivision/motion).


Updates `motion` from 12.43.0 to 13.1.1
- [Changelog](https://github.com/motiondivision/motion/blob/main/CHANGELOG.md)
- [Commits](https://github.com/motiondivision/motion/compare/v12.43.0...v13.1.1)

---
updated-dependencies:
- dependency-name: motion
  dependency-version: 13.1.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: major-updates
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* feat: add semantic motion system (#1320)

* feat: add semantic motion system

* feat: animate session workspace transitions

* feat: refine motion accessibility and transfer feedback

* feat: enforce RBAC and harden collaboration features (#1327)

* feat: enforce RBAC and harden collaboration features

- Mount requirePermission on hosts/snippets/credentials/automations/AI routes
- Seed and backfill system role permissions on every dialect at startup
- Support personal credential overrides for RDP/VNC/Telnet shared hosts
- Broadcast participant presence in shared terminal sessions
- Make audit log forwarding configurable from the admin panel
- Add role members endpoint and snippet folder sharing

* fix: enforce RBAC across split routes

* fix: reject malformed Guacamole tokens safely (#1329)

* fix: allow approved private notification hosts (#1330)

* feat: collaboration rooms with switchable presenter (#1328)

* feat: add collaboration rooms with switchable presenter

Rooms are a group of members watching one stage - the live SSH/RDP/VNC
session the current presenter shares. Any member can take over the
stage; the host can invite, force-stop and end the meeting. Stages
reuse session_shares (new room share type), so gating, recording,
expiry and the global sharing toggle all apply unchanged.

* feat: add stage control handoff to collaboration rooms

The presenter or host can grant any member write access to the live
stage and take it back; members can raise a hand to ask. SSH flips the
participant's permission on the live gate; RDP/VNC re-mint the viewer's
join token. Control clears on every stage switch.

* feat: guest links, role invites and invite awareness for collab rooms

- Anonymous guest link per room (host toggles/rotates), followed by
  polling the public resolve endpoint; SSH guests join over the terminal
  WS with roomGuestToken, guac guests get read-only join tokens
- Invite by role (expands to current members, snapshot semantics)
- Toast when a room you were invited to appears
- Stale stages are cleared lazily when the presenter is gone
- Telnet presenting, expired-tab fallback, documented single-instance
  and guac-kick limits
- Tests for the collab routes, room hub, share access and control flip

* fix: keep remote desktop collaboration read-only

* fix: restore RDP clipboard paste across browsers (#1331)

* fix: show the full command line in the process inspector (#1334)

The CMD column rendered ps's comm field, which the kernel caps at 15
characters, so anything longer looked truncated no matter how wide the
column was. The full args were already collected; show them.

* fix: harden collaboration room access (#1332)

* fix: harden collaboration room access

* fix: confirm guest link lifecycle changes

* fix: make RDP drive redirection writable on the stock deployment (#1333)

* fix: make RDP drive redirection writable on the stock deployment

The default drive-path was /drive on the guacd side, which the official
guacd image cannot create as its non-root user, so every upload was
refused with guacd's raw "FAIL (CANNOT OPEN)" ack. Default to
GUACD_DRIVE_PATH (set to the shared termix-data volume in compose) with
one folder per user, and explain guacd's refusal in the file browser.

* style: format RDP drive settings

* feat: quick connect for RDP and VNC (#1335)

The Quick Connect panel gets a protocol switch. RDP/VNC quick hosts are
built like SSH ones (never saved) and opened as regular remote desktop
tabs; GuacamoleApp mints their token from the typed fields through the
existing /guacamole/token endpoint instead of a host-row lookup.

* fix: authenticate unwatched hosts during the status probe (#1337)

With metrics enabled, the status probe left SSH authentication to the
metrics poll - which only runs while someone is viewing the host. An
unwatched host therefore never left "reachable", while a host with
metrics disabled (whose probe always authenticates) showed online. The
probe now authenticates whenever no metrics poll will.

* feat: compact snippet list option (#1339)

A "Show Commands" toggle in the snippets settings menu hides the command
text under each snippet name, for people who dock the panel on the
narrow right rail and only need the names. Local preference, on by
default.

* fix: guide users to Auto-Tmux when a persisted session expires (#1336)

* fix: guide users to Auto-Tmux when a persisted session expires

A timed-out terminal session silently reconnected to a fresh shell, so
people running long jobs lost them with no explanation and never learned
about Auto-Tmux. Explain the expiry with a one-click Enable Auto-Tmux
action, let admins default it for new hosts and tune the persistence
timeout from the UI, and move the setting up with copy that says what it
does. The global default stays off.

* style: format terminal expiry notice

* feat: improve collaboration rooms (#1338)

* feat: Step CA SSH certificates as a host authentication type (#1340)

* feat: Step CA SSH certificates as a host authentication type

Issue short-lived SSH user certificates from a smallstep CA through its
OIDC provisioner, over the CA's HTTP API rather than the step binary.
Everything after issuance reuses the OPKSSH plumbing: the same encrypted
per-user/host token store, WebSocket dialog and ssh2 certificate
injection, with the connect paths branching on a shared
usesIssuedCertificate() predicate. Instance-wide CA settings live in the
admin panel, with a private-host allowlist for the SSRF guard.

* fix: harden Step CA callback flow

* style: format Step CA changes

* feat: 1Password Connect secret sources for SSH credentials (#1341)

* feat: 1Password Connect secret sources for SSH credentials

Hosts and credentials can hold op://vault/item/field references instead
of secrets; they are resolved at connect time from the user's secret
source (1Password Connect) at the single point where every subsystem
receives plaintext credentials, so terminal, SFTP, Docker, metrics and
tunnels all work without per-subsystem changes. Sources are per user,
optionally shared, with the access token encrypted under the owner's
data key; resolved values are cached briefly in memory.

* style: format secret source changes

* feat: share credentials with users and roles, inherit data on account deletion (#1342)

* feat: share credentials with users and roles, inherit data on account deletion

Credentials can be shared at "use" or "manage" level. Recipients get
a copy re-encrypted under their own data key (shared_credential_secrets),
kept in step with the owner's row through the same lifecycle hooks as
shared host secrets. One gate, findUsableCredential(), replaces the
private-namespace lookups so a shared credential works wherever a
private one does. Deleting a user now hands their hosts and credentials
to a successor (the deleting admin by default) instead of revoking
everything they shared.

* fix: harden credential ownership transfer

* feat: folder shares apply to hosts added later (#1343)

* feat: folder shares apply to hosts added later

Sharing a folder only fanned grants out to the hosts in it at the time.
The share is now also kept as a standing rule on the folder, and a host
created in or moved into it (or a subfolder) inherits the same access
and secret snapshots. Rules follow folder renames and can be stopped
from the share dialog.

* fix: stabilize folder access migrations

* fix: package sharp for both macOS architectures (#1344)

* fix: prompt shared RDP users for credentials (#1345)

* feat: add terminal copy-on-select option (#1346)

* fix: retry protected file reads with sudo (#1349)

* fix: stop SSH-authenticating hosts during routine status polling (#1347)

* fix: preserve omitted host protocol settings (#1350)

* fix: surface remote sync reauthentication failures (#1351)

* fix: harden file reads and timer cleanup (#1352)

* fix: harden file reads and timer cleanup

* fix: preserve literal file path escapes

* fix: enforce SSH pool connection limits (#1353)

* fix: enforce SSH pool connection limits

* fix: discard stale pooled connections

* fix: harden connection, payload, and persisted state handling (#1354)

* fix: clean up Cloudflare tunnel timeouts

* fix: couple tunnel socket lifecycle

* fix: validate Docker console messages

* fix: bound homepage proxy responses

* fix: bound reconnect and response failures

* fix: harden persisted and socket state

* fix: support local connections to shared hosts

* fix: recover expired dashboard metrics sessions (#1355)

* fix: upload files to redirected RDP drives (#1356)

* fix: unify connection toolbar visibility (#1357)

* fix: reset host virtualizer after editing (#1358)

* test: update Guacamole toolbar display mock (#1360)

* fix: reflect live SSH sessions in host status (#1359)

* fix: support Vault auth in file manager (#1361)

* fix: allow exec on shared hosts (#1362)

* fix(file-manager): align chunked upload contract (#1371)

* fix(file-manager): make bulk uploads resilient (#1373)

* fix(terminal): disable local echo on alternate screen (#1372)

* fix(homepage): validate clock widget timezones (#1374)

An invalid timezone in a clock widget's config reached toLocaleTimeString
unchecked, throwing RangeError during render and taking the homepage canvas
down with it. The edit dialog accepted any string, so "America/New York" - a
space where IANA wants an underscore - was easy to save, and the homepage
stayed broken on every later load because the value is reloaded from the
database.

The edit dialog now flags an unusable zone the way FolderMetadataDialog flags
a duplicate folder name: inline message, aria-invalid, and a disabled Save.
Whitespace is normalized to underscores on save, so the space spelling is
stored as America/New_York rather than rejected. ClockWidget falls back to
local time for any config already holding an invalid zone.

Related to Termix-SSH/Support#1238

* fix(hosts): preserve connection origin in editor (#1376)

* fix(remote-sync): expose local login notification (#1375)

* fix(auth): allow passkeys in desktop login (#1378)

* fix(proxmox): elevate guest discovery commands (#1379)

* Fix permanent file-transfer completion toasts (#1383)

* fix(file-manager): expire completed progress toasts

* test(file-manager): use valid transfer status

* fix(hosts): allow clearing SSH key type (#1384)

* fix(terminal): suppress local echo for contextual password prompts (#1387)

* fix(desktop): surface a failed embedded backend start (#1382)

* fix(desktop): surface a failed embedded backend start

When the embedded backend's HTTP port was already taken, the desktop app
sat on the "Loading..." spinner forever with nothing in the UI to say
why. The backend logged the conflict and exited 1, and startBackendServer
resolved false, but that verdict never reached the renderer: the
get-embedded-server-status channel was not exposed in preload and nothing
called it.

The renderer, by design, treats every connection failure as "the embedded
backend is still booting" and retries indefinitely -- in main.tsx's
verifying phase, in Auth's desktop auto-session, and in
FullScreenAppWrapper. That holds while the backend is merely slow to boot,
but not once the process has exited, and nothing distinguished the two.

Classify why the child died from its exit code and a bounded tail of its
stderr, report it through get-embedded-server-status, and have each retry
loop keep waiting only while no failure is reported. A port conflict names
the port, since that is what the user has to act on -- most often a Termix
container on the same ports, or a backend orphaned by a hard-kill that
reapOrphanedBackendProcess could not claim.

A deliberate shutdown is not reported as a crash, and a backend that is
only slow to start still gets retried as before.

Fixes Termix-SSH/Support#1254

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(desktop): treat every unrequested backend exit as a failure

The classifier exempted a clean exit and SIGTERM/SIGINT, calling those a
deliberate shutdown. It has no evidence for that: its only caller already
sits behind backendStopRequested, so it is reached only for exits
stopBackendServer() did not ask for. A backend that exited 0 on its own,
or was terminated by the OS or an external signal, therefore reported no
failure at all -- leaving all three renderer loops waiting forever for a
process that is gone, which is the exact hang this change set exists to
remove.

Every exit reaching the classifier is now a failure, port-in-use when
stderr carries EADDRINUSE and crashed otherwise, with backendStopRequested
left as the sole deliberate-shutdown guard. That makes the exit code and
signal irrelevant to the verdict, so the classifier now takes only the
stderr tail rather than carrying two parameters it no longer reads.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>

* Add white label branding settings (#1386)

* feat(admin): add white label branding settings

Admins can configure a custom app name, logo and tagline from the
Admin Settings panel. The values apply to the login screen and the
browser tab title/favicon at runtime.

* fix(admin): restore default icons on logo reset, validate upload MIME type

Resetting the logo now restores the bundled favicon/apple-touch-icon
instead of leaving the previous custom one until a reload. The admin
upload also validates file.type up front instead of only failing
later on save.

* fix(admin): restore default favicons and reject invalid logo types

Capture bundled icon hrefs before the first custom logo is applied so a
reset does not leave the previous upload in the tab, and reject
non-image uploads before they are read into branding state.

* test(admin): cover branding routes and logo validation

Add backend tests for the public GET, admin-only PATCH, unknown-field
rejection, and parseBrandingLogoDataUrl so invalid images cannot land
in settings without a failing test.

* fix(backend): report port conflicts on the service ports (#1388)

Express's app.listen(port, host, callback) registers that callback as the
server's error handler as well as its listening handler:

    if (typeof args[args.length - 1] === 'function') {
      var done = args[args.length - 1] = once(args[args.length - 1])
      server.once('error', done)
    }

so a bind failure invoked the service's "started" callback with an
EADDRINUSE error as its only argument and emitted nothing. None of the
services read that argument, which made a failed bind indistinguishable
from a successful one: the service logged that it had started, ran its
initialisation, and served nothing. With one of 30003-30012 occupied the
backend still reported backend_init_complete, the app loaded, and the
affected feature was dead for the session with no error anywhere in the
logs -- searching the backend log, the Electron main log and stdout for
EADDRINUSE returned nothing, as did uncaughtException and
unhandledRejection probes.

This is also why only the main port behaved sensibly: database.ts does
not use app.listen(), it builds the server and attaches a real error
handler, so 30001 was the one port whose conflict was ever detected.

listenOnServicePort() builds the server so that listening and error stay
separate, and treats a conflict the way database.ts already does -- name
the port, then exit -- rather than running on with one feature missing.
Exiting also hands the desktop app the classified failure it already
surfaces, so the user is told which port to free. Services that must own
their server, such as the tunnel service with its WebSocket upgrade
handler, get the same handler via attachServicePortConflictHandler().

Note that adding .on("error") to the services would not have worked:
express consumes the event through once('error', done) before any later
handler runs. The callback has to stop being passed to listen() at all.

Fixes Termix-SSH/Support#1260

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>

* feat(desktop): allow RDP/VNC/Telnet to originate from this device (#1389)

The desktop pinned rdp/vnc/telnet to the remote server, so a host the
user's own machine could reach but the Termix server could not was
impossible to open: the app answered "Remote server required" even when
no remote server was wanted. The embedded backend already runs the
Guacamole websocket server and guacd's address is already configurable
globally and per host, so what was missing was the choice.

resolveConnectionOrigin now honours an explicit per-host origin for
these protocols. Left on Default they still resolve to remote: they need
a guacd, which the desktop does not ship, so originating locally only
works once the user has pointed Termix at one of their own. Keeping that
opt-in means an upgrade never moves a working connection onto a guacd
that is not there. Serial and non-Electron behaviour are unchanged.

Three call paths had the same assumption baked in and would have quietly
ignored the setting:

- The Guacamole call sites resolved the origin without passing the
  host's own override, so it could never take effect.
- guacamole-api sent every token, connect-host and status call to the
  remote server whenever running under Electron, and remapped the host
  id onto the remote server's id -- which would address the wrong row,
  or fail outright with no server configured.
- GuacamoleDisplay minted its token before resolving the origin, so the
  token could come from a different backend than the socket dialled.

The origin is a required parameter on those API functions rather than a
defaulted one. A default silently sent a missed call site to the remote
server: the guacd status check in fetchToken was one, and it failed with
a bare "Network Error" on a desktop with no server configured. Making it
required means the compiler names every caller instead. That also
covers CollabRoomTab, which now resolves from the host it already holds,
so a locally-originated host stays local when presented into a room.

Finally, the Connection Origin control was gated on SSH alone, so a host
enabling only these protocols could never reach the setting. That gate
is now a named predicate covering every protocol the control applies to.

Verified end to end on Linux against a local guacd: with a host set to
"This device", guacd accepted the connection and reached the target,
which answered for itself. With guacd stopped, the guacd status check
that has run before every connection since v2.3.0 -- now asking the
backend the session will actually use -- reports it clearly before a
socket is opened.

Refs Termix-SSH/Support#1240

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>

* feat(local-terminal): add copy/paste support (#1391)

* feat(local-terminal): add copy/paste support

Local terminal had no clipboard wiring, so selected text couldn't be
copied. Extracted the SSH terminal's copy/paste shortcut and
right-click handling into a shared terminal-clipboard module and wired
it into both terminals, removing duplicated logic in the process.

* fix(local-terminal): stop language changes from restarting the shell session

The session effect that starts the local PTY depended on `t`, whose
identity changes on every language switch (react-i18next). That tore
down the running shell and spawned a new one just from changing the UI
language. Read translations through a ref instead so localization
stays decoupled from the PTY lifecycle.

Also adds regression coverage for the extracted terminal-clipboard.ts
helpers: copy with/without selection, explicit vs native paste,
right-click preference, and Ctrl+right-click passthrough.

* fix(file-manager): keep name column visible on narrow viewports in list view (#1402)

Rebased onto dev-2.8.0 (the density refactor kept the same 3
list-view grid patterns). Use minmax(140px, 1fr) for the name track
so it cannot collapse to 0px on narrow viewports; the table scrolls
horizontally instead of hiding names and icons.

Co-authored-by: inontz <inontz@users.noreply.github.com>

* feat(desktop): local filesystem and transfer bridge for the file manager (#1392)

* feat(desktop): local filesystem and transfer bridge for the file manager

Adds the Electron main-process side of the upcoming Local | Remote dual-pane
file manager, with no UI yet:

- electron/local-files.cjs: IPC handlers to browse the local disk (home,
  list, mkdir, createFile, rename, trash, ensureDir, walk, reveal, open) and
  to stream files between the local disk and the file-manager backend
  (uploadLocalFile / downloadToLocal with progress events and cancellation).
  Streams go through Electron's `net` so the session cookie / remembered JWT
  is attached the same way as the renderer's own requests.
- electron/preload.js: exposes them as `window.electronAPI.localFs` and
  `window.electronAPI.localTransfer`; the existing `invoke` allowlist is
  untouched.
- src/types/electron.d.ts: typings for the new surface.
- electron/main.cjs: registers the handlers.

Follow-up PRs add the renderer side (local pane, drag-and-drop transfers,
context menu).

* fix(desktop): harden the local transfer bridge (origin allowlist, collision policy)

Addresses the review on the transfer boundary:

- The renderer no longer supplies a URL or headers. It sends
  `{ origin: "local" | "remote", route, deviceId }` and the main process
  resolves the target itself: fixed route allowlist (`uploadFileStream`,
  `downloadFileStream`), local = the embedded backend base, remote = the
  remote-sync config's URL (http/https only) with the stored JWT. Anything
  else is rejected before a request is made. `deviceId` is validated.
- Downloads never rename or replace silently. The destination is checked
  first and `EEXIST` is returned unless the caller passes `overwrite: true`.
  Each transfer writes to its own `<dest>.<transferId>.termix-part` opened
  with `wx`, and publishes with `fs.link` / `COPYFILE_EXCL` (rename only when
  overwriting), so concurrent transfers to the same path cannot share or
  clobber a partial (`EBUSY` for the second). Partials are removed on
  failure or cancel.
- New `local-fs:exists` handler so the renderer can ask before starting.
- `createLocalFileHandlers` / `createTargetResolver` take their
  dependencies (net, shell, remote-sync getters) as parameters so the
  boundary is unit-testable without Electron.
- src/backend/tests/electron/local-files.test.ts: target resolution and
  off-origin refusal, EEXIST / EBUSY / overwrite paths, unique partials and
  cleanup, upload multipart integrity (parsed with Busboy).

* fix(desktop): Windows-safe replace for overwrite downloads

`publishDownload()` used `rename(partial, dest)` for the explicit overwrite
path. POSIX replaces the destination, but on Windows rename() onto an
existing name commonly fails (EEXIST / EPERM, always while the file is
open), so "Replace" did not actually work there.

The overwrite path no longer renames onto an occupied name:

1. the current file is moved aside to a transfer-unique sibling
   (`<dest>.<transferId>.termix-replaced`) - renaming to a fresh name is
   safe on every platform;
2. the partial is published exclusively under the now-free name (the same
   `link` / `COPYFILE_EXCL` primitive the non-overwrite path uses);
3. the aside copy is deleted (retried once; if another process still holds
   it open on Windows it is left in place and logged rather than failing
   the transfer).

Failure handling preserves the original: if step 1 fails (file in use)
nothing has changed and the caller gets `EBUSY`; if step 2 fails the aside
copy is moved back under its name and the error propagates. Replacing a
folder with a file is refused with `EISDIR`; a destination that vanished
mid-transfer falls back to the exclusive publish.

The publish primitives take their filesystem operations as an injectable
`publishFs` (default: real fs), and the tests drive them with a
Windows-like fs whose rename() refuses to overwrite - so the strategy is
verified without relying on POSIX rename-over-existing semantics:
successful swap with no rename ever targeting an occupied name, original
restored byte-for-byte when publishing fails, EBUSY with nothing touched
when the file cannot be moved aside, EISDIR for folders, vanished
destination, and the end-to-end overwrite through the download handler.

---------

Co-authored-by: Max <maxim@cogitate.ai>

* chore: update package lock

* feat(file-manager): Termius-style Local | Remote dual pane with drag-and-drop transfers (desktop)

Renderer side of the dual-pane file manager, built on the local filesystem
bridge added in the previous PR. Desktop app only; the web build is
unchanged (the toggle is hidden when `window.electronAPI.localFs` is absent).

- New Local pane (LocalFilePane) next to the remote grid, toggled from the
  toolbar (Laptop icon); path, visibility and width are remembered in
  localStorage (`termix:file-manager:local-pane:*`). Grid and list views,
  hidden files toggle, breadcrumb navigation, New Folder.
- Drag files/folders from the Local pane onto the remote grid to upload,
  and from the remote grid onto the Local pane to download. Both directions
  stream through the main process (`useLocalTransfers`) with a single
  progress toast per batch (speed, ETA, cancel). Finder drops onto the
  remote grid keep working as before.
- Collision policy for downloads: destinations are checked first; if any
  exist the user is asked Replace / Skip for the batch. Skip, dismiss and
  timeout all mean skip - nothing is ever replaced without an explicit
  click, and the main process enforces the same rule (`EEXIST` unless
  `overwrite` is set).
- Drag MIME contract: `application/x-termix-local-files` for local drags,
  `application/x-termix-remote-files` marker on the remote grid's internal
  drags, so each pane can tell the two apart from Finder drops.
- Transfer targets are described as `{ origin, route, deviceId }`
  (`getSessionOrigin` in main-axios) - the renderer never hands the main
  process a URL.
- i18n: new `fileManager.local*` keys in en.json only (other locales via
  Crowdin).
- Tests: LocalFilePane rendering/navigation, local-transfer-utils
  (relative-path planning, size formatting).
- Modified column uses the same `Mon DD HH:MM` / `Mon DD  YYYY` (ls -l style)
  format as the remote grid, so both panes read alike.

* docs: point security note to the docs root (old /security page is gone) (#1400)

* chore: sync Crowdin translations

* chore(deps): bump the prod-minor-updates group across 1 directory with 3 updates (#1325)

Bumps the prod-minor-updates group with 3 updates in the / directory: [@anthropic-ai/sdk](https://github.com/anthropics/anthropic-sdk-typescript), [js-yaml](https://github.com/nodeca/js-yaml) and [pg](https://github.com/brianc/node-postgres/tree/HEAD/packages/pg).


Updates `@anthropic-ai/sdk` from 0.116.0 to 0.120.0
- [Release notes](https://github.com/anthropics/anthropic-sdk-typescript/releases)
- [Changelog](https://github.com/anthropics/anthropic-sdk-typescript/blob/main/CHANGELOG.md)
- [Commits](https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.116.0...sdk-v0.120.0)

Updates `js-yaml` from 5.2.3 to 5.3.0
- [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodeca/js-yaml/compare/5.2.3...5.3.0)

Updates `pg` from 8.22.0 to 8.23.0
- [Changelog](https://github.com/brianc/node-postgres/blob/master/CHANGELOG.md)
- [Commits](https://github.com/brianc/node-postgres/commits/pg@8.23.0/packages/pg)

---
updated-dependencies:
- dependency-name: "@anthropic-ai/sdk"
  dependency-version: 0.120.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-minor-updates
- dependency-name: js-yaml
  dependency-version: 5.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-minor-updates
- dependency-name: pg
  dependency-version: 8.23.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-minor-updates
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps-dev): bump the dev-minor-updates group across 1 directory with 10 updates (#1323)

Bumps the dev-minor-updates group with 10 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [@codemirror/commands](https://github.com/codemirror/commands) | `6.10.4` | `6.11.0` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `26.1.2` | `26.2.0` |
| [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react) | `6.0.5` | `6.1.0` |
| [electron](https://github.com/electron/electron) | `43.2.0` | `43.4.1` |
| [globals](https://github.com/sindresorhus/globals) | `17.9.0` | `17.11.0` |
| [i18next](https://github.com/i18next/i18next) | `26.3.6` | `26.4.0` |
| [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) | `1.28.0` | `1.33.0` |
| [react-hook-form](https://github.com/react-hook-form/react-hook-form) | `7.84.0` | `7.85.0` |
| [react-pdf](https://github.com/wojtekmaj/react-pdf/tree/HEAD/packages/react-pdf) | `10.4.1` | `10.5.0` |
| [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) | `8.66.0` | `8.67.0` |



Updates `@codemirror/commands` from 6.10.4 to 6.11.0
- [Changelog](https://github.com/codemirror/commands/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codemirror/commands/commits)

Updates `@types/node` from 26.1.2 to 26.2.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@vitejs/plugin-react` from 6.0.5 to 6.1.0
- [Release notes](https://github.com/vitejs/vite-plugin-react/releases)
- [Changelog](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite-plugin-react/commits/plugin-react@6.1.0/packages/plugin-react)

Updates `electron` from 43.2.0 to 43.4.1
- [Release notes](https://github.com/electron/electron/releases)
- [Commits](https://github.com/electron/electron/compare/v43.2.0...v43.4.1)

Updates `globals` from 17.9.0 to 17.11.0
- [Release notes](https://github.com/sindresorhus/globals/releases)
- [Commits](https://github.com/sindresorhus/globals/compare/v17.9.0...v17.11.0)

Updates `i18next` from 26.3.6 to 26.4.0
- [Release notes](https://github.com/i18next/i18next/releases)
- [Changelog](https://github.com/i18next/i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next/compare/v26.3.6...v26.4.0)

Updates `lucide-react` from 1.28.0 to 1.33.0
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/1.33.0/packages/lucide-react)

Updates `react-hook-form` from 7.84.0 to 7.85.0
- [Release notes](https://github.com/react-hook-form/react-hook-form/releases)
- [Changelog](https://github.com/react-hook-form/react-hook-form/blob/master/CHANGELOG.md)
- [Commits](https://github.com/react-hook-form/react-hook-form/compare/v7.84.0...v7.85.0)

Updates `react-pdf` from 10.4.1 to 10.5.0
- [Release notes](https://github.com/wojtekmaj/react-pdf/releases)
- [Commits](https://github.com/wojtekmaj/react-pdf/commits/v10.5.0/packages/react-pdf)

Updates `typescript-eslint` from 8.66.0 to 8.67.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.67.0/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: "@codemirror/commands"
  dependency-version: 6.11.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: "@types/node"
  dependency-version: 26.2.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: "@vitejs/plugin-react"
  dependency-version: 6.1.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: electron
  dependency-version: 43.4.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: globals
  dependency-version: 17.11.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: i18next
  dependency-version: 26.4.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: lucide-react
  dependency-version: 1.33.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: react-hook-form
  dependency-version: 7.85.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: react-pdf
  dependency-version: 10.5.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: typescript-eslint
  dependency-version: 8.67.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore: sync Crowdin translations

* Update redirect-issues workflow configuration

Updated the workflow to change the runner and modify the issue response message.

* chore: sync Crowdin translations

* Add Hetzner logo and referral link to README

Added Hetzner logo with a referral link to README.

* Fix Hetzner logo URL in README.md

* docs: point security note to the feature security page

The old /security page is gone and the docs root redirects to /install/,
which loses the encryption context the sentence promises. Point the
per-user secret and database encryption note at the canonical
docs.termix.site/features/authentication/security/ page instead.
Applied across all README locales.

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: LukeGus <bugattiguy527@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Luke Gustafson <88517757+LukeGus@users.noreply.github.com>
Co-authored-by: ssmurfgg04-gif <232103099+ssmurfgg04-gif@users.noreply.github.com>
Co-authored-by: ZacharyZcR <payasonorahc@protonmail.com>

* fix: use i18n for host status tooltip labels (#1403)

* chore: sync Crowdin translations

* chore(deps): bump the prod-minor-updates group across 1 directory with 3 updates (#1325)

Bumps the prod-minor-updates group with 3 updates in the / directory: [@anthropic-ai/sdk](https://github.com/anthropics/anthropic-sdk-typescript), [js-yaml](https://github.com/nodeca/js-yaml) and [pg](https://github.com/brianc/node-postgres/tree/HEAD/packages/pg).


Updates `@anthropic-ai/sdk` from 0.116.0 to 0.120.0
- [Release notes](https://github.com/anthropics/anthropic-sdk-typescript/releases)
- [Changelog](https://github.com/anthropics/anthropic-sdk-typescript/blob/main/CHANGELOG.md)
- [Commits](https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.116.0...sdk-v0.120.0)

Updates `js-yaml` from 5.2.3 to 5.3.0
- [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodeca/js-yaml/compare/5.2.3...5.3.0)

Updates `pg` from 8.22.0 to 8.23.0
- [Changelog](https://github.com/brianc/node-postgres/blob/master/CHANGELOG.md)
- [Commits](https://github.com/brianc/node-postgres/commits/pg@8.23.0/packages/pg)

---
updated-dependencies:
- dependency-name: "@anthropic-ai/sdk"
  dependency-version: 0.120.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-minor-updates
- dependency-name: js-yaml
  dependency-version: 5.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-minor-updates
- dependency-name: pg
  dependency-version: 8.23.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-minor-updates
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps-dev): bump the dev-minor-updates group across 1 directory with 10 updates (#1323)

Bumps the dev-minor-updates group with 10 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [@codemirror/commands](https://github.com/codemirror/commands) | `6.10.4` | `6.11.0` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `26.1.2` | `26.2.0` |
| [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react) | `6.0.5` | `6.1.0` |
| [electron](https://github.com/electron/electron) | `43.2.0` | `43.4.1` |
| [globals](https://github.com/sindresorhus/globals) | `17.9.0` | `17.11.0` |
| [i18next](https://github.com/i18next/i18next) | `26.3.6` | `26.4.0` |
| [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) | `1.28.0` | `1.33.0` |
| [react-hook-form](https://github.com/react-hook-form/react-hook-form) | `7.84.0` | `7.85.0` |
| [react-pdf](https://github.com/wojtekmaj/react-pdf/tree/HEAD/packages/react-pdf) | `10.4.1` | `10.5.0` |
| [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) | `8.66.0` | `8.67.0` |



Updates `@codemirror/commands` from 6.10.4 to 6.11.0
- [Changelog](https://github.com/codemirror/commands/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codemirror/commands/commits)

Updates `@types/node` from 26.1.2 to 26.2.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@vitejs/plugin-react` from 6.0.5 to 6.1.0
- [Release notes](https://github.com/vitejs/vite-plugin-react/releases)
- [Changelog](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite-plugin-react/commits/plugin-react@6.1.0/packages/plugin-react)

Updates `electron` from 43.2.0 to 43.4.1
- [Release notes](https://github.com/electron/electron/releases)
- [Commits](https://github.com/electron/electron/compare/v43.2.0...v43.4.1)

Updates `globals` from 17.9.0 to 17.11.0
- [Release notes](https://github.com/sindresorhus/globals/releases)
- [Commits](https://github.com/sindresorhus/globals/compare/v17.9.0...v17.11.0)

Updates `i18next` from 26.3.6 to 26.4.0
- [Release notes](https://github.com/i18next/i18next/releases)
- [Changelog](https://github.com/i18next/i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next/compare/v26.3.6...v26.4.0)

Updates `lucide-react` from 1.28.0 to 1.33.0
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/1.33.0/packages/lucide-react)

Updates `react-hook-form` from 7.84.0 to 7.85.0
- [Release notes](https://github.com/react-hook-form/react-hook-form/releases)
- [Changelog](https://github.com/react-hook-form/react-hook-form/blob/master/CHANGELOG.md)
- [Commits](https://github.com/react-hook-form/react-hook-form/compare/v7.84.0...v7.85.0)

Updates `react-pdf` from 10.4.1 to 10.5.0
- [Release notes](https://github.com/wojtekmaj/react-pdf/releases)
- [Commits](https://github.com/wojtekmaj/react-pdf/commits/v10.5.0/packages/react-pdf)

Updates `typescript-eslint` from 8.66.0 to 8.67.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.67.0/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: "@codemirror/commands"
  dependency-version: 6.11.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: "@types/node"
  dependency-version: 26.2.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: "@vitejs/plugin-react"
  dependency-version: 6.1.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: electron
  dependency-version: 43.4.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: globals
  dependency-version: 17.11.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: i18next
  dependency-version: 26.4.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: lucide-react
  dependency-version: 1.33.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: react-hook-form
  dependency-version: 7.85.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: react-pdf
  dependency-version: 10.5.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: typescript-eslint
  dependency-version: 8.67.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore: sync Crowdin translations

* Update redirect-issues workflow configuration

Updated the workflow to change the runner and modify the issue response message.

* chore: sync Crowdin translations

* fix: use i18n for host status tooltip labels (#1265)

* fix: add missing hosts.status.* locale keys (fixes #1265)

* fix: add hosts.status.* translation keys for i18n tooltip

The buildStatusTooltip function calls t("hosts.status.available"), t("hosts.status.reachable"), t("hosts.status.offline"), and t("hosts.status.monitoringDisabled"), but the locale file only had "status": "Status" as a flat string.

Replaced with a status object containing all four keys plus a "label" key preserving the original "Status" string.

* fix: restore final newline in en.json

Requested by ZacharyZcR in review feedback.

* test: assert translated labels in buildStatusTooltip

Per review feedback from ZacharyZcR: add focused tests that exercise
buildStatusTooltip with a translator and assert the rendered labels
rather than key paths. Covers all three status values, monitoring
disabled, protocol list, and the no-key-path regression guard.

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: LukeGus <bugattiguy527@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Luke Gustafson <88517757+LukeGus@users.noreply.github.com>
Co-authored-by: ZacharyZcR <payasonorahc@protonmail.com>

* fix(workspaces): fall back when randomUUID is unavailable (#1397)

* fix(terminal): preserve macOS Alt digit characters (#1398)

* fix(ssh): verify resolved server host identity (#1419)

* fix: add principals to Termix ID certificates (#1421)

* chore: sync Crowdin translations

* chore(deps): bump the prod-minor-updates group across 1 directory with 3 updates (#1325)

Bumps the prod-minor-updates group with 3 updates in the / directory: [@anthropic-ai/sdk](https://github.com/anthropics/anthropic-sdk-typescript), [js-yaml](https://github.com/nodeca/js-yaml) and [pg](https://github.com/brianc/node-postgres/tree/HEAD/packages/pg).


Updates `@anthropic-ai/sdk` from 0.116.0 to 0.120.0
- [Release notes](https://github.com/anthropics/anthropic-sdk-typescript/releases)
- [Changelog](https://github.com/anthropics/anthropic-sdk-typescript/blob/main/CHANGELOG.md)
- [Commits](https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.116.0...sdk-v0.120.0)

Updates `js-yaml` from 5.2.3 to 5.3.0
- [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodeca/js-yaml/compare/5.2.3...5.3.0)

Updates `pg` from 8.22.0 to 8.23.0
- [Changelog](https://github.com/brianc/node-postgres/blob/master/CHANGELOG.md)
- [Commits](https://github.com/brianc/node-postgres/commits/pg@8.23.0/packages/pg)

---
updated-dependencies:
- dependency-name: "@anthropic-ai/sdk"
  dependency-version: 0.120.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-minor-updates
- dependency-name: js-yaml
  dependency-version: 5.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-minor-updates
- dependency-name: pg
  dependency-version: 8.23.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-minor-updates
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps-dev): bump the dev-minor-updates group across 1 directory with 10 updates (#1323)

Bumps the dev-minor-updates group with 10 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [@codemirror/commands](https://github.com/codemirror/commands) | `6.10.4` | `6.11.0` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `26.1.2` | `26.2.0` |
| [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react) | `6.0.5` | `6.1.0` |
| [electron](https://github.com/electron/electron) | `43.2.0` | `43.4.1` |
| [globals](https://github.com/sindresorhus/globals) | `17.9.0` | `17.11.0` |
| [i18next](https://github.com/i18next/i18next) | `26.3.6` | `26.4.0` |
| [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) | `1.28.0` | `1.33.0` |
| [react-hook-form](https://github.com/react-hook-form/react-hook-form) | `7.84.0` | `7.85.0` |
| [react-pdf](https://github.com/wojtekmaj/react-pdf/tree/HEAD/packages/react-pdf) | `10.4.1` | `10.5.0` |
| [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) | `8.66.0` | `8.67.0` |



Updates `@codemirror/commands` from 6.10.4 to 6.11.0
- [Changelog](https://github.com/codemirror/commands/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codemirror/commands/commits)

Updates `@types/node` from 26.1.2 to 26.2.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@vitejs/plugin-react` from 6.0.5 to 6.1.0
- [Release notes](https://github.com/vitejs/vite-plugin-react/releases)
- [Changelog](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite-plugin-react/commits/plugin-react@6.1.0/packages/plugin-react)

Updates `electron` from 43.2.0 to 43.4.1
- [Release notes](https://github.com/electron/electron/releases)
- [Commits](https://github.com/electron/electron/compare/v43.2.0...v43.4.1)

Updates `globals` from 17.9.0 to 17.11.0
- [Release notes](https://github.com/sindresorhus/globals/releases)
- [Commits](https://github.com/sindresorhus/globals/compare/v17.9.0...v17.11.0)

Updates `i18next` from 26.3.6 to 26.4.0
- [Release notes](https://github.com/i18next/i18next/releases)
- [Changelog](https://github.com/i18next/i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next/compare/v26.3.6...v26.4.0)

Updates `lucide-react` from 1.28.0 to 1.33.0
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/1.33.0/packages/lucide-react)

Updates `react-hook-form` from 7.84.0 to 7.85.0
- [Release notes](https://github.com/react-hook-form/react-hook-form/releases)
- [Changelog](https://github.com/react-hook-form/react-hook-form/blob/master/CHANGELOG.md)
- [Commits](https://github.com/react-hook-form/react-hook-form/compare/v7.84.0...v7.85.0)

Updates `react-pdf` from 10.4.1 to 10.5.0
- [Release notes](https://github.com/wojtekmaj/react-pdf/releases)
- [Commits](https://github.com/wojtekmaj/react-pdf/commits/v10.5.0/packages/react-pdf)

Updates `typescript-eslint` from 8.66.0 to 8.67.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.67.0/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: "@codemirror/commands"
  dependency-version: 6.11.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: "@types/node"
  dependency-version: 26.2.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: "@vitejs/plugin-react"
  dependency-version: 6.1.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: electron
  dependency-version: 43.4.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: globals
  dependency-version: 17.11.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: i18next
  dependency-version: 26.4.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: lucide-react
  dependency-version: 1.33.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: react-hook-form
  dependency-version: 7.85.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: react-pdf
  dependency-version: 10.5.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: typescript-eslint
  dependency-version: 8.67.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore: sync Crowdin translations

* Update redirect-issues workflow configuration

Updated the workflow to change the runner and modify the issue response message.

* chore: sync Crowdin translations

* Add Hetzner logo and referral link to README

Added Hetzner logo with a referral link to README.

* Fix Hetzner logo URL in README.md

* chore: pull sponsor logos from the docs site

* fix: add principals to Termix ID certificates

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: LukeGus <bugattiguy527@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Luke Gustafson <88517757+LukeGus@users.noreply.github.com>
Co-authored-by: ZacharyZcR <payasonorahc@protonmail.com>

* fix(deps): resolve transitive security advisories (#1412)

* chore: sync Crowdin translations

* chore(deps): bump the prod-minor-updates group across 1 directory with 3 updates (#1325)

Bumps the prod-minor-updates group with 3 updates in the / directory: [@anthropic-ai/sdk](https://github.com/anthropics/anthropic-sdk-typescript), [js-yaml](https://github.com/nodeca/js-yaml) and [pg](https://github.com/brianc/node-postgres/tree/HEAD/packages/pg).


Updates `@anthropic-ai/sdk` from 0.116.0 to 0.120.0
- [Release notes](https://github.com/anthropics/anthropic-sdk-typescript/releases)
- [Changelog](https://github.com/anthropics/anthropic-sdk-typescript/blob/main/CHANGELOG.md)
- [Commits](https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.116.0...sdk-v0.120.0)

Updates `js-yaml` from 5.2.3 to 5.3.0
- [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodeca/js-yaml/compare/5.2.3...5.3.0)

Updates `pg` from 8.22.0 to 8.23.0
- [Changelog](https://github.com/brianc/node-postgres/blob/master/CHANGELOG.md)
- [Commits](https://github.com/brianc/node-postgres/commits/pg@8.23.0/packages/pg)

---
updated-dependencies:
- dependency-name: "@anthropic-ai/sdk"
  dependency-version: 0.120.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-minor-updates
- dependency-name: js-yaml
  dependency-version: 5.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-minor-updates
- dependency-name: pg
  dependency-version: 8.23.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-minor-updates
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps-dev): bump the dev-minor-updates group across 1 directory with 10 updates (#1323)

Bumps the dev-minor-updates group with 10 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [@codemirror/commands](https://github.com/codemirror/commands) | `6.10.4` | `6.11.0` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `26.1.2` | `26.2.0` |
| [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react) | `6.0.5` | `6.1.0` |
| [electron](https://github.com/electron/electron) | `43.2.0` | `43.4.1` |
| [globals](https://github.com/sindresorhus/globals) | `17.9.0` | `17.11.0` |
| [i18next](https://github.com/i18next/i18next) | `26.3.6` | `26.4.0` |
| [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) | `1.28.0` | `1.33.0` |
| [react-hook-form](https://github.com/react-hook-form/react-hook-form) | `7.84.0` | `7.85.0` |
| [react-pdf](https://github.com/wojtekmaj/react-pdf/tree/HEAD/packages/react-pdf) | `10.4.1` | `10.5.0` |
| [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) | `8.66.0` | `8.67.0` |



Updates `@codemirror/commands` from 6.10.4 to 6.11.0
- [Changelog](https://github.com/codemirror/commands/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codemirror/commands/commits)

Updates `@types/node` from 26.1.2 to 26.2.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@vitejs/plugin-react` from 6.0.5 to 6.1.0
- [Release notes](https://github.com/vitejs/vite-plugin-react/releases)
- [Changelog](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite-plugin-react/commits/plugin-react@6.1.0/packages/plugin-react)

Updates `electron` from 43.2.0 to 43.4.1
- [Release notes](https://github.com/electron/electron/releases)
- [Commits](https://github.com/electron/electron/compare/v43.2.0...v43.4.1)

Updates `globals` from 17.9.0 to 17.11.0
- [Release notes](https://github.com/sindresorhus/globals/releases)
- [Commits](https://github.com/sindresorhus/globals/compare/v17.9.0...v17.11.0)

Updates `i18next` from 26.3.6 to 26.4.0
- [Release notes](https://github.com/i18next/i18next/releases)
- [Changelog](https://github.com/i18next/i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next/compare/v26.3.6...v26.4.0)

Updates `lucide-react` from 1.28.0 to 1.33.0
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/1.33.0/packages/lucide-react)

Updates `react-hook-form` from 7.84.0 to 7.85.0
- [Release notes](https://github.com/react-hook-form/react-hook-form/releases)
- [Changelog](https://github.com/react-hook-form/react-hook-form/blob/master/CHANGELOG.md)
- [Commits](https://github.com/react-hook-form/react-hook-form/compare/v7.84.0...v7.85.0)

Updates `react-pdf` from 10.4.1 to 10.5.0
- [Release notes](https://github.com/wojtekmaj/react-pdf/releases)
- [Commits](https://github.com/wojtekmaj/react-pdf/commits/v10.5.0/packages/react-pdf)

Updates `typescript-eslint` from 8.66.0 to 8.67.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.67.0/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: "@codemirror/commands"
  dependency-version: 6.11.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: "@types/node"
  dependency-version: 26.2.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: "@vitejs/plugin-react"
  dependency-version: 6.1.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: electron
  dependency-version: 43.4.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: globals
  dependency-version: 17.11.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: i18next
  dependency-version: 26.4.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: lucide-react
  dependency-version: 1.33.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: react-hook-form
  dependency-version: 7.85.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: react-pdf
  dependency-version: 10.5.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: typescript-eslint
  dependency-version: 8.67.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore: sync Crowdin translations

* Update redirect-issues workflow configuration

Updated the workflow to change the runner and modify the issue response message.

* chore: sync Crowdin translations

* Add Hetzner logo and referral link to README

Added Hetzner logo with a referral link to README.

* Fix Hetzner logo URL in README.md

* chore: pull sponsor logos from the docs site

* fix(deps): resolve transitive security advisories

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: LukeGus <bugattiguy527@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Luke Gustafson <88517757+LukeGus@users.noreply.github.com>

* fix(sync): map nested host parent references (#1418)

* fix(metrics): surface SSH host key changes (#1404)

* fix(guacamole): coalesce VNC wheel floods and label meta keys by device (#1385)

High-latency proxies like Cloudflare queue guacamole-common-js scroll
clicks so the desktop keeps crawling after the user stops. Cap in-flight
wheel buttons, and show Super/Cmd in the VNC toolbar on non-Windows clients.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: ZacharyZcR <zacharyzcr1984@gmail.com>

* fix(file-manager): keep downloaded files inside the selected local folder

Remote file names were turned into local destinations by splitting the
relative remote path on "/" and concatenating each name with the platform
separator. A POSIX file name may contain "\", ":" or end in a dot, so on
Windows a remote "..\outside.txt" downloaded into C:\Downloads\selected was
normalised to C:\Downloads\outside.txt - outside the folder the user picked,
even with overwrite disabled. The main process only normalised destPath and
never checked it against the selected root.

Two independent layers now enforce containment:

Renderer (local-transfer-utils.ts)
- `assertSafeLocalComponent(name, separator)` validates each remote path
  component for the destination platform: never empty, "." or "..", never
  "/" or NUL; on Windows (separator "\") additionally no "\ : * ? " < > |",
  no control characters, no trailing dot/space, no reserved device names
  (CON, NUL, COM1...). Backslashes stay legal on macOS/Linux, where they are
  ordinary file-name characters and the result remains inside the folder.
- `buildLocalDestination(localDir, relativePath, separator)` joins the
  validated components and asserts the result is strictly under localDir
  (case-insensitive on Windows).
- useLocalTransfers builds every file and directory destination through it.
  Items that fail are skipped before any filesystem call and reported
  ("Skipped N item(s) whose names cannot be used on this computer").

Main process (electron/local-files.cjs)
- `assertWithinRoot(rootPath, candidate, pathImpl)` resolves + normalises
  both paths and refuses anything that is the root itself, escapes it
  (".." after normalisation), is absolute relative to it (another drive,
  UNC) or contains empty/".." segments. `pathImpl` is injectable so the
  Windows rules run in tests on any OS.
- downloadToLocal requires `rootPath` (the selected folder) and checks the
  destination before the request is made or any file is created; the
  ensure-dir handler applies the same check when a root is passed (used for
  the directory skeleton of downloaded trees).
- LocalDownloadRequest / downloadSessionFileToLocal / ensureLocalDirectory
  carry the root.

Tests
- Renderer: ordinary nested folders on Windows; backslash traversal in a
  POSIX name; absolute, drive-qualified and UNC names; reserved names,
  trailing dots/spaces, control chars; POSIX traversal rejected while a
  POSIX-legal backslash name is kept inside the folder.
- Main process (path.win32): nested destinations accepted incl. case
  differences; "selected\..\outside.txt" refused; other drive / UNC /
  sibling folder refused; missing root refused; end-to-end handler test that
  a POSIX "../outside.txt" download and an escaping ensure-dir are refused
  before any network traffic or disk write.

* feat(file-manager): right-click context menu for the local pane

Mirrors the remote grid's menu for the user's own disk. On an entry (or
the current multi-selection): Open / Open folder, Upload to server,
Reveal in Finder/Explorer, Rename (inline, F2), Copy Path, Move to Trash
(confirmation toast, Del). On the background: New Folder, New File,
Reveal, Show/Hide hidden files, Refresh (F5). Enter opens, Cmd/Ctrl+A
selects all, Escape clears the selection.

Deletion goes through shell.trashItem so it lands in the OS Trash and is
recoverable; rename and create refuse names containing path separators
and never overwrite an existing entry.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013Bn6K6xNAihgWZ5fMVWt1W

* feat(file-manager): resizable list-view columns in both panes

Drag the boundary at the left edge of a column header (Modified, Owner,
Size, Permissions on the remote grid; Modified, Size, Kind in the local
pane) to change its width; the Name column takes whatever is left.
Double-click a handle to reset that column. Widths are remembered per
pane in localStorage. Finishing a drag over a sortable header no longer
toggles the sort.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013Bn6K6xNAihgWZ5fMVWt1W

* feat(file-manager): pinned ".." parent entry in both panes

Both the remote grid (list, grid and empty-folder states) and the local
pane show a Termius-style ".." row pinned above the entries whenever the
current folder has a parent. Double-clicking it goes up one level. It is
also a drop target: local files dropped on it upload into the parent
folder, remote rows dragged onto it move there, and remote items dropped
on the local pane's ".." download into the parent folder.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013Bn6K6xNAihgWZ5fMVWt1W

* feat(file-manager): show/hide list-view columns from the header

Right-click a list-view header (remote grid or local pane) to open a
Columns menu and tick/untick Modified, Owner, Size, Permissions (remote)
or Modified, Size, Kind (local). Hidden columns leave the grid template
entirely so the Name column gets the space back; at least one optional
column always stays on. The choice is remembered per pane alongside the
column widths.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013Bn6K6xNAihgWZ5fMVWt1W

* feat(file-manager): sidebar toggle works on desktop too

The toolbar's sidebar button now shows/hides the directories panel on
desktop (persisted), while below md it still opens the mobile overlay.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013Bn6K6xNAihgWZ5fMVWt1W

* feat(file-manager): resizable directories sidebar

The Trash/Directories sidebar can now be resized by dragging its right
edge (160px minimum, up to 40% of the row); double-click the handle to
restore the default 224px. The width is remembered. The same handle and
persisted-width hook now also drive the local pane divider, replacing the
inline implementation.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013Bn6K6xNAihgWZ5fMVWt1W

* fix(metrics): support macOS/WIN hosts in stats collection (#1430)

* fix(metrics): support macOS hosts in stats collection

Host metrics collectors only ever ran Linux commands (/proc/*, ip,
GNU df flags), so any macOS host always reported 0%/null for
cpu, memory, uptime, network and disk. Detect the host platform
once per poll and use vm_stat, sysctl, top, ifconfig and netstat
on Darwin hosts instead.

* fix(metrics): support Windows hosts in stats collection

RDP/VNC hosts running Windows hit the same problem as macOS did:
no /proc, no BSD tools, not even uname. Route CPU, memory, uptime,
network and disk through PowerShell (WMI/CIM) when the host is
detected as Windows, using -EncodedCommand so there's no cmd.exe
quoting to fight with.

* fix(metrics): use real macOS df/mount for disk collection

BSD df's -T flag filters by filesystem type instead of printing one
like GNU df does, so the previous macOS disk path was still running
a GNU-only command and coming back empty. Now uses df -Pk plus mount
output to build the filesystem type/percent list, filtering out the
noisy APFS system volumes and devfs/autofs mounts. Verified on an
M4 MacBook running the latest macOS - disk usage now reports correctly.

* feat(file-manager): Termius-style Local | Remote dual pane with drag-and-drop transfers (desktop) (#1413)

Integrate the reviewed change and its maintainer fixes into dev-2.8.0.

Validated with focused regression tests, type-check, lint, formatting, build, and the PR Check database jobs.

* fix(terminal): persist Ctrl+/- font zoom so it survives option refreshes (#1399)

Integrate the reviewed change and its maintainer fixes into dev-2.8.0.

Validated with focused regression tests, type-check, lint, formatting, build, and the PR Check database jobs.

* Fix macOS terminal packaging and keyboard shortcuts. (#1417)

Integrate the reviewed change and its maintainer fixes into dev-2.8.0.

Validated with focused regression tests, type-check, lint, formatting, build, and the PR Check database jobs.

* fix(auth): skip TOTP only after verified WebAuthn user verification (#1420)

Integrate the reviewed change and its maintainer fixes into dev-2.8.0.

Validated with focused regression tests, type-check, lint, formatting, build, and the PR Check database jobs.

* feat(hosts): add per-host Web Endpoints (direct or SSH-tunnelled web UIs) (#1416)

* test: provide an in-memory localStorage for the vitest environment

jsdom in this project ships without a localStorage global, so every suite
that touched storage threw "Cannot read properties of undefined" during
setup and failed wholesale -- 119 tests across 15 files, none of them
actual product defects.

Node only supplies localStorage with --localstorage-file, which persists to
disk and is shared across test files. A per-process in-memory Storage is
what tests want, so define one (plus sessionStorage) when the global is
absent, alongside the existing matchMedia shim.

Full suite goes from 15 failed files / 119 failed tests to 400 files and
2888 tests passing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fdjjsdaz6aFMyJr4h3Y6qj

* feat(web-endpoints): add endpoint types and URL resolution

First step of per-host Web Endpoints: a host declares web UIs it serves and
opens them either directly at the host's address or through an SSH forward
Termix establishes on demand.

This commit is pure logic with no I/O, so it needs no mocks to test.

resolveWebEndpointUrl expects an already-normalized path -- normalization is
the storage boundary's job (a later commit), and duplicating it here would
invite the two copies to drift.

separatedTunnelHost is the one part that is a security control rather than a
convenience. Cookies are keyed by host and ignore the port, and SameSite
computes "site" as scheme + registrable domain -- also ignoring the port. A
forward reached at the host string serving Termix is therefore same-site with
Termix, which leaks the session both ways: the framed service receives the jwt
cookie, and a Set-Cookie it returns lands in the jar Termix's own API calls
read from. So a tunnel URL resolves to a different loopback spelling than the
page's, and refuses outright when no alias exists. Only loopback literals
qualify -- a same-registrable-domain alias could still answer Set-Cookie with
a Domain attribute that reaches Termix.

The cookie-separation tests were verified to fail against a resolver that
returns the page host (4 failures), so they cannot pass vacuously.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* feat(web-endpoints): validate and normalize endpoint config

normalizeWebEndpoints is the enforcement point for values that reach an href
and an iframe src, so the editor's constraints are UX rather than security.
It drops any row it refuses instead of rejecting the whole host -- one bad
endpoint must not make a host unsaveable or unlistable.

Paths are checked for C0 controls and DEL by codepoint rather than by regex
character class: "\t//evil.example" defeats a startsWith("//") guard, because
the browser strips the control character and then follows the authority.

bindHost lands both in a TCP listener and in a URL authority, so it is
restricted to a bare host literal -- nothing carrying a scheme, port, path or
credentials survives. bindHost and localPort are ignored on a direct endpoint,
which never creates a forward.

parseWebUiConfig never throws. A malformed stored value yields an empty
endpoint list, so a half-written config cannot take out the whole host
listing -- which is what dockerConfig's bare JSON.parse does today.

The editor validator is a second implementation in a layer that cannot import
backend route modules. Its accompanying test runs BOTH implementations over
the same path and port samples, because drift here is invisible in the worst
way: the editor accepts a row, the normalizer silently drops it, and the
endpoint disappears on reload with no error. That agreement test was verified
to fail (4 cases) when the editor's control-character check is removed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* chore(db): migrate the shared_credential_secrets foreign key rename

Running `npm run schema:migrations` on an UNCHANGED schema emits these, so
they are pre-existing drift between schema.ts and drizzle/, not something this
branch introduced. Landing them alone, before the web-endpoint columns, so the
feature's own migration is reviewable without an unrelated table rebuild
sitting in the middle of it.

Both forms are a foreign-key constraint rename only. Postgres drops and
re-adds the constraint under a shorter name. SQLite has no ALTER for that, so
drizzle emits the standard table rebuild -- verified data-preserving: CREATE
lists 14 columns, INSERT...SELECT copies the same 14 in the same order, and
both indexes are recreated.

The SQLite file is in practice dead code: runRemoteMigrations throws for
sqlite, which builds its schema from db/index.ts instead. It is kept rather
than hand-trimmed because drizzle derives the meta snapshot from schema.ts
regardless, so trimming the .sql while the snapshot advances would make the
drift permanently invisible -- no future `generate` would re-emit it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* feat(db): add enable_web_ui and web_ui_config columns

Two columns on ssh_data mirroring the Docker pair. No show_web_ui_in_sidebar:
every existing showXInSidebar column is vestigial -- they appear only in
defaults, the export payload and tests, and gate no rendering -- so a fourth
dead column plus a migration buys nothing.

web_ui_config stores an object rather than a bare array so host-level web
settings can be added later without a second migration.

The column has to be declared in FOUR places, not one. SQLite never runs the
drizzle migrations at all (runRemoteMigrations throws for sqlite), so the live
default-dialect schema comes from hand-written DDL:

  1. db/schema.ts, then the two generated dialect schemas and the migrations
  2. db/index.ts CREATE TABLE -- fresh databases
  3. db/index.ts addColumnIfNotExists -- existing databases
  4. database.ts CREATE TABLE and its positional INSERT -- encrypted export

Missing 2 or 3 breaks every host write on the default dialect while the
migration file sits there looking correct.

Two guards, both watched failing first. bootstrap-matches-schema-columns boots
a real database and compares PRAGMA table_info against the drizzle definition
for every table -- it reported ssh_data.enable_web_ui and ssh_data.web_ui_config
missing before item 2/3 landed. A grep-based guard could not: db/index.ts
names columns as snake_case strings, never the camelCase the schema uses.

export-ddl-matches-schema-columns covers database.ts, which no booted database
reaches. It caught a real defect while being written: the two new columns went
into the INSERT list but the VALUES list still held 53 placeholders for 55
columns. Being positional, that shifts every later value by one. The
placeholder-count assertion is now permanent.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* feat(hosts): thread web endpoint config through host read and write paths

A host field has to be enumerated by hand in nine places here, and "added a
column, missed one update path" is this codebase's most repeated bug -- during
the first attempt at this feature a field was missed at one of these points
six separate times, each surfacing as a different mystery: endpoints that
saved but never appeared, config that vanished on reload.

Backend: host-normalizers (input type, CONNECT_LEVEL_FIELDS, boolean
normalization, parse block), host.ts (create, update, both read paths,
quick-connect defaults), host-bulk-routes (bulk update, import, reset).
Renderer: host-export-payload, HostManagerData's sshHostToHost, tabUtils'
hostToSSHHost, HostEditorData's form seed and payload builder. The three
renderer mappers copy field by field, so an unlisted field is silently
dropped -- which is how endpoints saved correctly and never appeared.

webUiConfig is parsed with parseWebUiConfig rather than a bare JSON.parse.
dockerConfig on the adjacent line uses a bare one, so a single malformed value
takes out the whole host listing; that is a bug to avoid copying, not a
convention to follow.

All three write paths now clear webUiConfig when the feature is disabled. They
disagreed before, and the export payload ships the config unconditionally -- so
a host disabled without clearing still exported its endpoint list (internal
hostnames, ports, paths) while the UI read as off, and re-enabling resurrected
stale endpoints.

webUiConfig is shared with connect-level recipients, unlike dockerConfig. A
connect-level recipient is already authorized to open these tunnels, so
withholding the config only breaks discovery while the flag advertises the
feature. Docker's precedent does not transfer: its tab works without its
config, whereas a web endpoint IS its config.

The enumeration guard asserts every one of the nine files mentions the web
endpoint field beside its Docker counterpart, and checks the Docker anchor is
present too so it cannot pass vacuously if a file is restructured.

The clear-on-disable assertion was rewritten after the first version passed
with the guard deleted -- a loose regex matched unrelated sites. Both halves
are now anchored on exact text and were watched failing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* feat(tunnel): report the real bound port, support idle close, reserve web:

Three changes the web endpoint open route depends on, plus the name
reservation that makes the scheme safe.

Real bound port. Under sourcePort 0 the kernel assigns the port, but the
runtime recorded the requested value -- so it advertised 0 and any caller
reusing it failed. It now records tcpServer.address().port.

Idle close, behind the new tunnelConfig.idleTimeoutMs. Web endpoint tunnels
are opened on demand and must not outlive their use. The timer lives inside
establishDirectTunnel because the socket set is only visible from that
closure, polls at min(30s, timeout) so "empty for N" means roughly that rather
than "empty at the instant of one N-spaced tick", and unrefs so it cannot hold
the process open. It calls cleanupTunnelResources rather than close(): close()
stops the listener but leaves the entry in activeTunnelRuntimes, so the open
route would keep handing out a port nothing is listening on.

Reserved names skip retry. handleDisconnect returns early for a "web:" name
after a forced cleanup. maxRetries: 0 would NOT achieve this -- the retry path
reads `maxRetries || 3`, so 0 falls through to 3. The cleanup is forced
because cleanupTunnelResources no-ops while tunnelConnecting holds the name,
and a web tunnel has no retry pass to self-heal a leaked runtime.

That early return carries an identity guard, which is the subtle one.
sourceClient.end() only STARTS an async teardown, so the SSH "close" event
lands after a reopen may already have registered a NEW runtime under the same
name. Acting by name alone would tear down the successor rather than the stale
tunnel -- surfacing as a 200 with a good port followed by a silent connection
reset and no error anywhere. handleDisconnect now takes the closing Client and
returns early when the registered runtime belongs to someone else. The idle
timer carries the same guard for the same reason.

/ssh/tunnel/connect now rejects a user-supplied "web:" name with 400.
validateTunnelConfig is no defence here: it returns true unconditionally for
any name that is not the legacy 6-part format, so an authenticated user could
otherwise create a real retry-configured tunnel that collides with a live web
endpoint forward and silently loses its own reconnect behaviour.

The manager tests run against a real TCP listener and real timers -- mixing
fake timers with real socket I/O is a known route to a hanging test. Both were
watched failing: reverting the bound port fails the port test, and swapping
cleanupTunnelResources for close() fails the idle test, which asserts the
ENTRY is gone rather than merely that the listener stopped.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* feat(tunnel): add the web endpoint open route

POST /ssh/tunnel/web-endpoint/open { hostId, endpointId } -> { port }.

The host is resolved through the user-scoped resolveHostById, so an
authenticated user cannot obtain a forward to a host id they do not own. The
endpoint is re-normalized out of storage rather than trusted: the stored value
predates any later tightening of the rules, and this is what a forward gets
built from. An enabled flag is required as well as a present endpoint -- a
bulk update that sends only { webUiConfig } can leave a configured endpoint on
a host whose UI reads as off everywhere.

Not gated to the desktop. The forward binds wherever this backend runs, as the
server tunnels feature does, and the endpoint's own bindHost decides whether
that is reachable from a browser.

endpointHost: "127.0.0.1" is load-bearing, not cosmetic. connectSSHTunnel
picks its strategy via shouldEstablishDirectTunnel -> isSingleHostTunnel, which
keys on endpointHost -- setting only targetHost selects a different path and
the forward never binds locally.

connectSSHTunnel never rejects, and its promise resolves right after
conn.connect() -- long before the SSH "ready" event populates
activeTunnelRuntimes. Awaited is not connected, so waitForTunnelSettled polls
the maps the manager already exports. Polling rather than adding a
promise-returning variant: every existing caller is fire-and-forget by design,
and changing that contract for one new caller is the larger blast radius.

A probe forwardOut runs before returning 200. Without it the route succeeds the
moment listen() does, and forwardOut is only attempted per inbound socket where
failure is swallowed -- so the likeliest real error, nothing listening on the
endpoint's port, reached the user as a blank frame and no message.

Staleness is validated at open, never on save: host save lives in the database
service and the runtimes live in the tunnel service, with no push between them.
On reuse the route compares a fingerprint covering the endpoint's target AND
the host's SSH identity, and reopens when it differs. An absent fingerprint
means reuse, not staleness -- a reserved-prefixed runtime can only have been
created here. Deletion, disabling and host removal then need no handling:
nothing reopens the tunnel, so it idles out.

Also closes an authorization gap this feature would otherwise have created.
/ssh/tunnel/disconnect and /ssh/tunnel/cancel checked ownership only inside
`if (config && config.sourceHostId)`, and web tunnels are deliberately absent
from tunnelConfigs -- so the check never ran for them. Host ids are small
sequential integers and endpoint ids are client-supplied, so the name is
guessable and any authenticated user could force-close another user's tunnel.
authorizeTunnelAction recovers the host id from the name and fails closed when
it cannot; the tests were watched failing against the old behaviour.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* feat(hosts): add the web endpoint client and per-origin certificate allowance

The client posts a path relative to tunnelApi's base, which already includes
/ssh -- a leading "/ssh" here resolves to /ssh/ssh/... and 404s on every call.
The test asserts that on the captured runtime argument rather than by scanning
source, so quoting style and indirection cannot fool it.

Backend error messages are preserved rather than collapsed. 502 is this
route's likeliest real failure and carries the actionable cause -- SSH auth
rejected, host unreachable, nothing listening on the target port -- and
handleApiError would replace all three with "Server error occurred". It stays
as the fallback for bodies that carry no string reason, so a body shaped
{ error: <object> } cannot reach the user as "[object Object]".

openWebEndpointExternally applies the same refusal gate as the embedded tab.
Opening in the real browser is not the safer path: the cookie jar is the
browser's either way, so a tunnel URL on the page's own host string leaks the
session exactly as a frame would. The refusal happens before the forward is
opened -- binding the port and then declining to navigate would be no
protection.

Certificate allowance covers the one case Electron's existing handling misses:
direct access to a HOSTNAME over https. isPrivateNetworkHost matches IP
literals only and sshData.ip has no IP validation, so https://nas.local:8006
fails the check and renders blank inside an iframe with no click-through --
Chromium offers no proceed option for subframes.

Three properties of that allowance are deliberate and now pinned by tests,
because each would otherwise be undone by a reasonable-looking simplification:

  - it is NOT wired into isInvalidCertificateAllowedForUrl, which also governs
    this process's own outbound TLS via getTlsVerificationOptions;
  - it is https-only, in both the check and the IPC handler, since a non-TLS
    origin in a TLS-error allowlist is meaningless and file:/ftp: must never
    be storable; and
  - entries carry a five-minute TTL refreshed on each registration. Main has
    no host-database access and cannot verify the renderer's claim that an
    origin is a configured endpoint, so the residual risk has to be a
    momentary window rather than one lasting until the app restarts.

The handler stores the parsed origin, never the caller's string, so a path or
wildcard cannot widen the allowance.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* feat(hosts): add the Web UI editor tab

Mounted as a Web UI sub-tab inside the SSH group, beside Docker, Tunnels,
Files and Host Metrics, and laid out as two SectionCards following the tunnels
editor: settings first, then the list it governs.

There is a deliberate asymmetry with the sidebar here. The sidebar entry will
appear on enableWebUi alone, because a direct endpoint needs no SSH -- but Web
UI is an SSH sub-tab, so a host with SSH disabled cannot configure endpoints at
all. That is the accepted behaviour and both halves are pinned by tests, so
neither gets "fixed" into agreement later.

tunnelAvailable is enableSsh && originIsLocal, resolved inside HostWebUiTab
rather than in HostEditor.tsx, which is already ~2600 lines. It is NOT gated on
isElectron(): the forward binds wherever the backend runs, exactly as the
server tunnels feature does. resolveConnectionOrigin is called with
connectionType "ssh" deliberately -- a tunnel endpoint always rides SSH, and
"ssh" avoids the guacamole special case that forces "remote" for
RDP/VNC/Telnet.

Three input details that each prevent a silent data loss:

  - the id generator falls back off crypto.randomUUID, which is undefined
    outside a secure context -- a plain-http web deployment is a first-class
    target for direct+external and would otherwise throw on "Add endpoint";
  - a new row gets a de-duplicated label, since labels are what identify an
    endpoint in the sidebar picker; and
  - the port field commits only a value the normalizer would keep. Number("")
    is 0, which the normalizer rejects, so clearing the field would otherwise
    write an endpoint that vanishes on save with no error.

The tunnel fields carry three warnings: a non-loopback bind exposes the
target's web UI unauthenticated to anyone who can reach the port; a loopback
bind on a remote backend cannot be reached from a browser at all; and a tunnel
reached at Termix's own hostname would hand the tunnelled service this
session. All three are shown while configuring rather than only when the tab
fails to load.

The unavailable-tunnel reason is shown whenever tunnelling is unavailable, not
only once a row asks for it -- a disabled dropdown option with no stated reason
reads as the control being broken.

Copy is reused verbatim from the previous iteration's reviewed strings rather
than reworded.

One test was written and then removed rather than kept: its name promised that
switching to tunnel access clears ignoreCert, but Radix Select needs pointer
APIs jsdom lacks, so the body only asserted the control existed. The clearing
is covered where it is enforced, in the normalizer.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* feat(hosts): open web endpoints from the sidebar and in a tab

One sidebar entry per host, never one per endpoint: a host may declare up to
16, and a row of 16 identical globes is unusable. With a single endpoint the
entry wears its label and acts directly; with several it carries no endpointId
and the click opens a picker -- a DropdownMenu in the tray, a DropdownMenuSub
in the Connect submenu.

The entry is gated on enableWebUi ALONE, unlike every neighbouring action,
which requires enableSsh. A direct endpoint needs no SSH; SSH matters only
per-endpoint, for tunnel access, which the open route enforces.

openTab gains a fourth optional parameter rather than overloading `restore`,
which means something else. What was actually broken for two endpoints on one
host was the LABEL -- tab ids are already `${name}-${type}-${Date.now()}`, so
they never collided. All existing call sites keep working.

The tab is passed the endpoint ID, not the endpoint object, so one deleted
while its tab is open renders a plain message instead of throwing.

Reload re-resolves and REMOUNTS. A direct endpoint's URL never changes and a
live tunnel returns the same port on every open, so setUrl(resolved) would be
a same-value setState that React bails out of, leaving the frame untouched --
Reload would silently do nothing in the two most common cases. A generation
counter folded into the iframe key fixes that and doubles as the staleness
guard for two resolutions landing out of order. The test captures the DOM node
before and after, and was watched failing against a url-only key.

PERSISTENT_TAB_TYPES is hoisted to module scope and exported so it can be
asserted on -- it was a local const inside the component and therefore
untestable. web-endpoint is deliberately excluded: an idle tunnel re-binds a
fresh kernel-assigned port, so a restored tab could never hold a valid URL.

Two notes on verification. `tsc -p tsconfig.json` passes vacuously in this
repo -- tsconfig.json is a solution file with project references and does
nothing without -b -- so `npm run type-check` (tsc -b --force) is the real
check; it caught two insertions that had landed in the wrong function. And the
one full-suite failure seen along the way was vault-signer-core, which passes
in isolation and on re-run, is untouched by this branch, and is a flake under
parallel load.

Lint: 0 errors, 102 warnings, identical to the baseline on a clean tree.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(tunnel): register the web endpoint route under its /ssh path

Every route in routes.ts registers the full "/ssh/tunnel/..." path -- nginx
proxies /ssh through with the path intact -- and the client resolves
"/tunnel/web-endpoint/open" against a baseURL that already ends in /ssh. The
unprefixed registration therefore 404'd every call.

No handler unit test could catch this: they call handleWebEndpointOpen
directly and never touch registration. It surfaced only on opening a real
tunnel against a deployed build, which is why that step exists.

Added a registration test that captures the paths passed to app.post, so the
invariant is checked without needing a server.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(hosts): apply session-cookie isolation to direct web endpoints

The cookie guard only covered tunnel access. `unreachableTunnelReason`
returned null for every `access: direct` endpoint, so WebEndpointTab framed
the host's own address unconditionally. With Termix served at
https://termix.example/ and a direct endpoint at https://termix.example:8443/,
the browser attaches Termix's `jwt` to the framed request -- cookies are keyed
by host and ignore the port -- and a `Set-Cookie` from that service lands in
the jar both auth middlewares read before the Authorization header.

Renames the helper to `webEndpointRefusalReason` so its scope is no longer
tunnel-only, and gives it the endpoint's target host. A direct endpoint is now
refused in a browser when that host shares Termix's cookie site, checked
BEFORE any navigation in both open paths (embedded tab and external window) --
refusing after framing would leak on the first request.

`sharesCookieSiteWithPage` treats an equal host as same-site (the jwt is set
host-only, so the port is irrelevant) and also a parent/sub domain, which a
`Set-Cookie: Domain=` from the target crosses. The suffix test is anchored on a
dot boundary so `eviltermix.example` does not pass as `termix.example`. A
precise eTLD+1 test would also catch sibling subdomains, but needs a public
suffix list this app does not bundle.

The desktop stays exempt: its session is Bearer-only with no `jwt` in the jar.

Also drops "or change this endpoint to Direct" from the tunnel refusal copy,
which pointed at the path that had this same leak.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: ZacharyZcR <payasonorahc@protonmail.com>

* fix(tunnel): preserve local status when remote names collide (#1431)

* fix(desktop): honor remote sync certificate setting (#1432)

* fix(file-manager): interpolate preview download filename (#1433)

* fix(automations): dispatch SSH login events to triggers (#1434)

* fix(hosts): preserve imported settings and remap jump hosts (#1435)

* fix(hosts): preserve terminal switches across JSON transfer

* fix(hosts): remap imported jump-host dependencies

* fix(ssh): preserve agent framing after unsupported extensions (#1436)

* fix(guacamole): return tokens before awaiting the client handshake (#1437)

* fix(sidebar): unmount the host tree while its panel is hidden (#1438)

* fix(terminal): leave macOS Option characters enabled by default (#1439)

* fix(dashboard): open the enabled remote desktop protocol (#1440)

* fix(version): preserve local version when update checks fail (#1441)

* fix(sftp): create uploaded directories without shell access (#1442)

* fix(desktop): honor explicit GPU acceleration opt-out (#1443)

* fix(desktop): exclude remote-only host IDs from local tab persistence (#1444)

* Enhance SFTP and terminal flows, stabilize desktop sync (#1377)

* feat: add electron sftp c2s and terminal ai flows

* fix: stabilize desktop sync and c2s tunnels

* Improve remote tunnels and SFTP transfer feedback

* chore: sync Crowdin translations

* chore(deps): bump the prod-minor-updates group across 1 directory with 3 updates (#1325)

Bumps the prod-minor-updates group with 3 updates in the / directory: [@anthropic-ai/sdk](https://github.com/anthropics/anthropic-sdk-typescript), [js-yaml](https://github.com/nodeca/js-yaml) and [pg](https://github.com/brianc/node-postgres/tree/HEAD/packages/pg).


Updates `@anthropic-ai/sdk` from 0.116.0 to 0.120.0
- [Release notes](https://github.com/anthropics/anthropic-sdk-typescript/releases)
- [Changelog](https://github.com/anthropics/anthropic-sdk-typescript/blob/main/CHANGELOG.md)
- [Commits](https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.116.0...sdk-v0.120.0)

Updates `js-yaml` from 5.2.3 to 5.3.0
- [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodeca/js-yaml/compare/5.2.3...5.3.0)

Updates `pg` from 8.22.0 to 8.23.0
- [Changelog](https://github.com/brianc/node-postgres/blob/master/CHANGELOG.md)
- [Commits](https://github.com/brianc/node-postgres/commits/pg@8.23.0/packages/pg)

---
updated-dependencies:
- dependency-name: "@anthropic-ai/sdk"
  dependency-version: 0.120.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-minor-updates
- dependency-name: js-yaml
  dependency-version: 5.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-minor-updates
- dependency-name: pg
  dependency-version: 8.23.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-minor-updates
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps-dev): bump the dev-minor-updates group across 1 directory with 10 updates (#1323)

Bumps the dev-minor-updates group with 10 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [@codemirror/commands](https://github.com/codemirror/commands) | `6.10.4` | `6.11.0` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `26.1.2` | `26.2.0` |
| [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react) | `6.0.5` | `6.1.0` |
| [electron](https://github.com/electron/electron) | `43.2.0` | `43.4.1` |
| [globals](https://github.com/sindresorhus/globals) | `17.9.0` | `17.11.0` |
| [i18next](https://github.com/i18next/i18next) | `26.3.6` | `26.4.0` |
| [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) | `1.28.0` | `1.33.0` |
| [react-hook-form](https://github.com/react-hook-form/react-hook-form) | `7.84.0` | `7.85.0` |
| [react-pdf](https://github.com/wojtekmaj/react-pdf/tree/HEAD/packages/react-pdf) | `10.4.1` | `10.5.0` |
| [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) | `8.66.0` | `8.67.0` |



Updates `@codemirror/commands` from 6.10.4 to 6.11.0
- [Changelog](https://github.com/codemirror/commands/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codemirror/commands/commits)

Updates `@types/node` from 26.1.2 to 26.2.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@vitejs/plugin-react` from 6.0.5 to 6.1.0
- [Release notes](https://github.com/vitejs/vite-plugin-react/releases)
- [Changelog](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite-plugin-react/commits/plugin-react@6.1.0/packages/plugin-react)

Updates `electron` from 43.2.0 to 43.4.1
- [Release notes](https://github.com/electron/electron/releases)
- [Commits](https://github.com/electron/electron/compare/v43.2.0...v43.4.1)

Updates `globals` from 17.9.0 to 17.11.0
- [Release notes](https://github.com/sindresorhus/globals/releases)
- [Commits](https://github.com/sindresorhus/globals/compare/v17.9.0...v17.11.0)

Updates `i18next` from 26.3.6 to 26.4.0
- [Release notes](https://github.com/i18next/i18next/releases)
- [Changelog](https://github.com/i18next/i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next/compare/v26.3.6...v26.4.0)

Updates `lucide-react` from 1.28.0 to 1.33.0
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/1.33.0/packages/lucide-react)

Updates `react-hook-form` from 7.84.0 to 7.85.0
- [Release notes](https://github.com/react-hook-form/react-hook-form/releases)
- [Changelog](https://github.com/react-hook-form/react-hook-form/blob/master/CHANGELOG.md)
- [Commits](https://github.com/react-hook-form/react-hook-form/compare/v7.84.0...v7.85.0)

Updates `react-pdf` from 10.4.1 to 10.5.0
- [Release notes](https://github.com/wojtekmaj/react-pdf/releases)
- [Commits](https://github.com/wojtekmaj/react-pdf/commits/v10.5.0/packages/react-pdf)

Updates `typescript-eslint` from 8.66.0 to 8.67.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.67.0/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: "@codemirror/commands"
  dependency-version: 6.11.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: "@types/node"
  dependency-version: 26.2.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: "@vitejs/plugin-react"
  dependency-version: 6.1.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: electron
  dependency-version: 43.4.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: globals
  dependency-version: 17.11.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: i18next
  dependency-version: 26.4.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: lucide-react
  dependency-version: 1.33.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: react-hook-form
  dependency-version: 7.85.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: react-pdf
  dependency-version: 10.5.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: typescript-eslint
  dependency-version: 8.67.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore: sync Crowdin translations

* Update redirect-issues workflow configuration

Updated the workflow to change the runner and modify the issue response message.

* test(sftp): verify local collection limit boundaries

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: LukeGus <bugattiguy527@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Luke Gustafson <88517757+LukeGus@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: ZacharyZcR <payasonorahc@protonmail.com>

* chore: increment ver

* fix: allow any origin by default when CORS_ALLOWED_ORIGINS is unset

* feat(file-manager): parallel local transfers (#1446)

Uploads from the Local pane (and downloads to it) ran strictly one file
after another. Batches of many small files were bound by per-file latency
rather than bandwidth.

- `runWithConcurrency(items, limit, worker, shouldStop)`: a bounded worker
  pool that dispatches in order, keeps at most `limit` transfers in flight,
  and stops dispatching once cancelled while letting in-flight items
  finish. Worker errors are handled by the worker (one failure never aborts
  the batch).
- useLocalTransfers: both directions go through the pool. Remote / local
  directory skeletons are still created up front, so file order does not
  matter. The batch runner now tracks a set of in-flight transfer ids
  (Cancel cancels all of them), sums bytes across in-flight transfers plus
  settled ones for the progress bar / speed, and shows how many files are
  moving at once.
- New preference "Simultaneous File Transfers" (1-8, default 4) in the
  profile settings, stored in localStorage
  (`termix:file-manager:transfer-concurrency`) and part of the storage
  snapshot. 1 restores the previous sequential behaviour; the hint suggests
  lowering it for servers that limit SFTP channels.
- Remote directories are created with the now-idempotent mkdir (#1442)
  without swallowing its errors, so a real failure stops the batch up
  front instead of surfacing as N per-file failures. When files do fail,
  the summary toast carries the first underlying reason (e.g. the
  backend's 401 message) instead of a bare "Upload failed".
- Tests: pool never exceeds the limit and drains everything, stops on
  cancel, tolerates a failing item, handles empty input; preference
  clamping and persistence; bridge-level concurrent uploads/downloads
  with a mid-flight cancel leave every other file intact and no partials.

Co-authored-by: Max <maxim@cogitate.ai>

* fix(sftp): complete streamed uploads and stop pre-parsing chunk bodies

* fix(desktop): stop setting Content-Length on local download requests

* fix(file-manager): keep drop overlays in view when the list is scrolled

* fix(file-manager): let remote rows be dropped on the local pane

* fix(desktop): authenticate local transfers with the renderer's token

* chore: update release notes

* chore: remove unused gitlab ci and argocd deploy configs

* chore: remove unused files

* feat: improve loading animation

* fix(shell): stop tab reorder from resetting terminals and tab indicator

Keep the tab-content portal order stable so reordering tabs doesn't
retrigger React's offscreen pass and dispose live terminals. Also stop
the active tab indicator from teleporting during a drag, and fix the
drag ghost's size/border mismatch.

* fix(shell): hand-roll the tab indicator instead of a shared layoutId

Framer's layoutId could measure the wrong tab's rect during a reorder
and land on an inactive tab, or leave a stray line visible mid-drag.
Now it reads the active tab's own DOM rect directly and hides while
dragging.

* fix(hosts): fix right-click menu position and unwanted tray expand

* chore: update release notes

* fix(terminal): stop autosuggestion ghost text overlapping typed input

Position was computed from cursorX before server echo landed, causing
a stale read that overlapped just-typed characters on fast local input.

* chore: update release notes for v2.8.0

* fix(sftp): rebuild transfer tab for web, fix menu offset bug

Drop the electron-only local mode and dead code, i18n all strings,
fix double progress toasts and a wrong pane refresh on move.
Fix context menus rendering offset due to a lingering CSS transform
from the tab-switch animation. Move SFTP next to SSH Tools in the rail.

* fix(file-manager): shrink oversized .. entry, navigate on single click

* fix: make select2 component use rounded corners

* fix: rebuild terminal AI assistant on the real backend

Removes the Electron-only Agent Mode/AI Command Helper that bypassed
admin/user gating and ran commands with no approval step. Replaces it
with a terminal-docked panel on the same gated backend as the AI tab,
adds a per-host toggle (off by default), moves it into the toolbar,
and fixes proposal ordering and run-in-terminal execution.

* fix(file-manager): remove duplicate borders in toolbar view toggle

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix: separate registration toggle from step ca settings

* fix: collab room bugs and add room deletion

Accent-colored new room button, fix fullscreen guest view layout and
duplicate view-only badges, self-heal stale presenter state, add
delete room for persistent rooms.

* refactor: move host-identity helpers to hosts core

Used by docker, file-manager, and terminal alike, so it belongs
at the hosts root instead of under terminal/.

* refactor: move host-session-status singleton to hosts core

metrics subscribed to terminal's private online/offline pub-sub
module. Moved to hosts core so both sides depend on a shared
module instead of metrics reaching into terminal. Marked the
subscribe call with PLUGIN-EVENT for the future event bus.

* refactor: split generic automation event notify out of metrics

notifyAutomationInternalEvent was in hosts/metrics/automation-bridge.ts
but is used by tunnel, host routes, user routes, and automations
engine itself, not just metrics. Moved it to hosts/automation-events.ts
so those callers depend on a shared module instead of metrics
internals. Left the metrics-specific notifiers in place.

* feat: add plugin system schema and repositories

Adds plugins, plugin_permission_grants, plugin_registries, and
plugin_install_counts tables plus their repositories. No routes or UI yet.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* feat: add runtime rail item and tab component registries for plugins

* feat: support runtime-registered permission groups

Adds register/unregister for plugin permission groups so the RBAC
catalog and validation can grow beyond the static list.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* feat: add plugin-api nginx route and dispatcher stub

* feat: add plugin manifest schema and validator

* chore: update release notes

* chore: update i18n for local/remote file manager

* feat: add toggle to show/hide app rail pin button

* feat(host-metrics): add NVIDIA GPU metrics card (#1452)

* feat(host-metrics): add NVIDIA GPU metrics card

Collect per-GPU utilization, VRAM, temperature, power, fan speed and
the processes using each GPU over SSH with nvidia-smi. The collector
exits immediately when nvidia-smi is missing, so hosts without a GPU
pay almost nothing per poll.

The GPU card is opt-in: it is available from the Add card tray but is
not part of new-host defaults or any UI preset. It shows live
sparklines for utilization and VRAM per GPU.

Adaptive polling now also watches GPU readings and the GPU process
count, so it no longer backs off on hosts where only the GPU is busy.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F2ctuPwiesLzhF6XQiozm8

* fix(host-metrics): draw sparklines from the first metrics sample

The first sample fetched when the tab connects was shown but never
added to the sparkline history, so every sparkline (CPU, memory, disk,
GPU) stayed empty until the second poll, a full metrics interval later
(about 35 s with the default 30 s interval). Record the first sample
like every later one, so the lines appear as soon as the tab loads.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F2ctuPwiesLzhF6XQiozm8

* Fix logical condition for memory percentage calculation

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Luke Gustafson <88517757+LukeGus@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* fix: annotate local transfer plan type to fix CI type-check

* fix: move connection toolbar settings to bottom of host editor general tab

* chore: add debug logging for macOS sharp packaging failure

Temporary diagnostic to find which phase drops @img/sharp-darwin-x64
from the packaged app. Revert once root cause is found.

* fix: correct macOS sharp verify script for universal build layout

electron-builder uses mergeASARs: false, so universal builds ship
app-x64.asar.unpacked and app-arm64.asar.unpacked side by side instead
of a single app.asar.unpacked. The verify script only checked the
single-asar path, so it always failed on universal/mas artifacts even
when packaging was correct.

* fix: update sharp verify test fixtures for universal build layout

The test built fake apps using the single app.asar.unpacked layout,
which doesn't match how universal builds are actually packaged now
(app-x64.asar.unpacked / app-arm64.asar.unpacked side by side).

* chore: update readme

* fix: guard against missing rooms array in collab list response

* fix: distinct guac connection log stages, RDP black screen before failure

* fix: proxy /collab routes in nginx configs

* fix: stop tab-switch flash and host metrics/proxmox reconnect

Tab DOM visibility now syncs before paint instead of after, and
switching tabs no longer tears down live metrics connections.

* fix: tab bar flashing, growing, and merged separators

Terminal tabs no longer flash when switching, the enter animation no
longer nudges layout size, and a stray transform on resting tabs no
longer causes the border between tabs to vanish at some zoom levels.

* fix: match select trigger height to inputs in web UI editor

* chore: lint, format, and bump version to 2.8.0

* chore: sync Crowdin translations for 2.8.0

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: ZacharyZcR <zacharyzcr1984@gmail.com>
Co-authored-by: Angad Singh <7099405+singhangadin@users.noreply.github.com>
Co-authored-by: Angad Singh <angad@singhangad.in>
Co-authored-by: Neo <54811660+neooriginal@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Wali Lambert <98448225+YatoVoid@users.noreply.github.com>
Co-authored-by: Nasif Rahman <44437976+nasif-naseef@users.noreply.github.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: vietanhtwdk <vietanhtruongwdk@gmail.com>
Co-authored-by: inontz <inontz@icloud.com>
Co-authored-by: inontz <inontz@users.noreply.github.com>
Co-authored-by: Max Serov <133950708+maxser0v@users.noreply.github.com>
Co-authored-by: Max <maxim@cogitate.ai>
Co-authored-by: ssmurfgg04-gif <ssmurfgg04@gmail.com>
Co-authored-by: ssmurfgg04-gif <232103099+ssmurfgg04-gif@users.noreply.github.com>
Co-authored-by: ZacharyZcR <payasonorahc@protonmail.com>
Co-authored-by: slsgzs-cloud <slsgzs@gmail.com>
Co-authored-by: anshtsolanki-sketch <anshtsolanki@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: tcezarl <tomescu.cezar.laurentiu@gmail.com>
Co-authored-by: Anton Priestley <anton@priestley.me>
Co-authored-by: Hakim M <hakimmarsudi@outlook.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Adel Alzubeir <14052842+Adelzu@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-09-20 14:56:39 -05:00

5105 lines
305 KiB
JSON
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"connection": {
"retryingIn": "Đang thử lại sau {{seconds}}giây ({{attempt}}/{{max}})",
"retryingNow": "Đang thử lại... ({{attempt}}/{{max}})",
"disconnected": "Không thể kết nối",
"reconnect": "Kết nối lại"
},
"termixId": {
"title": "Termix ID",
"loadFailed": "Tải Termix ID thất bại",
"claimTitle": "Nhận Termix ID của bạn",
"claimIntro": "Chọn một tên người dùng duy nhất. Khóa công khai SSH của bạn sẽ được công bố tại một URL công khai mà bạn có thể thêm vào tệp authorized_keys của bất kỳ máy chủ nào.",
"handleLabel": "Tên người dùng",
"handlePlaceholder": "alice",
"checking": "Đang kiểm tra…",
"available": "Có sẵn",
"taken": "Đã được sử dụng",
"invalidHandle": "Chỉ chữ thường, số, - và _",
"descriptionLabel": "Mô tả (tùy chọn)",
"descriptionPlaceholder": "Khóa laptop & điện thoại",
"create": "Tạo Termix ID",
"created": "Đã tạo Termix ID",
"createFailed": "Tạo Termix ID thất bại",
"deleteConfirm": "Xóa Termix ID và tất cả khóa đã công bố? Các máy chủ bạn đã cung cấp sẽ vẫn giữ khóa cho đến khi bạn xóa thủ công.",
"deleted": "Đã xóa Termix ID",
"deleteFailed": "Xóa Termix ID thất bại",
"copyFailed": "Sao chép thất bại",
"resolverUrlLabel": "URL phân giải công khai",
"provisionLabel": "Cung cấp máy chủ",
"publishTitle": "Công bố khóa công khai",
"generate": "Tạo",
"generateTooltip": "Tạo cặp khóa Ed25519 — công bố khóa công khai và tải khóa riêng về thiết bị của bạn",
"saveToVault": "Lưu vào Kho thông tin",
"keyPlaceholder": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5... user@host",
"labelPlaceholder": "Nhãn (tùy chọn)",
"add": "Thêm",
"importFromCredential": "Hoặc nhập từ một thông tin đăng nhập đã lưu",
"keyPublished": "Đã công bố khóa",
"addKeyFailed": "Thêm khóa thất bại",
"generatedSaved": "Đã tạo cặp khóa và lưu vào kho thông tin đăng nhập của bạn. Khóa riêng cũng đã được tải xuống.",
"generatedOnly": "Đã tạo cặp khóa — khóa riêng đã được tải xuống (chỉ hiển thị một lần).",
"generateFailed": "Tạo khóa thất bại",
"imported": "Đã nhập khóa từ thông tin đăng nhập",
"importFailed": "Nhập khóa thất bại",
"noKeys": "Chưa có khóa công khai được công bố.",
"keysTitle": "Khóa đã công bố",
"published": "Đã công bố",
"hidden": "Ẩn",
"keyRemoved": "Đã xóa khóa",
"removeKeyFailed": "Xóa khóa thất bại",
"updateKeyFailed": "Cập nhật khóa thất bại",
"fromVault": "Từ kho thông tin xác thực",
"linkedToTermixId": "Công bố qua Termix ID",
"selectCredential": "Chọn thông tin xác thực...",
"import": "Nhập",
"caTitle": "Cơ quan chứng thực",
"caIntro": "Tin cậy CA này trên máy chủ và nó chấp nhận mọi chứng chỉ do bạn ký. Xoay để thu hồi tất cả cùng lúc; chứng chỉ cũng tự hết hạn.",
"caEnable": "Bật CA",
"caEnabled": "Đã bật CA",
"caCreateFailed": "Bật CA thất bại",
"caPublicKeyLabel": "Khóa công khai CA",
"caTrustLabel": "Tin cậy trên máy chủ (chạy với quyền root)",
"caRotate": "Xoay",
"caRotateConfirm": "Xoay CA? Mọi chứng chỉ do CA này ký sẽ không còn được chấp nhận và phải được cấp lại.",
"caRotated": "Đã xoay CA — các chứng chỉ trước bị thu hồi",
"caRotateFailed": "Xoay CA thất bại",
"caDelete": "Gỡ bỏ CA",
"caDeleteConfirm": "Gỡ bỏ cơ quan chứng thực?",
"caDeleted": "Đã gỡ CA",
"caDeleteFailed": "Gỡ CA thất bại",
"caValidityLabel": "Hiệu lực chứng chỉ (ngày)",
"issueCert": "Chứng chỉ",
"issueCertTooltip": "Cấp chứng chỉ SSH cho khóa này, được ký bởi CA của bạn",
"certIssued": "Chứng chỉ đã được cấp và tải xuống",
"certIssueFailed": "Cấp chứng chỉ thất bại"
},
"credentials": {
"folders": "Thư mục",
"folder": "Thư mục",
"password": "Mật khẩu",
"key": "Khóa",
"sshPrivateKey": "Khóa riêng SSH",
"upload": "Tải lên",
"keyPassword": "Mật khẩu khóa",
"sshKey": "Khóa SSH",
"uploadPrivateKeyFile": "Tải lên tệp khóa riêng",
"searchCredentials": "Tìm kiếm chứng chỉ...",
"addCredential": "Thêm chứng chỉ",
"caCertificate": "Chứng chỉ CA (-cert.pub)",
"caCertificateDescription": "Tùy chọn: Tải lên hoặc dán tệp chứng chỉ do CA ký (ví dụ: id_ed25519-cert.pub). Cần khi máy chủ SSH của bạn sử dụng xác thực dựa trên chứng chỉ.",
"uploadCertFile": "Tải lên tệp -cert.pub",
"clearCert": "Xóa",
"certLoaded": "Đã tải chứng chỉ",
"certPublicKeyLabel": "Chứng chỉ CA",
"certTypeLabel": "Loại chứng chỉ",
"pasteOrUploadCert": "Dán hoặc tải lên chứng chỉ -cert.pub...",
"hasCaCert": "Có chứng chỉ CA",
"noCaCert": "Không có chứng chỉ CA",
"noPublicKeyAvailable": "Không có khóa công khai. Hãy mở trình chỉnh sửa chứng chỉ trước.",
"deployCommandCopied": "Đã sao chép lệnh triển khai",
"sortCredentials": "Sắp xếp chứng chỉ",
"sortDefault": "Thứ tự mặc định",
"sortNameAsc": "Tên (A → Z)",
"sortNameDesc": "Tên (Z → A)",
"sortUsernameAsc": "Tên người dùng (A → Z)",
"sortUsernameDesc": "Tên người dùng (Z → A)",
"filterCredentials": "Lọc chứng chỉ",
"filterClearAll": "Xóa bộ lọc",
"filterTypeGroup": "Loại",
"filterTypePassword": "Mật khẩu",
"filterTypeKey": "Khóa SSH",
"filterTagsGroup": "Thẻ",
"copyDeployCommand": "Sao chép lệnh triển khai",
"cloneCredentialAction": "Sao chép thông tin đăng nhập",
"clonedCredential": "Đã sao chép {{name}}",
"clonedCredentialName": "{{name}} (copy)",
"shareCredentialAction": "Chia sẻ thông tin đăng nhập",
"sharedBadge": "đã chia sẻ",
"sharedBy": "Được chia sẻ bởi {{owner}}",
"share": {
"title": "Chia sẻ \"{{name}}\"",
"description": "Người nhận sẽ nhận được bản sao mã hóa riêng của các thông tin bí mật. Bản sao này được làm mới mỗi khi thông tin xác thực thay đổi và bị xóa khi quyền chia sẻ bị thu hồi.",
"users": "Người dùng",
"roles": "Vai trò",
"searchPlaceholder": "Tìm kiếm...",
"permission": "Sự cho phép",
"levelUse": "Sử dụng",
"levelManage": "Quản lý",
"levelUseDesc": "Cách sử dụng: đính kèm thông tin xác thực vào máy chủ và kết nối. Bản thân thông tin bí mật sẽ được giữ kín.",
"levelManageDesc": "Quản lý: chỉnh sửa thông tin đăng nhập và chia sẻ với người khác.",
"expires": "Hết hạn",
"expiry": {
"never": "Không bao giờ",
"oneDay": "1 ngày",
"sevenDays": "7 ngày",
"thirtyDays": "30 ngày"
},
"currentAccess": "Đã chia sẻ với",
"revoke": "Thu hồi",
"shared": "Thông tin xác thực được chia sẻ",
"shareButton": "Chia sẻ"
},
"deleteCredentialAction": "Xóa thông tin đăng nhập",
"editCredentialAction": "Chỉnh sửa thông tin đăng nhập",
"failedToCloneCredential": "Không thể sao chép thông tin xác thực.",
"failedToDeleteCredential": "Không thể xóa thông tin đăng nhập",
"idBadge": "NHẬN DẠNG",
"keyBadge": "CHÌA KHÓA",
"passwordBadge": "Người khuyết tật",
"renameFolder": "Đổi tên thư mục",
"deleteFolder": "Xóa thư mục",
"deleteCredentialConfirm": "Xóa thông tin xác thực \"{{name}}\"?",
"deletedCredential": "Đã xóa {{name}}",
"deploySSHKeyTitle": "Triển khai khóa lên máy chủ",
"loadingCredentials": "Đang tải thông tin đăng nhập...",
"noCredentialsFound": "Không tìm thấy thông tin đăng nhập.",
"noCredentialsMatchSearch": "Không có thông tin đăng nhập nào khớp với tìm kiếm của bạn.",
"addCredentialBtn": "Thêm thông tin đăng nhập",
"failedToReorder": "Không thể sắp xếp lại thông tin xác thực",
"failedToMoveCredential": "Không thể chuyển thông tin xác thực.",
"sortManual": "Hướng dẫn sử dụng (kéo để sắp xếp lại)",
"customizeSidebar": "Tùy chỉnh thanh bên",
"customizeSidebarDescription": "Chọn cách hiển thị và hoạt động của danh sách thông tin đăng nhập.",
"customizeDensityTitle": "Tỉ trọng",
"densityComfortableDesc": "Một thông tin xác thực trên mỗi dòng, kèm theo chi tiết bổ sung.",
"densityCompactDesc": "Mỗi thông tin đăng nhập tương ứng với một dòng, đối với danh sách dài hơn.",
"displayDensityComfortable": "Thoải mái",
"displayDensityCompact": "Nhỏ gọn",
"customizeBehaviorTitle": "Hành vi",
"showCredentialTags": "Hiển thị thẻ",
"showCredentialTagsDesc": "Hiển thị thẻ trong danh sách thông tin xác thực",
"actionsVisibility": "Hành động xác thực",
"actionsVisibilityDesc": "Khi các nút kết nối và quản lý trên mỗi thông tin đăng nhập hiển thị",
"actionsAlways": "Luôn hiển thị",
"actionsOnly": "Chỉ cần kết nối, phần còn lại chỉ cần nhấp chuột.",
"actionsHover": "Hiển thị khi di chuột",
"actionsClick": "Hiển thị khi nhấp chuột",
"customizeSortHint": "Tùy chọn sắp xếp nằm trong menu sắp xếp trên thanh công cụ.",
"expandActions": "Mở rộng hành động",
"collapseActions": "Hành động thu gọn",
"backToHosts": "Trở lại trang Chủ nhà",
"backToCredentials": "Trở lại trang Thông tin đăng nhập",
"searchCredentialsPlaceholder": "Thông tin đăng nhập tìm kiếm…",
"deployDialogTitle": "Triển khai khóa SSH",
"deployDialogDesc": "Triển khai {{name}} vào authorized_keys của máy chủ.",
"targetHostLabel": "Máy chủ mục tiêu",
"selectHostOption": "Chọn máy chủ...",
"deployingBtn": "Đang triển khai...",
"deployBtn": "Triển khai",
"keyDeployedSuccess": "Khóa đã được triển khai thành công",
"failedToDeployKey": "Không thể triển khai khóa.",
"folderRenamedTo": "Thư mục được đổi tên thành \"{{name}}\"",
"failedToRenameFolder": "Không thể đổi tên thư mục.",
"arrangeUnlockedSwitchedToManual": "Đã chuyển sang chế độ sắp xếp thủ công để đơn hàng của bạn được giữ nguyên.",
"arrangeUnlocked": "Mở khóa chức năng kéo để sắp xếp lại."
},
"homepage": {
"title": "Trang chủ",
"addWidget": "Thêm widget",
"editWidget": "Sửa widget",
"deleteWidget": "Xóa",
"widgetTypes": "Loại widget",
"serviceLink": "Liên kết dịch vụ",
"folder": "Thư mục",
"clock": "Đồng hồ",
"notes": "Ghi chú",
"hostStatus": "Trạng thái máy chủ",
"bookmarkList": "Dấu trang",
"zoomIn": "Phóng to",
"zoomOut": "Thu nhỏ",
"resetView": "Đặt lại chế độ xem",
"lockLayout": "Khóa bố cục",
"unlockLayout": "Mở khóa bố cục",
"noWidgets": "Nhấp chuột phải hoặc nhấn + để thêm widget đầu tiên",
"openFullView": "Mở toàn màn hình",
"previewTitle": "Xem trước trang chủ",
"cancel": "Hủy",
"save": "Lưu",
"title_label": "Tiêu đề",
"widgetTitlePlaceholder": "Tiêu đề widget (tùy chọn)",
"url": "URL",
"imageUrl": "URL hình ảnh tùy chỉnh",
"imageUrlHint": "Để trống để tự động dùng favicon của trang",
"showImage": "Hiển thị hình ảnh",
"description": "Mô tả",
"color": "Màu sắc",
"icon": "Biểu tượng",
"expanded": "Mở rộng mặc định",
"timezone": "Múi giờ",
"invalidTimezone": "Múi giờ không hợp lệ. Hãy sử dụng tên IANA như America/New_York.",
"showSeconds": "Hiển thị giây",
"format12h": "12 giờ",
"format24h": "24 giờ",
"content": "Nội dung",
"backgroundColor": "Màu nền",
"host": "Máy chủ",
"showMetrics": "Hiển thị chỉ số",
"links": "Liên kết",
"addLink": "Thêm liên kết",
"linkLabel": "Nhãn",
"linkUrl": "URL",
"removeLink": "Xóa",
"categoryLinks": "Liên kết",
"categoryInfo": "Thông tin",
"categorySystem": "Hệ thống",
"widgetServiceLinkDesc": "Ô nhấp được để liên kết đến URL dịch vụ",
"widgetFolderDesc": "Hộp chứa để nhóm các widget liên quan",
"widgetClockDesc": "Đồng hồ trực tiếp với múi giờ tùy chỉnh",
"widgetNotesDesc": "Widget ghi chú markdown",
"widgetHostStatusDesc": "Hiển thị trực tiếp CPU, bộ nhớ và ổ đĩa cho máy chủ SSH",
"widgetBookmarkListDesc": "Danh sách liên kết nhanh",
"copyLink": "Sao chép liên kết",
"linkCopied": "Đã sao chép liên kết!",
"location": "Vị trí",
"temperatureUnit": "Đơn vị nhiệt độ",
"showForecast": "Hiển thị dự báo 3 ngày",
"scrolling": "Cho phép cuộn",
"feedUrl": "URL nguồn cấp",
"maxItems": "Số mục tối đa",
"showDescription": "Hiển thị mô tả",
"widgetWeatherName": "Thời tiết",
"widgetWeatherDesc": "Thời tiết trực tiếp cho mọi vị trí",
"widgetIframeName": "Nhúng iFrame",
"widgetIframeDesc": "Nhúng bất kỳ URL nào vào iframe",
"widgetRssName": "Nguồn RSS",
"widgetRssDesc": "Hiển thị các mục từ nguồn RSS hoặc Atom",
"dragToFolder": "Kéo widget vào đây hoặc dùng + để thêm",
"showDisk": "Hiển thị mức sử dụng ổ đĩa",
"addToFolder": "Thêm widget vào thư mục",
"noHostSelected": "Chưa chọn máy chủ",
"metricsNotAvailable": "Chỉ số không khả dụng",
"selectHost": "Chọn máy chủ...",
"displayedMetrics": "Chỉ số hiển thị",
"metricCpu": "CPU",
"metricMemory": "Bộ nhớ",
"metricDisk": "Đĩa",
"metricUptime": "Thời gian hoạt động",
"metricSystem": "Hệ thống",
"metricOs": "Hệ điều hành",
"metricKernel": "Nhân",
"metricHostname": "Tên máy chủ",
"metricNetwork": "Mạng",
"metricProcesses": "Tiến trình",
"metricProcessesTotal": "tổng",
"metricProcessesRunning": "đang chạy",
"categoryMonitoring": "Giám sát",
"loading": "Đang tải...",
"noData": "Không có dữ liệu",
"allClear": "Tất cả ổn",
"acknowledgeAlert": "Xác nhận",
"noPingUrls": "Chưa cấu hình URL",
"pingLabel": "Nhãn",
"addPingUrl": "Thêm URL",
"showLatency": "Hiển thị độ trễ",
"refreshInterval": "Chu kỳ làm mới",
"seconds": "giây",
"filterActivityTypes": "Loại hoạt động",
"filterTypesHint": "Để trống để hiển thị tất cả",
"showTimestamp": "Hiển thị dấu thời gian",
"uptimeUnavailable": "Không có thời gian hoạt động",
"uptimeLabel": "Thời gian hoạt động",
"overviewVersion": "Phiên bản",
"overviewUpdate": "Đã cập nhật mới nhất",
"overviewUpdateLabel": "Cập nhật",
"overviewUpdateAvailable": "Có bản cập nhật",
"overviewDatabase": "Cơ sở dữ liệu",
"overviewUptime": "Thời gian hoạt động",
"noHosts": "Chưa cấu hình máy chủ nào",
"hostGridHosts": "Máy chủ",
"hostGridAllHint": "Để trống để hiển thị tất cả máy chủ",
"columns": "Cột",
"showIp": "Hiển thị địa chỉ IP",
"connectionType": "Kiểu kết nối",
"layout": "Bố cục",
"showStatus": "Hiển thị trạng thái",
"showHostName": "Hiển thị tên máy chủ",
"noDockerActivity": "Không có hoạt động Docker",
"noActivity": "Không có hoạt động",
"showAcknowledged": "Hiển thị đã xác nhận",
"showCurrentValue": "Hiển thị giá trị hiện tại",
"chartMetric": "Chỉ số",
"metricRange": "Phạm vi",
"widgetMetricsChartName": "Biểu đồ chỉ số",
"widgetMetricsChartDesc": "Biểu đồ lịch sử CPU, bộ nhớ, ổ đĩa hoặc mạng cho một máy chủ",
"widgetHostGridName": "Lưới máy chủ",
"widgetHostGridDesc": "Hiển thị trạng thái máy chủ SSH dạng lưới",
"widgetAlertFeedName": "Luồng cảnh báo",
"widgetAlertFeedDesc": "Cảnh báo trực tiếp kèm hỗ trợ xác nhận",
"widgetPingStatusName": "Trạng thái ping",
"widgetPingStatusDesc": "Trạng thái ping HTTP cho một hoặc nhiều URL",
"widgetRecentActivityName": "Hoạt động gần đây",
"widgetRecentActivityDesc": "Luồng cuộn hiển thị hoạt động Termix gần đây",
"widgetTermixUptimeName": "Thời gian hoạt động Termix",
"widgetTermixUptimeDesc": "Bộ đếm uptime trực tiếp cho máy chủ Termix",
"widgetSystemOverviewName": "Tổng quan hệ thống",
"widgetSystemOverviewDesc": "Phiên bản Termix, tình trạng cơ sở dữ liệu và uptime trong nháy mắt",
"widgetSshQuickConnectName": "Kết nối nhanh SSH",
"widgetSshQuickConnectDesc": "Nút bấm một lần để mở phiên SSH",
"widgetDockerActivityName": "Hoạt động Docker",
"widgetDockerActivityDesc": "Các sự kiện container Docker gần đây trên tất cả máy chủ",
"widgetCalendarName": "Lịch",
"widgetCalendarDesc": "Lịch tháng có đánh dấu ngày hôm nay",
"widgetCountdownName": "Đếm ngược",
"widgetCountdownDesc": "Đồng hồ đếm ngược đến ngày mục tiêu",
"widgetSearchBarName": "Thanh tìm kiếm",
"widgetSearchBarDesc": "Widget tìm kiếm web nhanh",
"widgetTextBannerName": "Biểu ngữ văn bản",
"widgetTextBannerDesc": "Nhãn đậm hoặc tiêu đề phần cho canvas",
"widgetImageWidgetName": "Hình ảnh",
"widgetImageWidgetDesc": "Hiển thị hình ảnh từ URL",
"widgetMarkdownNotesName": "Ghi chú Markdown",
"widgetMarkdownNotesDesc": "Ghi chú phong phú hiển thị markdown trực tiếp",
"widgetCustomApiName": "API Tùy chỉnh",
"widgetCustomApiDesc": "Lấy và hiển thị dữ liệu từ bất kỳ API JSON nào",
"widgetServiceGridName": "Lưới Dịch vụ",
"widgetServiceGridDesc": "Lưới các liên kết ô dịch vụ có thể cấu hình",
"widgetDashboardLinksName": "Liên kết Bảng điều khiển",
"widgetDashboardLinksDesc": "Hiển thị các liên kết dịch vụ đã cấu hình từ bảng điều khiển",
"widgetSearchLinksName": "Lối tắt tìm kiếm",
"widgetSearchLinksDesc": "Các nút lối tắt tìm kiếm nhanh với nhập liệu trực tiếp",
"widgetLinkTreeName": "Cây Liên kết",
"widgetLinkTreeDesc": "Các phần liên kết được nhóm với tiêu đề",
"calMon": "T2",
"calTue": "T3",
"calWed": "T4",
"calThu": "T5",
"calFri": "T6",
"calSat": "T7",
"calSun": "CN",
"startOnMonday": "Bắt đầu tuần từ Thứ 2",
"countdownNoDate": "Chưa đặt ngày mục tiêu",
"countdownPast": "Sự kiện đã qua",
"countdownDays": "ngày",
"countdownHours": "giờ",
"countdownMinutes": "phút",
"countdownSeconds": "giây",
"countdownLabel": "Nhãn",
"countdownLabelPlaceholder": "Ví dụ: Ngày ra mắt",
"countdownShowDays": "Hiển thị ngày",
"countdownShowHours": "Hiển thị giờ",
"targetDate": "Ngày mục tiêu",
"searchEngine": "Công cụ tìm kiếm",
"customSearchUrl": "URL tìm kiếm tùy chỉnh",
"searchPlaceholder": "Tìm kiếm...",
"searchGo": "Tìm",
"searchPlaceholderLabel": "Văn bản gợi ý",
"searchPlaceholderHint": "Văn bản hiển thị trong ô tìm kiếm",
"openInNewTab": "Mở trong tab mới",
"searchQueryPlaceholder": "Nhập truy vấn...",
"noSearchShortcuts": "Chưa có phím tắt nào được cấu hình",
"addSearchShortcut": "Thêm phím tắt",
"fontSize": "Cỡ chữ",
"textAlign": "Căn chỉnh văn bản",
"fontWeight": "Độ đậm chữ",
"clearColor": "Xóa màu",
"imageFit": "Kiểu vừa ảnh",
"imageLinkUrl": "URL liên kết",
"noImage": "Chưa đặt URL hình ảnh",
"altText": "Văn bản thay thế",
"altTextPlaceholder": "Mô tả hình ảnh",
"renderMarkdown": "Kết xuất Markdown",
"displayMode": "Chế độ hiển thị",
"displayField": "Trường hiển thị",
"jsonPath": "Đường dẫn JSON",
"customApiLabel": "Nhãn",
"customApiLabelPlaceholder": "Ví dụ: Nhiệt độ",
"customApiUnit": "Đơn vị",
"customApiNoUrl": "Chưa cấu hình URL API",
"customApiError": "Không tải được",
"customApiNotArray": "Phản hồi không phải là một mảng",
"addService": "Thêm dịch vụ",
"showLabels": "Hiển thị nhãn",
"iconSize": "Kích thước biểu tượng",
"noDashboardLinks": "Chưa có liên kết bảng điều khiển",
"noLimit": "Không giới hạn",
"sectionHeading": "Tiêu đề phần",
"addSection": "Thêm phần",
"compactMode": "Chế độ thu gọn",
"showDetailed": "Hiển thị chi tiết",
"selectHosts": "Chọn máy chủ",
"allHosts": "Tất cả máy chủ",
"listLayout": "Danh sách",
"gridLayout": "Lưới",
"terminal": "Terminal",
"files": "Tệp",
"docker": "Docker",
"range15m": "15 phút",
"range1h": "1 giờ",
"range6h": "6 giờ",
"range24h": "24 giờ",
"metricNetRx": "Tải xuống",
"metricNetTx": "Tải lên",
"severityFilter": "Bộ lọc mức độ",
"filterAll": "Tất cả",
"accentColor": "Màu nhấn",
"widgetSshTerminalName": "SSH Terminal",
"widgetSshTerminalDesc": "Một terminal SSH nội tuyến kết nối tới máy chủ đã cấu hình",
"sshTerminalNoHost": "Chưa cấu hình máy chủ",
"sshTerminalConnect": "Kết nối",
"sshTerminalAutoConnect": "Tự động kết nối khi tải",
"widgetQuickConnectName": "Kết nối nhanh",
"widgetQuickConnectDesc": "Nút khởi chạy một nhấp cho mọi loại kết nối trên các máy chủ của bạn",
"connectionTypes": "Loại kết nối",
"connType_terminal": "Terminal",
"connType_files": "Quản lý tệp",
"connType_docker": "Docker",
"connType_tunnel": "Đường hầm",
"connType_host-metrics": "Thông số Máy chủ",
"connType_rdp": "RDP",
"connType_vnc": "VNC",
"connType_telnet": "Telnet",
"widgetFileManagerName": "Quản lý Tệp",
"widgetFileManagerDesc": "Trình quản lý tệp SFTP tích hợp cho máy chủ đã cấu hình",
"widgetDockerName": "Quản lý Docker",
"widgetDockerDesc": "Trình quản lý container Docker tích hợp cho máy chủ đã cấu hình",
"widgetTunnelName": "Quản lý Đường hầm",
"widgetTunnelDesc": "Trình quản lý đường hầm SSH tích hợp cho máy chủ đã cấu hình",
"widgetNoHostSelected": "Chưa cấu hình máy chủ"
},
"serverConfig": {
"title": "Cấu hình Máy chủ",
"description": "Cấu hình URL máy chủ Termix để kết nối đến các dịch vụ backend của bạn",
"serverUrl": "URL máy chủ",
"enterServerUrl": "Vui lòng nhập URL máy chủ",
"saveFailed": "Lưu cấu hình thất bại",
"saveError": "Lỗi khi lưu cấu hình",
"saving": "Đang lưu...",
"saveConfig": "Lưu Cấu hình",
"helpText": "Nhập URL nơi máy chủ Termix của bạn đang chạy (ví dụ: http://localhost:30001 hoặc https://your-server.com)",
"changeServer": "Đổi Máy chủ",
"mustIncludeProtocol": "URL máy chủ phải bắt đầu bằng http:// hoặc https://",
"allowInvalidCertificate": "Cho phép chứng chỉ không hợp lệ",
"allowInvalidCertificateDesc": "Chỉ dùng cho các máy chủ tự lưu trữ đáng tin cậy có chứng chỉ tự ký hoặc chứng chỉ địa chỉ IP.",
"useEmbedded": "Dùng Máy chủ Cục bộ",
"embeddedDesc": "Chạy Termix với máy chủ cục bộ tích hợp (không cần máy chủ từ xa)",
"embeddedConnecting": "Đang kết nối đến máy chủ cục bộ...",
"embeddedNotReady": "Máy chủ cục bộ chưa sẵn sàng. Vui lòng đợi một lát và thử lại.",
"localServer": "Máy chủ Cục bộ",
"savedServers": "Máy chủ Đã lưu",
"noSavedServers": "Không có máy chủ nào được lưu",
"removeServer": "Xóa"
},
"migrationNotice": {
"title": "Termix Desktop hiện đã có thể chạy độc lập.",
"body1": "Ứng dụng này trước đây kết nối trực tiếp với máy chủ Termix của bạn. Giờ đây, nó đã được thiết kế lại để hoạt động hoàn toàn độc lập, lưu trữ máy chủ và thông tin đăng nhập cục bộ để tiếp tục hoạt động ngoại tuyến. Đồng bộ hóa hai chiều với máy chủ Termix tự lưu trữ hiện là tùy chọn.",
"body2": "Máy chủ và thông tin đăng nhập hiện tại của bạn vẫn nằm trên {{url}}. Hãy bật Đồng bộ hóa từ xa và kết nối lại với máy chủ đó để khôi phục chúng và giữ cho cả hai luôn được đồng bộ trong tương lai.",
"dismiss": "Không phải bây giờ",
"setUpSync": "Thiết lập đồng bộ hóa từ xa"
},
"remoteSync": {
"title": "Đồng bộ từ xa",
"description": "Bạn có thể tùy chọn kết nối ứng dụng máy tính để bàn này với máy chủ Termix tự lưu trữ để đồng bộ hóa máy chủ, thông tin đăng nhập và đoạn mã trên các thiết bị. Ứng dụng luôn hoạt động hoàn toàn ngoại tuyến cho dù bạn có kết nối mạng hay không.",
"notConnected": "Không kết nối",
"connected": "Đã kết nối",
"connectedTo": "Đã kết nối với {{url}}",
"lastSynced": "Lần đồng bộ cuối cùng {{time}}",
"neverSynced": "Chưa bao giờ đồng bộ",
"syncError": "Lỗi đồng bộ: {{message}}",
"needsReauth": "Đăng nhập đã hết hạn",
"connectButton": "Kết nối với máy chủ",
"disconnectButton": "Ngắt kết nối",
"syncNowButton": "Đồng bộ ngay",
"syncing": "Đang đồng bộ hóa...",
"syncSuccess": "Đồng bộ hóa từ xa đã hoàn tất",
"syncUnavailable": "Không thể khởi động đồng bộ hóa từ xa.",
"serverUrl": "URL máy chủ",
"enterServerUrl": "Vui lòng nhập URL máy chủ",
"mustIncludeProtocol": "URL máy chủ phải bắt đầu bằng http:// hoặc https://",
"connectionTestFailed": "Không thể kết nối đến máy chủ Termix tại địa chỉ URL đó.",
"allowInvalidCertificate": "Cho phép chứng chỉ không hợp lệ",
"allowInvalidCertificateDesc": "Chỉ sử dụng cho các máy chủ tự lưu trữ đáng tin cậy có chứng chỉ tự ký hoặc chứng chỉ địa chỉ IP.",
"savedServers": "Máy chủ đã lưu",
"removeServer": "Di dời",
"continueButton": "Tiếp tục",
"cancelButton": "Hủy bỏ",
"signInTitle": "Đăng nhập vào {{url}}",
"originTitle": "Nguồn gốc kết nối",
"originDescription": "Chọn nơi mặc định các kết nối SSH được tạo ra. Có thể thay đổi cài đặt này cho từng máy chủ.",
"originLocal": "Thiết bị này (mạng cục bộ)",
"originRemote": "Máy chủ từ xa",
"bannerReconnect": "Kết nối lại",
"bannerMessage": "Đồng bộ hóa từ xa cần xác thực lại."
},
"versionCheck": {
"error": "Lỗi Kiểm tra Phiên bản",
"checkFailed": "Kiểm tra cập nhật thất bại",
"upToDate": "Ứng dụng đã là phiên bản mới nhất",
"currentVersion": "Bạn đang chạy phiên bản {{version}}",
"updateAvailable": "Có bản cập nhật",
"updateLinkLabel": "Đã có bản cập nhật — xem ghi chú phát hành trên GitHub.",
"newVersionAvailable": "Đã có phiên bản mới! Bạn đang chạy {{current}}, nhưng đã có {{latest}}.",
"betaVersion": "Phiên bản beta",
"betaVersionDesc": "Bạn đang chạy {{current}}, mới hơn bản phát hành ổn định mới nhất {{latest}}.",
"releasedOn": "Phát hành vào {{date}}",
"downloadUpdate": "Tải xuống bản cập nhật",
"checking": "Đang kiểm tra cập nhật...",
"checkUpdates": "Kiểm tra cập nhật",
"checkingUpdates": "Đang kiểm tra cập nhật...",
"updateRequired": "Yêu cầu cập nhật"
},
"common": {
"close": "Đóng",
"minimize": "Thu nhỏ",
"online": "Trực tuyến",
"offline": "Ngoại tuyến",
"unknown": "Không xác định",
"continue": "Tiếp tục",
"maintenance": "Bảo trì",
"degraded": "Suy giảm",
"error": "Lỗi",
"warning": "Cảnh báo",
"unsavedChanges": "Thay đổi chưa lưu",
"dismiss": "Bỏ qua",
"more": "Hơn",
"loading": "Đang tải...",
"optional": "Tùy chọn",
"connect": "Kết nối",
"copied": "Đã sao chép",
"connecting": "Đang kết nối...",
"updateAvailable": "Có bản cập nhật",
"appName": "Termix",
"openInNewTab": "Mở trong tab mới",
"noReleases": "Không có bản phát hành",
"updatesAndReleases": "Cập nhật & Phát hành",
"newVersionAvailable": "Đã có phiên bản mới ({{version}}).",
"failedToFetchUpdateInfo": "Không thể lấy thông tin cập nhật",
"preRelease": "Tiền phát hành",
"noReleasesFound": "Không tìm thấy bản phát hành.",
"cancel": "Hủy",
"username": "Tên người dùng",
"login": "Đăng nhập",
"logout": "Đăng xuất",
"register": "Đăng ký",
"password": "Mật khẩu",
"confirmPassword": "Xác nhận mật khẩu",
"back": "Quay lại",
"save": "Lưu",
"saving": "Đang lưu...",
"delete": "Xóa",
"rename": "Đổi tên",
"edit": "Chỉnh sửa",
"add": "Thêm",
"confirm": "Xác nhận",
"no": "Không",
"or": "HOẶC",
"next": "Tiếp theo",
"previous": "Trước",
"refresh": "Làm mới",
"language": "Ngôn ngữ",
"checking": "Đang kiểm tra...",
"checkingDatabase": "Đang kiểm tra kết nối cơ sở dữ liệu...",
"checkingAuthentication": "Đang kiểm tra xác thực...",
"backendReconnected": "Kết nối máy chủ đã được khôi phục",
"connectionDegraded": "Mất kết nối máy chủ, đang khôi phục...",
"reload": "Tải lại",
"remove": "Xóa",
"create": "Tạo",
"update": "Cập nhật",
"copy": "Sao chép",
"copyFailed": "Không thể sao chép vào bảng tạm",
"maximize": "Phóng to",
"restore": "Khôi phục",
"of": "trên",
"saved": "Đã lưu",
"deleted": "Đã xóa",
"deleteFailed": "Không thể xóa",
"saveFailed": "Không thể lưu",
"required": "Bắt buộc"
},
"onboarding": {
"stepCounter": "Bước {{current}} của {{total}}",
"skip": "Bỏ qua bước thiết lập",
"next": "Kế tiếp",
"finish": "Bắt đầu",
"welcomeTitle": "Chào mừng đến với Termix",
"welcomeIntro": "Termix quản lý máy chủ của bạn từ một nơi duy nhất. Quá trình thiết lập này chỉ mất khoảng một phút và không có gì là cố định cả.",
"welcome_hosts": "Hãy bảo vệ máy chủ của bạn",
"welcome_hosts_desc": "Hãy lập một danh sách duy nhất để quản lý tất cả các máy móc bạn đang sử dụng.",
"welcome_terminal": "Kết nối ngay lập tức",
"welcome_terminal_desc": "Mở cửa sổ dòng lệnh trong một tab, không cần sử dụng trình khách SSH riêng biệt.",
"welcome_files": "Duyệt và chỉnh sửa tệp",
"welcome_files_desc": "Tải lên, tải xuống và chỉnh sửa các tệp từ xa.",
"presetTitle": "Bạn muốn hiển thị bao nhiêu trên màn hình?",
"presetIntro": "Termix có thể đơn giản hoặc chi tiết tùy thích. Hãy chọn một điểm bắt đầu.",
"presetChangeLater": "Bạn có thể chuyển đổi giữa các thiết lập sẵn hoặc thay đổi bất kỳ thiết lập nào sau này trong phần Cài đặt, mục Giao diện.",
"appearanceTitle": "Hãy biến nó thành của bạn",
"appearanceIntro": "Chọn chủ đề, màu nhấn và ngôn ngữ của bạn. Bạn có thể thay đổi cả ba sau này trong phần Cài đặt.",
"featuresTitle": "Ngoài ra, Termix còn cung cấp những dịch vụ gì khác?",
"featuresIntro": "Mỗi máy chủ bạn lưu có thể được mở trong nhiều cửa sổ dòng lệnh khác nhau. Đây là những gì đang chờ đợi phía sau các biểu tượng bên trái.",
"feature_files": "Trình quản lý tập tin",
"feature_files_desc": "Duyệt, tải lên, tải xuống và chỉnh sửa tệp qua SFTP mà không cần rời khỏi ứng dụng.",
"feature_desktop": "Máy tính từ xa",
"feature_desktop_desc": "Mở các phiên RDP, VNC và Telnet trong cùng một tab, tương tự như SSH.",
"feature_tunnels": "Đường hầm",
"feature_tunnels_desc": "Chuyển tiếp cổng thông qua máy chủ để truy cập các dịch vụ không được công khai.",
"feature_docker": "Docker",
"feature_docker_desc": "Xem các container, đọc nhật ký và theo dõi số liệu thống kê trên bất kỳ máy chủ nào đang chạy Docker.",
"feature_snippets": "Những đoạn trích",
"feature_snippets_desc": "Lưu lại các lệnh bạn thường xuyên sử dụng và gửi chúng đến cửa sổ dòng lệnh chỉ với một cú nhấp chuột.",
"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.",
"feature_metrics": "Số liệu và cảnh báo",
"feature_metrics_desc": "Theo dõi hiệu năng CPU, bộ nhớ và ổ đĩa theo thời gian, và nhận cảnh báo khi chúng gặp sự cố.",
"featuresRailHint": "Không cần những biểu tượng này? Hãy ẩn bất kỳ biểu tượng nào khỏi thanh bên trong Cài đặt, mục Điều hướng.",
"workflowTitle": "Di chuyển nhanh hơn",
"workflowIntro": "Một vài thói quen giúp tiết kiệm thời gian nhất khi bạn đã có một vài máy chủ.",
"workflow_palette": "Bảng lệnh",
"workflow_palette_desc": "Bạn có thể truy cập bất kỳ máy chủ hoặc hành động nào bằng cách nhập văn bản. Nhấn Shift hai lần để mở.",
"workflow_split": "Chia màn hình",
"workflow_split_desc": "Hiển thị tối đa bốn tab cạnh nhau để theo dõi nhật ký trong khi làm việc.",
"workflow_dock": "Tấm bên hông",
"workflow_dock_desc": "Nhấp chuột giữa hoặc nhấp chuột phải vào biểu tượng thanh bên để mở nó dưới dạng tab hoặc ghim nó vào bên phải.",
"workflow_workspaces": "Không gian làm việc",
"workflow_workspaces_desc": "Lưu lại một nhóm các tab đang mở và mở lại toàn bộ bố cục sau.",
"securityTitle": "Bảo vệ thông tin đăng nhập của bạn",
"securityIntro": "Termix lưu trữ thông tin đăng nhập của bạn, vì vậy bạn nên dành chút thời gian tìm hiểu cách thức hoạt động của nó.",
"security_credentials": "Thông tin xác thực có thể tái sử dụng",
"security_credentials_desc": "Bạn chỉ cần lưu khóa hoặc mật khẩu một lần và gắn nó vào bao nhiêu máy chủ tùy thích.",
"security_twofa": "Xác thực hai yếu tố và mật khẩu",
"security_twofa_desc": "Thêm mã TOTP hoặc mật khẩu vào tài khoản của bạn trong phần Cài đặt, mục Bảo mật.",
"security_identity": "Mã định danh Termix",
"security_identity_desc": "Hãy cấp chứng chỉ SSH có thời hạn ngắn thay vì sao chép khóa đến từng máy chủ.",
"security_sharing": "Chia sẻ",
"security_sharing_desc": "Cấp quyền truy cập máy chủ cho người dùng khác mà không cần cung cấp mật khẩu.",
"securityEncryptionNote": "Thông tin đăng nhập được mã hóa trước khi lưu trữ và chỉ được giải mã khi cần thiết cho việc kết nối.",
"doneTitle": "Bạn đã sẵn sàng",
"doneHeading": "Cài đặt hoàn tất",
"doneDesc": "Chọn một máy chủ từ thanh bên để mở cửa sổ dòng lệnh, xem các tệp hoặc xem số liệu của nó.",
"done_settings": "Bạn có thể thay đổi bất cứ điều gì sau này",
"done_settings_desc": "Các tùy chọn về chủ đề, mật độ bố cục và biểu tượng hiển thị đều nằm trong phần Cài đặt.",
"done_rerun": "Bạn muốn gọi lại món này không?",
"done_rerun_desc": "Mở Cài đặt, vào Giao diện và chọn Chạy thiết lập để thực hiện lại các bước này.",
"done_desktop": "Ứng dụng máy tính để bàn",
"done_desktop_desc": "Termix hoạt động như một ứng dụng máy tính để bàn trên Windows, macOS và Linux.",
"done_desktop_link": "Tải ứng dụng dành cho máy tính để bàn",
"done_mobile": "Ứng dụng di động",
"done_mobile_desc": "Mang theo máy chủ của bạn trên iOS và Android.",
"done_mobile_link": "Tải ứng dụng di động",
"done_docs": "Tài liệu đầy đủ",
"done_docs_desc": "Hướng dẫn chi tiết cho mọi tính năng, bao gồm cả những tính năng không được đề cập ở đây.",
"done_docs_link": "Mở tài liệu",
"done_cli": "Công cụ dòng lệnh",
"done_cli_desc": "Quản lý máy chủ của bạn từ thiết bị đầu cuối và sử dụng Termix trong các tập lệnh của riêng bạn.",
"done_cli_link": "Mở tài liệu CLI",
"aiTitle": "Trợ lý AI",
"aiIntro": "Termix có thể bao gồm trợ lý AI tùy chọn. Bạn có thể thay đổi điều này sau trong phần cài đặt.",
"aiEnableTitle": "Bật nó lên",
"aiEnableDesc": "Thêm một trợ lý đọc cấu hình của bạn và đề xuất các thay đổi mà bạn chấp thuận. Cần có nhà cung cấp do bạn chỉ định, chẳng hạn như Ollama địa phương.",
"aiSkipTitle": "Đừng làm vậy",
"aiSkipDesc": "Termix vẫn hoạt động như hiện tại. Trợ lý ảo vẫn ẩn mình.",
"aiNote": "Không có dữ liệu nào được gửi đi cho đến khi bạn thêm nhà cung cấp và gửi tin nhắn."
},
"nav": {
"collab": "Các cuộc họp",
"home": "Trang chủ",
"terminal": "Terminal",
"localTerminal": "Ga địa phương",
"docker": "Docker",
"tunnels": "Đường hầm",
"fileManager": "Quản lý tệp",
"serverStats": "Chỉ số máy chủ",
"hostMetrics": "Chỉ số máy chủ",
"admin": "Quản trị",
"termixId": "ID",
"userProfile": "Hồ sơ người dùng",
"splitScreen": "Chia màn hình",
"confirmClose": "Đóng phiên đang hoạt động?",
"close": "Đóng",
"cancel": "Hủy",
"sshManager": "Trình quản lý SSH",
"cannotSplitTab": "Không thể chia tab này",
"hostTabTitle": "{{username}}@{{ip}}:{{port}}",
"copyPassword": "Sao chép mật khẩu",
"copySudoPassword": "Sao chép mật khẩu Sudo",
"passwordCopied": "Đã sao chép mật khẩu",
"noPasswordAvailable": "Không có mật khẩu",
"failedToCopyPassword": "Không thể sao chép mật khẩu",
"refreshTab": "Làm mới kết nối",
"renameTab": "Đổi tên tab",
"openFileManager": "Mở quản lý tệp",
"dashboard": "Bảng điều khiển",
"networkGraph": "Biểu đồ mạng",
"tmuxMonitor": "Giám sát Tmux",
"homepage": "Trang chủ",
"quickConnect": "Kết nối nhanh",
"sshTools": "Công cụ SSH",
"history": "Lịch sử",
"sessionLogs": "Nhật ký phiên",
"openAsTabHint": "Nhấn Ctrl + chuột hoặc chuột giữa để mở dưới dạng tab",
"openAsTab": "Mở dưới dạng tab",
"openInRightDock": "Mở trong thanh công cụ bên phải",
"closeRightDock": "Đóng bến tàu bên phải",
"toggleRightDock": "Bật/tắt thanh công cụ bên phải",
"multiPanelHintTitle": "Làm việc với nhiều hơn một bảng điều khiển",
"multiPanelHintBody": "Hãy giữ cho bảng điều khiển này luôn mở trong khi thanh bên được sử dụng cho mục đích khác. Có hai cách để di chuyển nó:",
"multiPanelHintTabHow": "Nhấn giữ phím Ctrl và nhấp chuột vào biểu tượng trên thanh ray, hoặc sử dụng nút ở phần tiêu đề này.",
"multiPanelHintDockHow": "Nhấp chuột phải vào biểu tượng thanh ray hoặc sử dụng biểu tượng bảng điều khiển trên thanh tab.",
"sidebarSettings": "Cài đặt thanh bên...",
"hosts": "Máy chủ",
"snippets": "Đoạn mã",
"macros": "Macro",
"fleets": "Hạm đội",
"automations": "Tự động hóa",
"workspaces": "Không gian làm việc",
"hostManager": "Quản lý máy chủ",
"credentials": "Thông tin đăng nhập",
"portForwarding": "Chuyển tiếp",
"sftp": "SFTP",
"connections": "Kết nối",
"alerts": "Cảnh báo",
"serial": "Nối tiếp",
"keepSideMenuOpen": "Giữ menu luôn mở",
"collapseSideMenu": "Menu thu gọn",
"roleAdministrator": "Quản trị viên",
"roleUser": "Người dùng",
"ai": "Trí tuệ nhân tạo"
},
"hosts": {
"hosts": "Máy chủ",
"noHosts": "Không có máy chủ SSH",
"retry": "Thử lại",
"refresh": "Làm mới",
"optional": "Tùy chọn",
"downloadSample": "Tải mẫu",
"failedToDeleteHost": "Xóa {{name}} thất bại",
"importSkipExisting": "Nhập (bỏ qua các mục đã có)",
"importSSHConfig": "Nhập từ cấu hình SSH",
"connectionDetails": "Chi tiết kết nối",
"ssh": "SSH",
"telnet": "Telnet",
"remoteDesktop": "Máy tính từ xa",
"port": "Cổng",
"username": "Tên đăng nhập",
"folder": "Thư mục",
"tags": "Thẻ",
"pin": "Ghim",
"addHost": "Thêm máy chủ",
"editHost": "Sửa máy chủ",
"cloneHost": "Sao chép máy chủ",
"enableTerminal": "Bật Terminal",
"enableTunnel": "Bật Tunnel",
"enableFileManager": "Bật Trình Quản Lý Tệp",
"enableDocker": "Bật Docker",
"defaultPath": "Đường dẫn mặc định",
"connection": "Kết nối",
"upload": "Tải lên",
"authentication": "Xác thực",
"password": "Mật khẩu",
"passwordSaved": "Mật khẩu đã được lưu, nhập để thay đổi",
"key": "Khóa",
"credential": "Thông tin xác thực",
"none": "Không có",
"sshPrivateKey": "Khóa riêng SSH",
"keyType": "Loại khóa",
"uploadFile": "Tải tệp lên",
"tabGeneral": "Chung",
"tabSsh": "SSH",
"tabTerminal": "Terminal",
"tabRdp": "RDP",
"tabVnc": "VNC",
"tabTunnels": "Đường hầm",
"tabDocker": "Docker",
"tabFiles": "Tệp",
"tabStats": "Số liệu máy chủ",
"tabHostMetrics": "Số liệu máy chủ",
"tabTelnet": "Telnet",
"tabSharing": "Chia sẻ",
"tabAuthentication": "Xác thực",
"terminal": "Terminal",
"tunnel": "Đường hầm",
"fileManager": "Trình quản lý tệp",
"serverStats": "Số liệu máy chủ",
"status": {
"available": "Có sẵn",
"reachable": "Có thể truy cập, nhưng chưa được xác thực.",
"offline": "Ngoại tuyến",
"monitoringDisabled": "Chức năng giám sát đã bị vô hiệu hóa.",
"label": "Trạng thái"
},
"folderRenamed": "Đã đổi tên thư mục \"{{oldName}}\" thành \"{{newName}}\" thành công",
"failedToRenameFolder": "Không thể đổi tên thư mục",
"unsavedChangesDescription": "Các thay đổi trên máy chủ của bạn chưa được lưu. Bạn có muốn hủy bỏ chúng không?",
"keepEditing": "Tiếp tục chỉnh sửa",
"discardChanges": "Hủy bỏ các thay đổi",
"movedToFolder": "Đã chuyển {{count}} máy chủ vào thư mục \"{{folder}}\"",
"editHostTooltip": "Chỉnh sửa máy chủ",
"statusChecks": "Kiểm tra trạng thái",
"metricsCollection": "Thu thập chỉ số",
"metricsInterval": "Khoảng thời gian thu thập chỉ số",
"metricsIntervalDesc": "Tần suất thu thập thống kê máy chủ (5s - 1h)",
"behavior": "Hành vi",
"themePreview": "Xem trước chủ đề",
"theme": "Chủ đề",
"fontFamily": "Phông chữ",
"fontSize": "Cỡ chữ",
"letterSpacing": "Khoảng cách ký tự",
"lineHeight": "Chiều cao dòng",
"cursorStyle": "Kiểu con trỏ",
"cursorBlink": "Con trỏ nhấp nháy",
"scrollbackBuffer": "Bộ đệm cuộn ngược",
"bellStyle": "Kiểu chuông",
"rightClickSelectsWord": "Nhấp chuột phải chọn từ",
"fastScrollModifier": "Phím bổ trợ cuộn nhanh",
"fastScrollSensitivity": "Độ nhạy cuộn nhanh",
"sshAgentForwarding": "Chuyển tiếp SSH Agent",
"backspaceMode": "Chế độ Backspace",
"startupSnippet": "Đoạn mã khởi động",
"selectSnippet": "Chọn đoạn mã",
"forceKeyboardInteractive": "Buộc dùng Keyboard-Interactive",
"overrideCredentialUsername": "Ghi đè tên đăng nhập thông tin xác thực",
"overrideCredentialUsernameDesc": "Sử dụng tên đăng nhập ở trên thay vì tên trong thông tin xác thực",
"oidcUsernameHint": "Sử dụng $oidc.preferred_username để thay thế tên đăng nhập OIDC của bạn.",
"tailscaleUsernameHint": "Đây phải là người dùng Unix mà danh tính Tailscale của bạn được cấp trong ACL SSH của tailnet, không nhất thiết phải là người dùng root.",
"jumpHostChain": "Chuỗi máy chủ trung gian",
"portKnocking": "Port Knocking",
"addKnock": "Thêm cổng",
"addProxyNode": "Thêm nút",
"proxyNode": "Nút proxy",
"proxyType": "Loại proxy",
"quickActions": "Thao tác nhanh",
"sudoPasswordAutoFill": "Tự động điền mật khẩu Sudo",
"sudoPassword": "Mật khẩu Sudo",
"keepaliveInterval": "Khoảng thời gian Keepalive (ms)",
"moshCommand": "Lệnh MOSH",
"environmentVariables": "Biến môi trường",
"addVariable": "Thêm biến",
"docker": "Docker",
"copyTerminalUrl": "Sao chép URL Terminal",
"copyFileManagerUrl": "Sao chép URL Trình quản lý tệp",
"copyRemoteDesktopUrl": "Sao chép URL Máy tính từ xa",
"failedToConnect": "Không thể kết nối tới bảng điều khiển",
"connect": "Kết nối",
"disconnect": "Ngắt kết nối",
"start": "Khởi động",
"enableStatusCheck": "Bật kiểm tra trạng thái",
"enableMetrics": "Bật chỉ số",
"bulkUpdateFailed": "Cập nhật hàng loạt không thành công",
"selectAll": "Chọn tất cả",
"deselectAll": "Bỏ chọn tất cả",
"protocols": "Giao thức",
"secureShell": "Secure Shell",
"virtualNetwork": "Mạng ảo",
"unencryptedShell": "Shell không mã hóa",
"addressIp": "Địa chỉ / IP",
"friendlyName": "Tên hiển thị",
"macAddress": "Địa chỉ MAC",
"wolBroadcastAddress": "Địa chỉ Broadcast WoL",
"wolBroadcastAddressDesc": "Địa chỉ broadcast hướng tùy chọn cho mạng Docker/định tuyến (ví dụ: 192.168.1.255). Để trống để sử dụng 255.255.255.255.",
"folderAndAdvanced": "Thư mục & Nâng cao",
"showAdvancedSettings": "Hiển thị cài đặt nâng cao",
"hideAdvancedSettings": "Ẩn cài đặt nâng cao",
"privateNotes": "Ghi chú riêng tư",
"privateNotesPlaceholder": "Chi tiết về máy chủ này...",
"pinToTop": "Ghim lên đầu",
"pinToTopDesc": "Luôn hiển thị máy chủ này ở đầu danh sách",
"portKnockingSequence": "Chuỗi Port Knocking",
"addKnockBtn": "Thêm Knock",
"noPortKnocking": "Không có cấu hình port knocking.",
"knockPort": "Cổng knock",
"protocol": "Giao thức",
"delayAfterMs": "Độ trễ sau (ms)",
"useSocks5Proxy": "Dùng proxy SOCKS5",
"useSocks5ProxyDesc": "Định tuyến kết nối qua máy chủ proxy",
"connectionOrigin": "Nguồn gốc kết nối",
"connectionOriginDesc": "Nguồn gốc kết nối của máy chủ này. Ghi đè lên cài đặt mặc định toàn cục của ứng dụng trên máy tính để bàn.",
"connectionOriginGuacamoleNote": "RDP, VNC và Telnet sử dụng máy chủ từ xa trừ khi bạn chọn \"Thiết bị này\", tùy chọn này yêu cầu máy ảo guacd mà thiết bị đó có thể truy cập được — hãy thiết lập máy ảo này trong cài đặt URL của guacd hoặc cho từng máy chủ trong phần Proxy của guacd.",
"connectionOriginDefault": "Sử dụng mặc định",
"connectionOriginLocal": "Thiết bị này (mạng cục bộ)",
"connectionOriginRemote": "Máy chủ từ xa",
"proxyHost": "Máy chủ proxy",
"proxyPort": "Cổng proxy",
"proxyUsername": "Tên người dùng proxy",
"proxyPassword": "Mật khẩu proxy",
"proxySingleMode": "Proxy đơn",
"proxyChainMode": "Chuỗi proxy",
"you": "Bạn",
"jumpHostChainLabel": "Chuỗi máy chủ trung gian",
"addJumpBtn": "Thêm máy trung gian",
"noJumpHosts": "Không có máy chủ trung gian nào được cấu hình.",
"selectAServer": "Chọn máy chủ...",
"sshPort": "Cổng SSH",
"authMethod": "Phương thức xác thực",
"authenticationMethod": "Phương thức xác thực",
"authenticationMethodDesc": "Hãy chọn phương thức mà Termix sẽ sử dụng để xác thực kết nối SSH này. Các phương thức khác sẽ không được thử tự động.",
"storedCredential": "Thông tin xác thực đã lưu",
"selectACredential": "Chọn thông tin xác thực...",
"vaultProfile": "Hồ sơ người ký Vault",
"selectAVaultProfile": "Chọn hồ sơ Vault...",
"vaultProfileHint": "Cài đặt từ hồ sơ dùng chung; bạn sẽ đăng nhập Vault qua OIDC khi kết nối. Không lưu bí mật.",
"vaultNewProfile": "Hồ sơ mới",
"secretRefHint": "Bạn có thể dán mã tham chiếu 1Password (op://vault/item/field) thay cho mã bí mật; mã này sẽ được lấy từ nguồn mã bí mật của bạn khi kết nối.",
"secretSourcesManage": "Quản lý các nguồn tin mật",
"secretSourcesTitle": "Nguồn tin bí mật",
"secretSourcesDesc": "Termix đọc các mã bí mật từ các trình quản lý mật khẩu bên ngoài khi kết nối. Hiện tại là 1Password Connect (tự lưu trữ). Mã truy cập được lưu trữ dưới dạng mã hóa cùng với khóa dữ liệu của bạn.",
"secretSourceNew": "Nguồn tin mới",
"secretSourceUrlLabel": "URL kết nối máy chủ",
"secretSourceTokenLabel": "Mã truy cập kết nối",
"secretSourceTokenKeep": "Để trống nếu muốn giữ nguyên mã thông báo hiện tại.",
"secretSourceSharedLabel": "Chia sẻ với tất cả người dùng (chỉ quản trị viên; thao tác này sẽ được thực hiện khi bạn đang đăng nhập)",
"secretSourceShared": "đã chia sẻ",
"secretSourceTest": "Bài kiểm tra",
"secretSourceTestOk": "Đã kết nối — {{count}} kho lưu trữ đang hiển thị",
"secretSourceTestFailed": "Kiểm tra kết nối thất bại",
"secretSourceRequired": "Tên người dùng, URL máy chủ và mã thông báo là bắt buộc.",
"secretSourceSaved": "Nguồn bí mật đã được lưu",
"secretSourceDeleted": "Nguồn tin bí mật đã bị xóa.",
"vaultManageProfiles": "Quản lý hồ sơ Vault",
"vaultAddrLabel": "Địa chỉ Vault",
"vaultNamespaceLabel": "Không gian tên",
"vaultOidcMountLabel": "Điểm gắn xác thực OIDC",
"vaultOidcRoleLabel": "Vai trò OIDC",
"vaultSshMountLabel": "Điểm gắn bí mật SSH",
"vaultSshRoleLabel": "Vai trò ký SSH",
"vaultValidPrincipalsLabel": "Các danh tính hợp lệ",
"vaultKeyTypeLabel": "Loại khóa tạm thời",
"vaultSharedLabel": "Chia sẻ với tất cả người dùng",
"vaultCreateProfile": "Tạo hồ sơ",
"vaultProfileCreated": "Đã tạo hồ sơ Vault",
"vaultProfileSaved": "Đã lưu hồ sơ Vault",
"vaultProfileDeleted": "Đã xóa hồ sơ Vault",
"vaultProfileSaveFailed": "Không thể lưu hồ sơ Vault",
"vaultProfileDeleteFailed": "Không thể xóa hồ sơ Vault",
"vaultSaveProfile": "Lưu hồ sơ",
"vaultProfileValidationError": "Tên, địa chỉ Vault và vai trò ký SSH là bắt buộc",
"vaultNoProfiles": "Chưa có hồ sơ Vault nào.",
"vaultSharedBadge": "được chia sẻ",
"keyTypeLabel": "Loại khóa",
"keyTypeAuto": "Tự động phát hiện",
"keyPasteTab": "Dán",
"keyUploadTab": "Tải lên",
"keyFileLoaded": "Đã tải tệp khóa",
"keyUploadClick": "Nhấn để tải lên .pem / .key / .ppk",
"clearKey": "Xóa khóa",
"keySaved": "Đã lưu khóa SSH",
"keyReplaceNotice": "dán khóa mới bên dưới để thay thế",
"keyPassphraseSaved": "Đã lưu cụm mật khẩu, nhập để thay đổi",
"replaceKey": "Thay khóa",
"docsLink": "Xem tài liệu",
"stepcaLabel": "Bước CA",
"stepcaDesc": "Đăng nhập thông qua nhà cung cấp danh tính của bạn và cho phép Step CA cấp chứng chỉ SSH có thời hạn ngắn cho máy chủ này. URL CA, dấu vân tay gốc và trình cung cấp OIDC được quản trị viên thiết lập trong Cài đặt quản trị.",
"authTypeStepca": "Bước CA",
"opksshLabel": "OPKSSH",
"opksshDesc": "Đăng nhập vào máy chủ này bằng nhà cung cấp danh tính thay vì mật khẩu hoặc khóa. Yêu cầu OPKSSH được thiết lập trên máy chủ.",
"warpgateLabel": "Cổng Warpgate",
"warpgateDesc": "Máy chủ này kết nối thông qua proxy SSH Warpgate. Termix sẽ tự động xử lý luồng phê duyệt trên trình duyệt sau khi xác thực.",
"agentLabel": "SSH Agent",
"agentDesc": "Xác thực bằng SSH agent chạy trên máy chủ Termix (Bitwarden, 1Password, gpg-agent, KeeAgent, ssh-agent). Agent phải đang chạy trên máy chạy Termix.",
"agentAuthenticationDesc": "Sử dụng khóa từ SSH agent để xác thực kết nối này. Để trống đường dẫn socket để sử dụng SSH_AUTH_SOCK.",
"agentSocketPathLabel": "Đường dẫn socket của Agent",
"agentSocketPathPlaceholder": "Để trống để sử dụng SSH_AUTH_SOCK",
"agentSocketPathHint": "Để trống để tự động phát hiện từ biến môi trường SSH_AUTH_SOCK, hoặc nhập đường dẫn socket tùy chỉnh (ví dụ: /run/user/1000/gnupg/S.gpg-agent.ssh).",
"agentIdentityLabel": "Thông tin nhận dạng của tác nhân (Khóa công khai)",
"agentIdentityPlaceholder": "Để trống để thử tất cả các phím từ trình quản lý.",
"agentIdentityHint": "Dán khóa công khai (ví dụ: ssh-ed25519 AAAA...) để chỉ cho phép sử dụng khóa đó từ tác nhân. Cách này được khuyến nghị khi tác nhân giữ nhiều khóa, để tránh vượt quá giới hạn MaxAuthTries của máy chủ.",
"shareSshAuthLabel": "Chia sẻ xác thực SSH",
"shareSshAuthDesc": "Cung cấp cho người nhận bản sao đã mã hóa thông tin xác thực SSH của máy chủ này. Thông tin xác thực cá nhân của người nhận vẫn được ưu tiên.",
"tailscaleDeviceSelect": "Chọn thiết bị Tailscale",
"tailscaleDeviceSelectPlaceholder": "Chọn thiết bị...",
"tailscaleNoApiKey": "Chưa cấu hình khóa API Tailscale. Thêm một khóa trong Cài đặt Quản trị để bật khám phá thiết bị.",
"tailscaleDocsLink": "Xem tài liệu",
"tailscaleLoadingDevices": "Đang tải thiết bị...",
"tailscaleDeviceLoadFailed": "Không thể tải thiết bị Tailscale. Vui lòng kiểm tra URL API và kết nối mạng.",
"tailscaleNoDevices": "Không tìm thấy thiết bị nào trong tailnet của bạn.",
"tailscaleDeviceAutoFill": "Chọn thiết bị sẽ tự động điền địa chỉ IP máy chủ.",
"forceKeyboardInteractiveLabel": "Bắt buộc Keyboard Interactive",
"forceKeyboardInteractiveShortDesc": "Buộc nhập mật khẩu thủ công ngay cả khi có khóa",
"allowLegacyAlgorithmsLabel": "Cho phép thuật toán cũ",
"allowLegacyAlgorithmsDesc": "Kích hoạt các thuật toán SSH đã lỗi thời (ssh-dss, ssh-rsa, diffie-hellman-group1-sha1, hmac-md5, 3des-cbc) cho kết nối đến các thiết bị cũ không thể nâng cấp.",
"insecure": "Không an toàn",
"terminalAppearance": "Giao diện terminal",
"colorTheme": "Chủ đề màu",
"fontFamilyLabel": "Họ phông chữ",
"fontFamilyCustomOption": "Phong tục...",
"fontFamilyCustomPlaceholder": "Tên phông chữ chính xác, ví dụ: MesloLGS NF",
"fontFamilyCustomHint": "Chọn một phông chữ có sẵn hoặc chọn Tùy chỉnh và nhập chính xác tên của một phông chữ đã được cài đặt trên hệ thống của bạn (ví dụ: MesloLGS NF, Noto Sans Mono). Termix không thể cài đặt phông chữ cho bạn, hãy cài đặt nó trên hệ điều hành của bạn trước.",
"fontSizeLabel": "Cỡ chữ",
"cursorStyleLabel": "Kiểu con trỏ",
"letterSpacingPx": "Khoảng cách chữ (px)",
"lineHeightLabel": "Chiều cao dòng",
"bellStyleLabel": "Kiểu chuông",
"backspaceModeLabel": "Chế độ Backspace",
"cursorBlinking": "Nhấp nháy con trỏ",
"cursorBlinkingDesc": "Bật hiệu ứng nhấp nháy cho con trỏ terminal",
"rightClickSelectsWordLabel": "Nhấp chuột phải chọn từ",
"rightClickSelectsWordShortDesc": "Chọn từ dưới con trỏ khi nhấp chuột phải",
"macOptionIsMetaLabel": "Phím Tùy chọn gửi dữ liệu meta",
"macOptionIsMetaShortDesc": "Tắt tính năng gõ các ký tự đặc biệt (như @ hoặc |) bằng phím Option/Alt trên macOS thay vì gửi dữ liệu Meta.",
"backgroundImageLabel": "URL ảnh nền",
"backgroundImageDesc": "URL tùy chọn cho ảnh nền terminal",
"backgroundImageOpacityLabel": "Độ mờ ảnh nền",
"customThemeColors": "Màu tùy chỉnh",
"customThemeBackground": "Nền",
"customThemeForeground": "Màu chữ",
"customThemeCursor": "Con trỏ",
"customThemeCursorAccent": "Điểm nhấn con trỏ",
"customThemeSelection": "Vùng chọn",
"customThemeAnsiColors": "Màu ANSI",
"customThemeBlack": "Đen",
"customThemeRed": "Đỏ",
"customThemeGreen": "Xanh lục",
"customThemeYellow": "Vàng",
"customThemeBlue": "Xanh dương",
"customThemeMagenta": "Đỏ tươi",
"customThemeCyan": "Xanh lơ",
"customThemeWhite": "Trắng",
"customThemeBrightBlack": "Đen sáng",
"customThemeBrightRed": "Đỏ sáng",
"customThemeBrightGreen": "Xanh lá sáng",
"customThemeBrightYellow": "Vàng sáng",
"customThemeBrightBlue": "Xanh dương sáng",
"customThemeBrightMagenta": "Đỏ tươi sáng",
"customThemeBrightCyan": "Xanh lơ sáng",
"customThemeBrightWhite": "Trắng sáng",
"customThemeResetTooltip": "Đặt lại về mặc định",
"savedThemesLabel": "Chủ đề đã lưu",
"saveAsGlobalTheme": "Lưu dưới dạng Chủ đề toàn cầu",
"saveGlobalThemeNamePrompt": "Nhập tên cho chủ đề này",
"saveGlobalThemeSuccess": "Chủ đề đã được lưu",
"saveGlobalThemeError": "Không thể lưu chủ đề",
"applyGlobalThemeTooltip": "Áp dụng chủ đề này",
"deleteGlobalThemeTooltip": "Xóa chủ đề này",
"noSavedThemes": "Chưa có chủ đề nào được lưu.",
"syntaxHighlightingLabel": "Tô sáng cú pháp",
"syntaxHighlightingDesc": "Tô màu đầu ra terminal (lỗi, đường dẫn, IP, dấu thời gian)",
"syntaxHighlightingCategories": "Danh mục tô sáng",
"syntaxHighlightingCategoriesDesc": "Chọn loại nội dung cần tô màu",
"syntaxCategoryLogLevels": "Mức log",
"syntaxCategoryLogLevelsDesc": "error, warn, info, debug, fatal",
"syntaxCategoryPaths": "Đường dẫn tệp",
"syntaxCategoryPathsDesc": "/usr/share/doc, ~/file.txt",
"syntaxCategoryTimestamps": "Dấu thời gian",
"syntaxCategoryTimestampsDesc": "[12:34:56], 2024-01-15",
"syntaxCategoryIpAddresses": "Địa chỉ IP",
"syntaxCategoryIpAddressesDesc": "192.168.1.1, 10.0.0.1:8080",
"syntaxCategoryUrls": "URL",
"syntaxCategoryUrlsDesc": "https://example.com",
"syntaxCategoryNumbers": "Số có nhãn",
"syntaxCategoryNumbersDesc": "port 8080, exit 1, status 404",
"behaviorAndAdvanced": "Hành vi & Nâng cao",
"scrollbackBufferLabel": "Bộ đệm cuộn ngược",
"scrollbackMaxLines": "Số dòng tối đa được giữ trong lịch sử",
"sshAgentForwardingLabel": "Chuyển tiếp SSH Agent",
"sshAgentForwardingShortDesc": "Cho phép máy chủ từ xa này sử dụng tác nhân SSH cục bộ của bạn để thiết lập các kết nối tiếp theo. Điều này không bắt buộc đối với việc xác thực tác nhân.",
"useSSHTitleLabel": "Sử dụng tiêu đề cửa sổ SSH",
"useSSHTitleDesc": "Cập nhật tiêu đề tab từ tiêu đề cửa sổ shell thay vì tên máy chủ",
"enableAutoMosh": "Kích hoạt Auto-Mosh",
"enableAutoMoshDesc": "Ưu tiên Mosh hơn SSH nếu có",
"enableAutoTmux": "Kích hoạt Auto-Tmux",
"enableAutoTmuxDesc": "Giữ cho shell và mọi thứ đang chạy trong đó hoạt động bình thường ngay cả khi bị ngắt kết nối hoặc khởi động lại trình duyệt bằng cách chạy bên trong tmux (tmux phải được cài đặt trên máy chủ).",
"enableSessionLogging": "Ghi nhật ký phiên",
"enableSessionLoggingDesc": "Ghi lại đầu ra phiên terminal để xem lại sau",
"allowSessionSharing": "Cho phép chia sẻ phiên",
"allowSessionSharingDesc": "Cho phép chia sẻ các phiên trực tiếp trên máy chủ này qua liên kết hoặc với những người dùng khác.",
"enableCommandHistory": "Lịch sử lệnh",
"enableCommandHistoryDesc": "Ghi lại các lệnh chạy trong terminal này để dùng cho lịch sử và tự động hoàn thành",
"localEchoLabel": "Tiếng vọng địa phương",
"localEchoDesc": "Dự đoán các thao tác gõ phím an toàn có thể in được cục bộ trên các kết nối chậm. Lời nhắc nhập mật khẩu và đầu vào điều khiển không bao giờ được hiển thị lại.",
"localEchoDefault": "Sử dụng cài đặt toàn cầu",
"localEchoOff": "Tắt",
"localEchoAuto": "Tự động",
"localEchoOn": "Luôn bật",
"linkClickBehaviorLabel": "Hành vi nhấp liên kết",
"linkClickBehaviorDesc": "Điều khiển hành động khi nhấp liên kết trong terminal. Dùng 'Mặc định' để theo cài đặt cấp ứng dụng.",
"linkClickBehaviorDefault": "Mặc định (tuân theo cài đặt ứng dụng)",
"linkClickBehaviorConfirm": "Hiển thị popup để mở hoặc sao chép",
"linkClickBehaviorDirect": "Mở trực tiếp",
"sudoPasswordAutoFillLabel": "Tự động điền mật khẩu sudo",
"sudoPasswordAutoFillShortDesc": "Tự động cung cấp mật khẩu sudo khi được yêu cầu",
"sudoPasswordAutoFillDesc": "Lưu trữ mật khẩu sudo để các số liệu máy chủ, lời nhắc terminal và các thành phần khác có thể chạy lệnh đặc quyền tự động.",
"sudoPasswordLabel": "Mật khẩu sudo",
"sudoPasswordSaved": "Mật khẩu đã được lưu, nhập để thay đổi",
"environmentVariablesLabel": "Biến môi trường",
"addVariableBtn": "Thêm biến",
"noEnvVars": "Chưa cấu hình biến môi trường nào.",
"fastScrollModifierLabel": "Phím bổ trợ cuộn nhanh",
"fastScrollSensitivityLabel": "Độ nhạy cuộn nhanh",
"moshCommandLabel": "Lệnh Mosh",
"startupSnippetLabel": "Đoạn mã khởi động",
"keepaliveIntervalLabel": "Khoảng thời gian Keepalive (giây)",
"maxKeepaliveMisses": "Số lần bỏ lỡ Keepalive tối đa",
"tunnelSettings": "Cài đặt đường hầm",
"enableTunneling": "Kích hoạt đường hầm",
"enableTunnelingDesc": "Kích hoạt chức năng đường hầm SSH cho máy chủ này",
"serverTunnelsSection": "Đường hầm máy chủ",
"addTunnelBtn": "Thêm đường hầm",
"noTunnelsConfigured": "Chưa cấu hình đường hầm nào.",
"tunnelLabel": "Đường hầm {{number}}",
"tunnelType": "Loại đường hầm",
"tunnelModeLocalDesc": "Chuyển tiếp một cổng cục bộ đến một cổng trên máy chủ từ xa (hoặc máy chủ có thể truy cập từ đó).",
"tunnelModeRemoteDesc": "Chuyển tiếp một cổng trên máy chủ từ xa về một cổng cục bộ trên máy của bạn.",
"tunnelModeDynamicDesc": "Tạo proxy SOCKS5 trên một cổng cục bộ để chuyển tiếp cổng động.",
"sameHost": "Máy chủ này (đường hầm trực tiếp)",
"endpointHost": "Máy chủ đích",
"endpointHostPlaceholder": "Cùng máy chủ, máy chủ SSH, hoặc máy chủ/IP có thể truy cập",
"endpointPort": "Cổng đích",
"bindHost": "Máy chủ bind",
"sourcePort": "Cổng nguồn",
"maxRetries": "Số lần thử lại tối đa",
"retryIntervalS": "Khoảng thời gian thử lại (giây)",
"autoStartLabel": "Tự động khởi động",
"autoStartDesc": "Tự động kết nối đường hầm này khi máy chủ được tải",
"tunnelConnecting": "Đang kết nối đường hầm...",
"tunnelDisconnected": "Đã ngắt kết nối đường hầm",
"failedToConnectTunnel": "Kết nối thất bại",
"failedToDisconnectTunnel": "Ngắt kết nối thất bại",
"dockerIntegration": "Tích hợp Docker",
"enableDockerMonitor": "Bật Docker",
"enableDockerMonitorDesc": "Giám sát và quản lý container trên máy chủ này qua Docker",
"containerRuntime": "Môi trường chạy container",
"containerRuntimeDesc": "Chọn CLI dùng để quản lý container trên máy chủ này",
"containerRuntimeDocker": "Docker",
"containerRuntimePodman": "Podman",
"enableTmuxMonitor": "Bật Tmux Monitor",
"enableTmuxMonitorDesc": "Hiển thị máy chủ này trong Tmux Monitor và thêm các hành động tmux của nó vào thanh bên",
"enableTerminalToolbar": "Kích hoạt thanh công cụ Terminal",
"enableTerminalToolbarDesc": "Hiển thị thanh công cụ truy cập nhanh được gắn vào cửa sổ terminal đang hoạt động để xem các công cụ và số liệu thống kê trực tiếp của máy chủ này.",
"connectionToolbar": "Thanh công cụ kết nối",
"showConnectionToolbar": "Hiển thị thanh công cụ kết nối",
"showConnectionToolbarDesc": "Hiển thị thanh công cụ trong các phiên SSH, RDP, VNC và Telnet của máy chủ này. Bạn cũng có thể tạm thời ẩn nó từ chính thanh công cụ.",
"enableAiAssistant": "Kích hoạt Trợ lý AI",
"enableAiAssistantDesc": "Cho phép trợ lý AI hỗ trợ trong thiết bị đầu cuối của máy chủ này. Mặc định là tắt, nhưng bạn vẫn cần bật AI cho tài khoản của mình.",
"tabProxmox": "Proxmox",
"proxmoxIntegration": "Tích hợp Proxmox",
"enableProxmox": "Bật Proxmox",
"enableProxmoxDesc": "Đánh dấu máy chủ này là một node Proxmox. Cho phép khám phá và nhập khách trực tiếp từ máy chủ này.",
"proxmoxDefaultAuthType": "Loại xác thực mặc định",
"proxmoxDefaultAuthTypeDesc": "Phương thức xác thực áp dụng cho các máy khách được nhập. Chọn loại xác thực phù hợp với cách bạn kết nối đến máy khách của mình.",
"authTypePassword": "Mật khẩu",
"authTypeKey": "Khóa SSH",
"authTypeCredential": "Thông tin xác thực",
"authTypeOpkssh": "OPKSSH",
"authTypeNone": "Không",
"proxmoxDefaultCredential": "Thông tin đăng nhập mặc định",
"proxmoxDefaultCredentialDesc": "Thông tin xác thực dùng cho máy khách được nhập khi phương thức xác thực là Credential.",
"proxmoxWindowsDetection": "Phát hiện Windows / RDP",
"proxmoxWindowsDetectionDesc": "Các mẫu tên cách nhau bằng dấu phẩy để kích hoạt RDP thay vì SSH (không phân biệt hoa thường).",
"proxmoxDockerDetection": "Phát hiện Docker",
"proxmoxDockerDetectionDesc": "Các mẫu tên cách nhau bằng dấu phẩy để bật Docker cho các máy khách phù hợp.",
"proxmoxPreferredRanges": "Dải IP ưu tiên",
"proxmoxPreferredRangesDesc": "Các tiền tố cách nhau bằng dấu phẩy theo thứ tự ưu tiên để chọn IP khi máy khách có nhiều giao diện mạng.",
"proxmoxAutoSync": "Tự động đồng bộ máy khách",
"proxmoxAutoSyncDesc": "Định kỳ khám phá nút Proxmox này và tạo hoặc cập nhật máy khách đã nhập khi phiên của bạn được mở khóa.",
"proxmoxSyncInterval": "Khoảng đồng bộ (phút)",
"proxmoxSyncIntervalDesc": "Tối thiểu 5 phút. Bộ lập lịch bỏ qua các phiên người dùng bị khóa.",
"proxmoxMarkMissing": "Đánh dấu máy khách bị thiếu",
"proxmoxMarkMissingDesc": "Thêm thẻ proxmox-missing khi máy khách đã nhập trước đó biến mất thay vì xóa nó.",
"proxmoxLastSync": "Lần đồng bộ cuối",
"proxmoxLastSyncNever": "Chưa đồng bộ",
"proxmoxLastSyncNoResult": "Không có chi tiết kết quả",
"proxmoxLastSyncSummary": "Đã tạo {{created}}, cập nhật {{updated}}, thiếu {{markedMissing}}, bỏ qua {{skipped}}",
"proxmoxLastSyncStatus": {
"success": "Thành công",
"error": "Thất bại",
"pending": "Đang chờ"
},
"proxmoxDiscoverAction": "Khám phá và nhập máy khách Proxmox",
"proxmoxImportTitle": "Nhập từ Proxmox",
"proxmoxSelectHost": "Chọn máy chủ Proxmox…",
"proxmoxDiscover": "Khám phá",
"proxmoxDiscovering": "Đang khám phá…",
"proxmoxDiscoverGuests": "Khám phá máy khách",
"proxmoxGuestsSelected_one": "{{count}} máy khách — đã chọn {{selected}}",
"proxmoxGuestsSelected_other": "{{count}} máy khách — đã chọn {{selected}}",
"proxmoxSelectAll": "Chọn tất cả",
"proxmoxDeselectAll": "Bỏ chọn tất cả",
"proxmoxNoGuests": "Không tìm thấy máy khách nào trên nút Proxmox này.",
"proxmoxImportButton_one": "Nhập {{count}} máy chủ",
"proxmoxImportButton_other": "Nhập {{count}} máy chủ",
"proxmoxResultImported": "Đã nhập {{count}}",
"proxmoxResultUpdated": "Đã cập nhật {{count}}",
"proxmoxResultFailed": "{{count}} thất bại",
"proxmoxResultSkippedNoIp": "{{count}} đã bỏ qua (không tìm thấy địa chỉ IP)",
"proxmoxImportComplete": "Hoàn tất nhập từ Proxmox: {{summary}}",
"proxmoxDiscoveryFailed": "Khám phá thất bại",
"proxmoxImportFailed": "Nhập thất bại",
"enableProxmoxStats": "Bật thống kê Proxmox",
"enableProxmoxStatsDesc": "Hiển thị tab Thống kê Proxmox cho máy chủ này với các số liệu thống kê trực tiếp về nút, máy ảo, bộ nhớ và cụm được thu thập qua SSH.",
"proxmoxStatsPollInterval": "Khoảng thời gian giữa các lần thăm dò (giây)",
"proxmoxStatsPollIntervalDesc": "Tối thiểu 15 giây. Tần suất làm mới số liệu thống kê của node Proxmox.",
"proxmoxStatsNodeOverride": "Ghi đè tên nút",
"proxmoxStatsNodeOverrideDesc": "Ghi đè tính năng tự động phát hiện tên nút Proxmox (mặc định được phát hiện thông qua tên máy chủ).",
"proxmoxStatsNodeOverridePlaceholder": "Tự động nhận diện từ tên máy chủ",
"proxmoxStatsUrlCopied": "URL Thống kê Proxmox đã được sao chép vào clipboard",
"copyProxmoxStatsUrlAction": "Sao chép URL Thống kê Proxmox",
"enableFileManagerMonitor": "Bật Trình quản lý tập tin",
"enableFileManagerMonitorDesc": "Duyệt và quản lý tập tin trên máy này qua SFTP",
"scpLegacyLabel": "Chế độ SCP cũ",
"scpLegacyDesc": "Sử dụng truyền tập tin kiểu cũ cho các máy chủ không hỗ trợ hệ thống con SFTP (ví dụ: máy chủ SSH nhúng hoặc tối thiểu).",
"defaultPathLabel": "Đường dẫn mặc định",
"fileManagerPathHint": "Thư mục sẽ mở khi khởi chạy Trình quản lý tập tin cho máy này.",
"statusChecksLabel": "Kiểm tra trạng thái",
"enableStatusChecks": "Bật Kiểm tra trạng thái",
"enableStatusChecksDesc": "Định kỳ ping máy này để xác minh tính khả dụng",
"useGlobalInterval": "Dùng khoảng thời gian toàn cục",
"useGlobalIntervalDesc": "Ghi đè bằng khoảng thời gian kiểm tra trạng thái toàn máy chủ",
"checkIntervalS": "Khoảng kiểm tra (giây)",
"checkIntervalDesc": "Số giây giữa mỗi lần ping kết nối",
"metricsCollectionLabel": "Thu thập số liệu",
"enableMetricsLabel": "Bật thu thập số liệu",
"enableMetricsDesc": "Thu thập CPU, RAM, đĩa và các số liệu khác từ máy này",
"useGlobalMetrics": "Dùng khoảng thời gian toàn cục",
"useGlobalMetricsDesc": "Ghi đè bằng khoảng thời gian thu thập số liệu toàn máy chủ",
"metricsIntervalS": "Khoảng thu thập số liệu (giây)",
"metricsIntervalDesc2": "Số giây giữa các lần chụp số liệu",
"excludedMountsLabel": "Giá đỡ bị loại trừ",
"monitoredMountsLabel": "Đường dẫn được giám sát tùy chỉnh",
"monitoredMountsDesc": "Thêm các đường dẫn không được hiển thị dưới dạng các điểm gắn kết riêng biệt, bao gồm cả các đường dẫn Home Assistant được gắn kết bằng bind, chẳng hạn như /config.",
"monitoredMountPathPlaceholder": "Đường dẫn (/config, /mnt/data)",
"monitoredMountLabelPlaceholder": "Nhãn (tùy chọn)",
"addMonitoredMount": "Thêm đường dẫn",
"excludedMountsDesc": "Ẩn các điểm gắn kết hoặc loại hệ thống tập tin cụ thể (ví dụ: nfs, cifs) khỏi thông tin sử dụng ổ đĩa và cảnh báo cho máy chủ này.",
"excludedMountsPlaceholder": "Đường dẫn gắn kết (/mnt/nas) hoặc loại hệ thống tệp (nfs, cifs)",
"excludedMountsEmpty": "Không có điểm gắn kết nào bị loại trừ. Tất cả các hệ thống tập tin được phát hiện đều được hiển thị.",
"addExcludedMount": "Thêm vào",
"visibleWidgets": "Widget hiển thị",
"widgetsMovedToHostMetrics": "Các thẻ hiện được thêm, sắp xếp và thay đổi kích thước trực tiếp trong tab Số liệu máy. Mở Số liệu máy cho máy này và dùng Tùy chỉnh để chọn thẻ hiển thị.",
"cpuUsageLabel": "Sử dụng CPU",
"cpuUsageDesc": "Phần trăm CPU, tải trung bình, biểu đồ sparkline",
"memoryLabel": "Sử dụng bộ nhớ",
"memoryDesc": "Sử dụng RAM, swap, cache",
"storageLabel": "Sử dụng đĩa",
"storageDesc": "Sử dụng đĩa theo điểm gắn kết",
"networkLabel": "Giao diện mạng",
"networkDesc": "Danh sách giao diện và băng thông",
"uptimeLabel": "Thời gian hoạt động",
"uptimeDesc": "Thời gian hoạt động và thời điểm khởi động",
"systemInfoLabel": "Thông tin hệ thống",
"systemInfoDesc": "Hệ điều hành, nhân, tên máy, kiến trúc",
"recentLoginsLabel": "Đăng nhập gần đây",
"recentLoginsDesc": "Sự kiện đăng nhập thành công và thất bại",
"topProcessesLabel": "Tiến trình hàng đầu",
"topProcessesDesc": "PID, CPU%, MEM%, lệnh",
"listeningPortsLabel": "Cổng đang lắng nghe",
"listeningPortsDesc": "Cổng mở với tiến trình và trạng thái",
"firewallLabel": "Tường lửa",
"firewallDesc": "Trạng thái tường lửa, AppArmor, SELinux",
"quickActionsLabel": "Hành động nhanh",
"quickActionsToolbar": "Hành động nhanh xuất hiện dưới dạng nút trên thanh công cụ Chỉ số máy để thực thi lệnh một lần nhấp.",
"noQuickActions": "Chưa có hành động nhanh nào.",
"buttonLabel": "Nhãn nút",
"selectSnippetPlaceholder": "Chọn đoạn mã...",
"addActionBtn": "Thêm hành động",
"hostSharedSuccessfully": "Đã chia sẻ máy thành công",
"failedToShareHost": "Chia sẻ máy thất bại",
"accessRevoked": "Đã thu hồi quyền truy cập",
"failedToRevokeAccess": "Thu hồi quyền truy cập thất bại",
"cancelBtn": "Hủy",
"savingBtn": "Đang lưu...",
"addHostBtn": "Thêm máy",
"hostUpdated": "Đã cập nhật máy",
"hostCreated": "Đã tạo máy",
"failedToSave": "Lưu máy thất bại",
"credentialUpdated": "Đã cập nhật thông tin xác thực",
"credentialCreated": "Đã tạo thông tin xác thực",
"failedToSaveCredential": "Lưu thông tin xác thực thất bại",
"credentialNameRequired": "Vui lòng nhập tên cho thông tin xác thực",
"credentialAuthRequired": "Thêm mật khẩu, khóa SSH, hoặc cả hai",
"createCredentialFromHostBtn": "Tạo thông tin xác thực",
"createCredentialFromHostTitle": "Tạo thông tin xác thực từ máy chủ",
"createCredentialFromHostDesc": "Tạo một mục thông tin đăng nhập có thể tái sử dụng và chia sẻ, được điền sẵn tên người dùng, mật khẩu và/hoặc khóa SSH hiện tại của máy chủ này.",
"backToHosts": "Quay lại Máy chủ",
"pinned": "Đã ghim",
"noHostsFound": "Không tìm thấy máy chủ",
"tryDifferentTerm": "Thử từ khóa khác",
"addFirstHost": "Thêm máy chủ đầu tiên để bắt đầu",
"noCredentialsFound": "Không tìm thấy thông tin xác thực",
"addCredentialBtn": "Thêm Chứng thực",
"updateCredentialBtn": "Cập nhật Chứng thực",
"editCredentialAction": "Chỉnh sửa thông tin đăng nhập",
"backToHost": "Trở lại trang chủ",
"saveCredentialAsNewBtn": "Lưu dưới dạng mới",
"saveCredentialAsNewDesc": "Tạo một thông tin xác thực mới với những thay đổi này và gán nó cho máy chủ này. Thông tin xác thực ban đầu vẫn được giữ nguyên.",
"credentialSavedAsNew": "Đã lưu dưới dạng thông tin đăng nhập mới",
"failedToSaveCredentialAsNew": "Không thể lưu thông tin đăng nhập mới.",
"features": "Tính năng",
"noFolder": "(Không có thư mục)",
"deleteSelected": "Xóa",
"exitSelection": "Thoát chọn",
"importSkip": "Nhập (bỏ qua mục đã có)",
"importOverwrite": "Nhập (ghi đè)",
"collapseBtn": "Thu gọn",
"importExportBtn": "Nhập / Xuất",
"hostStatusesRefreshed": "Đã làm mới trạng thái máy chủ",
"failedToRefreshHosts": "Không thể làm mới máy chủ",
"movedHostTo": "Đã di chuyển {{host}} vào \"{{folder}}\"",
"failedToMoveHost": "Không thể di chuyển máy chủ",
"deletedFolder": "Đã xóa thư mục \"{{name}}\"",
"failedToDeleteFolder": "Không thể xóa thư mục",
"deleteAllInFolder": "Xóa tất cả máy chủ trong \"{{name}}\"? Hành động này không thể hoàn tác.",
"folderPickerPlaceholder": "Không có thư mục",
"folderPickerSearch": "Tìm kiếm hoặc tạo mới (dùng / cho thư mục con)...",
"folderPickerNone": "Không có thư mục",
"folderPickerCreate": "Tạo \"{{path}}\"",
"folderPickerEmpty": "Không tìm thấy thư mục phù hợp",
"parentHost": "Cha mẹ chủ trì",
"useFolderInstead": "Hãy sử dụng thư mục thay thế.",
"useParentHostInstead": "Hãy sử dụng máy chủ cha thay thế",
"parentHostPickerPlaceholder": "Không có máy chủ cha",
"parentHostPickerSearch": "Tìm kiếm máy chủ...",
"parentHostPickerNone": "Không có máy chủ cha",
"parentHostPickerEmpty": "Không tìm thấy máy chủ phù hợp",
"collapseSubHosts": "Thu gọn các máy chủ con",
"expandSubHosts": "Mở rộng máy chủ con",
"cannotNestUnderDescendant": "Không thể lồng một máy chủ vào bên trong máy chủ con của chính nó.",
"movedToParent": "Đã di chuyển {{count}} máy chủ vào \"{{parent}}\"",
"newFolder": "Thư mục mới",
"createFolderTitle": "Tạo thư mục",
"editFolderTitle": "Sửa thư mục",
"folderDialogDescription": "Chọn tên, màu sắc và biểu tượng. Dùng / để lồng thư mục.",
"folderNameLabel": "Tên thư mục",
"folderNamePlaceholder": "VD: Production/Web",
"folderNestingHint": "Sử dụng / để phân cách các cấp và tạo thư mục lồng.",
"folderNameDuplicate": "Đã có một thư mục với tên này tồn tại ở đây.",
"folderColor": "Màu",
"folderIcon": "Biểu tượng",
"folderCredential": "Chứng chỉ",
"folderCredentialNone": "Chưa được cấp chứng chỉ.",
"folderCredentialHint": "Các máy chủ trong thư mục này sử dụng phương thức xác thực \"Thông tin đăng nhập đã lưu\" mà không chọn thông tin đăng nhập riêng sẽ kế thừa thông tin đăng nhập này.",
"folderPreview": "Xem trước",
"folderNameFallback": "Thư mục không tên",
"createFolderButton": "Tạo thư mục",
"saveFolderButton": "Lưu thư mục",
"cancel": "Hủy",
"iconSearchPlaceholder": "Tìm kiếm biểu tượng...",
"openAllSessions": "Mở tất cả phiên",
"editFolder": "Chỉnh sửa thư mục",
"deleteFolder": "Xóa thư mục",
"selectFolder": "Chọn tất cả các máy chủ trong thư mục",
"deselectFolder": "Bỏ chọn tất cả máy chủ trong thư mục",
"folderSaved": "Đã lưu thư mục",
"failedToSaveFolder": "Không thể lưu thư mục",
"folderDeleted": "Đã xóa thư mục \"{{name}}\"",
"deleteFolderConfirm": "Xóa \"{{name}}\" và {{count}} máy chủ trong đó? Thao tác này không thể hoàn tác.",
"failedToMoveHosts": "Không thể di chuyển máy chủ",
"failedToReorder": "Không thể đặt hàng lại",
"expandAll": "Mở rộng tất cả thư mục",
"collapseAll": "Thu gọn tất cả thư mục",
"moreActions": "Khác",
"groupBy": "Nhóm theo",
"GroupByFolder": "Thư mục",
"GroupByTag": "Thẻ",
"GroupByStatus": "Trạng thái",
"GroupByProtocol": "Giao thức",
"GroupByAuth": "Loại xác thực",
"groupUngrouped": "Không nhóm",
"customizeSidebar": "Tùy chỉnh thanh bên",
"customizeSidebarDescription": "Chọn cách hiển thị và hoạt động của danh sách máy chủ.",
"customizeDensityTitle": "Tỉ trọng",
"customizeBehaviorTitle": "Hành vi",
"customizeSortHint": "Chức năng sắp xếp và nhóm nằm trong menu sắp xếp và nhóm trên thanh công cụ.",
"densityComfortableDesc": "Thông tin chi tiết hơn cho mỗi máy chủ: địa chỉ, thẻ và mức sử dụng tài nguyên.",
"densityCompactDesc": "Mỗi dòng tương ứng với một máy chủ, đối với danh sách dài hơn.",
"display": "Trưng bày",
"displayDensity": "Tỉ trọng",
"displayDensityComfortable": "Thoải mái",
"displayDensityCompact": "Nhỏ gọn",
"displayShowTags": "Hiển thị thẻ",
"displayTrayOnClick": "Mở các thao tác khi nhấp chuột (thay vì khi di chuột)",
"actionsVisibility": "Hiển thị hành động của máy chủ",
"actionsVisibilityDesc": "Chọn thời điểm các thao tác trên máy chủ mở rộng. Chọn nhấp chuột để khôi phục hành vi nhấp chuột để mở rộng trước đó.",
"actionsAlways": "Luôn hiển thị",
"actionsOnly": "Chỉ cần kết nối, phần còn lại chỉ cần nhấp chuột.",
"actionsHover": "Hiển thị khi di chuột",
"actionsClick": "Nhấp để mở rộng/thu gọn",
"openOnDoubleClick": "Mở bằng cách nhấp đúp chuột",
"openOnDoubleClickDesc": "Yêu cầu nhấp đúp chuột để mở phiên máy chủ thay vì chỉ nhấp chuột một lần.",
"deletedHost": "Đã xóa {{name}}",
"copiedToClipboard": "Đã sao chép vào bộ nhớ tạm",
"terminalUrlCopied": "Đã sao chép URL Terminal",
"fileManagerUrlCopied": "Đã sao chép URL Trình quản lý tệp",
"tunnelUrlCopied": "Đã sao chép URL Đường hầm",
"dockerUrlCopied": "Đã sao chép URL Docker",
"hostMetricsUrlCopied": "Đã sao chép URL Chỉ số máy chủ",
"tmuxMonitorUrlCopied": "Đã sao chép URL Tmux Monitor",
"rdpUrlCopied": "Đã sao chép URL RDP",
"openNativeRdp": "Mở bằng Windows Remote Desktop",
"nativeRdpOpened": "Đã mở bằng Windows Remote Desktop",
"nativeRdpFailed": "Không thể mở Windows Remote Desktop",
"vncUrlCopied": "Đã sao chép URL VNC",
"telnetUrlCopied": "Đã sao chép URL Telnet",
"remoteDesktopUrlCopied": "Đã sao chép URL Remote Desktop",
"expandActions": "Mở rộng thao tác",
"collapseActions": "Thu gọn thao tác",
"wakeOnLanAction": "Wake on LAN",
"wakeOnLanSuccess": "Đã gửi gói tin Magic đến {{name}}",
"wakeOnLanError": "Không thể gửi gói tin Magic",
"cloneHostAction": "Sao chép Host",
"copyAddress": "Sao chép địa chỉ",
"copyLink": "Sao chép liên kết",
"copyTerminalUrlAction": "Sao chép URL Terminal",
"copyFileManagerUrlAction": "Sao chép URL File Manager",
"copyTunnelUrlAction": "Sao chép URL Tunnel",
"copyDockerUrlAction": "Sao chép URL Docker",
"copyHostMetricsUrlAction": "Sao chép URL Host Metrics",
"copyTmuxMonitorUrlAction": "Sao chép URL Tmux Monitor",
"copyRdpUrlAction": "Sao chép URL RDP",
"copyVncUrlAction": "Sao chép URL VNC",
"copyTelnetUrlAction": "Sao chép URL Telnet",
"copyRemoteDesktopUrlAction": "Sao chép URL Remote Desktop",
"deleteCredentialConfirm": "Xóa thông tin xác thực \"{{name}}\"?",
"deletedCredential": "Đã xóa {{name}}",
"deleteHostsConfirm": "Xóa {{count}} host{{plural}}? Hành động này không thể hoàn tác.",
"movedToRoot": "Đã chuyển về thư mục gốc",
"enableTerminalFeature": "Bật Terminal",
"disableTerminalFeature": "Tắt Terminal",
"enableFilesFeature": "Bật Files",
"disableFilesFeature": "Tắt Files",
"enableTunnelsFeature": "Bật Tunnels",
"disableTunnelsFeature": "Tắt Tunnels",
"enableDockerFeature": "Bật Docker",
"disableDockerFeature": "Tắt Docker",
"enableProxmoxFeature": "Bật Proxmox",
"disableProxmoxFeature": "Tắt Proxmox",
"addTagsPlaceholder": "Thêm thẻ...",
"authDetails": "Chi tiết xác thực",
"credType": "Loại",
"generateKeyPairDesc": "Tạo cặp khóa mới, khóa riêng tư và công khai sẽ được tự động điền.",
"generatingKey": "Đang tạo...",
"generateLabel": "Tạo {{label}}",
"uploadFileBtn": "Tải tệp lên",
"keyPassphraseOptional": "Cụm mật khẩu khóa (Tuỳ chọn)",
"sshPublicKeyOptional": "Khóa công khai SSH (Tuỳ chọn)",
"publicKeyGenerated": "Đã tạo khóa công khai",
"failedToGeneratePublicKey": "Không thể suy ra khóa công khai",
"publicKeyCopied": "Đã sao chép khóa công khai",
"keyPairGenerated": "Đã tạo cặp khóa {{label}}",
"failedToGenerateKeyPair": "Không thể tạo cặp khóa",
"searchHostsPlaceholder": "Tìm kiếm máy chủ, địa chỉ, thẻ…",
"refreshBtn": "Làm mới",
"addTag": "Thêm thẻ...",
"deleteConfirmBtn": "Xoá",
"tunnelRequirementsText": "Máy chủ SSH phải có GatewayPorts yes, AllowTcpForwarding yes, và PermitRootLogin yes được đặt trong /etc/ssh/sshd_config.",
"deleteHostConfirm": "Xoá \"{{name}}\"?",
"enableAtLeastOneProtocol": "Bật ít nhất một giao thức ở trên để cấu hình cài đặt xác thực và kết nối.",
"keyPassphrase": "Cụm mật khẩu khóa",
"connectBtn": "Kết nối",
"disconnectBtn": "Ngắt kết nối",
"basicInformation": "Thông tin cơ bản",
"authDetailsSection": "Chi tiết xác thực",
"credTypeLabel": "Loại",
"hostsTab": "Máy chủ",
"credentialsTab": "Thông tin xác thực",
"selectMultiple": "Chọn nhiều",
"selectHosts": "Chọn máy chủ",
"connectionLabel": "Kết nối",
"authenticationLabel": "Xác thực",
"generateKeyPairTitle": "Tạo cặp khóa",
"generateKeyPairDescription": "Tạo cặp khóa mới, cả khóa riêng tư và khóa công khai sẽ được tự động điền.",
"generateFromPrivateKey": "Tạo từ khóa riêng tư",
"refreshBtn2": "Làm mới",
"exitSelectionTitle": "Thoát chọn",
"addHostBtn2": "Thêm máy chủ",
"addCredentialBtn2": "Thêm thông tin xác thực",
"checkingHostStatuses": "Đang kiểm tra trạng thái máy chủ...",
"pinnedSection": "Đã ghim",
"hostsExported": "Đã xuất máy chủ thành công",
"export": {
"menuItem": "Xuất khẩu...",
"title": "Máy chủ xuất khẩu",
"scope": "Phạm vi",
"scopeAll": "Tất cả",
"scopeSelected": "Đã chọn",
"searchHosts": "Tìm kiếm máy chủ...",
"include": "Bao gồm",
"groupConnection": "Sự liên quan",
"groupCredentials": "Thông tin xác thực",
"groupNotes": "Ghi chú",
"groupTags": "Thẻ & ghim",
"groupTunnels": "Đường hầm",
"groupJumpHosts": "Người dẫn chương trình Jump",
"groupQuickActions": "Hành động nhanh chóng",
"groupFeatureFlags": "Cờ tính năng",
"groupAdvanced": "Cấu hình nâng cao",
"preview": "Xem trước",
"moreHosts": "... {{count}} thêm máy chủ",
"summary": "{{selected}} trong số {{total}} máy chủ",
"credentialsIncluded": "bao gồm thông tin xác thực",
"credentialsExcluded": "thông tin xác thực bị loại trừ",
"noneSelected": "Chưa có máy chủ nào được chọn.",
"cancel": "Hủy bỏ",
"confirm": "Xuất khẩu",
"fetchFailed": "Không thể tải các máy chủ để xuất.",
"bulkButton": "Xuất khẩu"
},
"sampleDownloaded": "Đã tải tệp mẫu",
"failedToDeleteCredential2": "Xóa thông tin xác thực thất bại",
"noFolderOption": "(Không có thư mục)",
"nSelected": "{{count}} đã chọn",
"featuresMenu": "Tính năng",
"moveMenu": "Di chuyển",
"connectSelected": "Kết nối",
"cancelSelection": "Hủy",
"deletedCount": "Đã xóa {{count}} máy chủ",
"failedToDeleteCount": "Xóa {{count}} máy chủ thất bại",
"duplicatedHost": "Đã trùng lặp \"{{name}}\"",
"failedToDuplicateHost": "Không thể sao chép máy chủ",
"updatedCount": "Đã cập nhật {{count}} máy chủ",
"friendlyNameLabel": "Tên hiển thị",
"descriptionLabel": "Mô tả",
"loadingHost": "Đang tải máy chủ...",
"loadingHosts": "Đang tải các máy chủ...",
"loadingCredentials": "Đang tải thông tin xác thực...",
"noHostsYet": "Chưa có máy chủ nào",
"noHostsYetHint": "Thêm máy chủ để mở cửa sổ dòng lệnh, duyệt tập tin và xem số liệu.",
"noHostsMatchSearch": "Không có máy chủ nào khớp với tìm kiếm của bạn",
"hostNotFound": "Không tìm thấy máy chủ",
"searchHosts": "Tìm kiếm máy chủ...",
"sortHosts": "Sắp xếp Máy chủ",
"sortDefault": "Thứ tự mặc định",
"sortNameAsc": "Tên (A → Z)",
"sortNameDesc": "Tên (Z → A)",
"sortIpAsc": "Địa chỉ IP (Tăng dần)",
"sortIpDesc": "Địa chỉ IP (Giảm dần)",
"sortOnlineFirst": "Trực tuyến trước",
"sortOfflineFirst": "Ngoại tuyến trước",
"sortManual": "Hướng dẫn sử dụng (kéo để sắp xếp lại)",
"sortPinnedFirst": "Đã ghim trước",
"filterHosts": "Lọc Máy chủ",
"filterClearAll": "Xóa bộ lọc",
"filterStatusGroup": "Trạng thái",
"filterOnline": "Trực tuyến",
"filterOffline": "Ngoại tuyến",
"filterPinned": "Đã ghim",
"filterAuthGroup": "Loại xác thực",
"filterAuthPassword": "Mật khẩu",
"filterAuthKey": "Khóa SSH",
"filterAuthCredential": "Thông tin xác thực",
"filterAuthNone": "Không",
"filterAuthOpkssh": "OPKSSH",
"filterAuthStepca": "Bước CA",
"filterProtocolGroup": "Giao thức",
"filterProtocolSsh": "SSH",
"filterProtocolRdp": "RDP",
"filterProtocolVnc": "VNC",
"filterProtocolTelnet": "Telnet",
"filterFeaturesGroup": "Tính năng",
"filterFeatureTerminal": "Terminal",
"filterFeatureFileManager": "Trình quản lý file",
"filterFeatureTunnel": "Tunnel",
"filterFeatureDocker": "Docker",
"filterTagsGroup": "Thẻ",
"connectRdp": "RDP",
"connectVnc": "VNC",
"connectTelnet": "Telnet",
"editHostAction": "Chỉnh sửa máy chủ",
"moreOptions": "Nhiều tùy chọn hơn",
"shareHost": "Chia sẻ máy chủ",
"shareHostTitle": "Chia sẻ: {{name}}",
"shareFolder": "Chia sẻ thư mục",
"shareFolderTitle": "Chia sẻ thư mục: {{name}}",
"folderSharedSuccessfully": "Máy chủ dùng chung {{count}} trong thư mục",
"failedToShareFolder": "Không thể chia sẻ thư mục",
"sharing": {
"loadError": "Không thể tải dữ liệu chia sẻ. Vui lòng thử lại.",
"shareWithSection": "Chia sẻ với",
"usersTab": "Người dùng",
"rolesTab": "Vai trò",
"searchPlaceholder": "Tìm kiếm người dùng hoặc vai trò...",
"noMatches": "Không tìm thấy kết quả phù hợp",
"permissionLevelLabel": "Cấp độ quyền",
"levels": {
"connect": {
"label": "Kết nối",
"description": "Chỉ mở phiên: terminal, remote desktop, trình quản lý file, tunnel và Docker. Không truy cập cấu hình máy chủ."
},
"view": {
"label": "Xem",
"description": "Kết nối, cùng xem cấu hình máy chủ. Bí mật không bao giờ được hiển thị."
},
"edit": {
"label": "Chỉnh sửa",
"description": "Xem và chỉnh sửa cài đặt máy chủ không yêu cầu xác thực. Thông tin xác thực SSH của chủ sở hữu vẫn được giữ kín và chỉ dành riêng cho chủ sở hữu."
},
"manage": {
"label": "Quản lý",
"description": "Chỉnh sửa, và chia sẻ máy chủ với người khác, thay đổi cấp độ quyền và thu hồi quyền truy cập."
}
},
"expiryLabel": "Hết hạn truy cập",
"expiry": {
"never": "Không bao giờ",
"oneHour": "1 giờ",
"oneDay": "24 giờ",
"sevenDays": "7 ngày",
"thirtyDays": "30 ngày",
"custom": "Tùy chỉnh"
},
"customHoursPlaceholder": "Số giờ cho đến khi hết hạn truy cập",
"shareButton": "Chia sẻ",
"shareWithCount": "Chia sẻ ({{count}})",
"currentAccess": "Truy cập hiện tại",
"noAccessEntries": "Máy chủ này chưa được chia sẻ",
"folderRulesTitle": "Áp dụng cho các máy chủ được thêm vào sau này.",
"folderRulesHint": "Các quyền truy cập này vẫn nằm trong thư mục: một máy chủ được tạo hoặc di chuyển vào thư mục đó (hoặc thư mục con) sẽ tự động có quyền truy cập tương tự. Việc xóa một quy tắc chỉ ngăn chặn việc kế thừa quyền truy cập trong tương lai.",
"folderRuleRemove": "Ngừng kế thừa",
"folderShareSummary": "Được chia sẻ {{shared}} trong số {{total}} máy chủ trong thư mục này",
"grantedBy": "Được cấp bởi",
"expires": "Hết hạn",
"expired": "Đã hết hạn",
"never": "Không bao giờ",
"revoke": "Thu hồi",
"accessUpdated": "Đã cập nhật quyền truy cập",
"accessUpdateFailed": "Cập nhật quyền truy cập thất bại",
"sharedBadge": "Đã chia sẻ",
"sharedBadgeTooltip": "Được chia sẻ bởi {{owner}} (quyền truy cập {{level}})",
"viewOnlyBanner": "Máy chủ này được {{owner}} chia sẻ cho bạn với quyền xem. Cấu hình chỉ đọc.",
"sharedEditBanner": "Máy chủ này được {{owner}} chia sẻ cho bạn với quyền chỉnh sửa. Thay đổi áp dụng cho máy chủ thực; tham chiếu xác thực chỉ có thể được thay đổi bởi chủ sở hữu.",
"ownerOnlyControl": "Chỉ chủ sở hữu máy chủ mới có thể thay đổi",
"ownerAuthPrivate": "Thông tin xác thực SSH của chủ sở hữu máy chủ là riêng tư. Sử dụng tùy chọn “Thiết lập xác thực SSH cá nhân” từ menu máy chủ để chọn thông tin đăng nhập của riêng bạn.",
"ownerAuthShared": "Chủ sở hữu máy chủ đã chia sẻ thông tin xác thực SSH cho máy chủ này. Bạn có thể sử dụng thông tin đó hoặc chọn thông tin đăng nhập của riêng mình từ mục “Thiết lập xác thực SSH cá nhân”.",
"authOverrideAction": "Thiết lập xác thực SSH cá nhân",
"authOverrideActionProtocol": "Thiết lập xác thực cá nhân {{protocol}}",
"authOverrideTitle": "Xác thực SSH cá nhân",
"authOverrideTitleProtocol": "Xác thực cá nhân {{protocol}}",
"authOverrideDescriptionPrivate": "Thông tin đăng nhập SSH của chủ sở hữu máy chủ được giữ bí mật. Hãy chọn một trong các thông tin đăng nhập đã lưu của bạn để kết nối với {{host}}.",
"authOverrideDescriptionShared": "Sử dụng thông tin xác thực do chủ sở hữu máy chủ cung cấp, hoặc thay thế nó bằng một trong những thông tin đăng nhập đã lưu của bạn để kết nối với {{host}}.",
"authOverrideCredentialLabel": "Thông tin xác thực",
"useSharedAuthentication": "Sử dụng xác thực máy chủ dùng chung",
"noPersonalCredential": "Không có giấy tờ chứng nhận cá nhân",
"authOverrideNoCredentials": "Bạn chưa lưu thông tin đăng nhập SSH nào. Hãy tạo một thông tin đăng nhập trong mục Thông tin đăng nhập để kết nối với các máy chủ yêu cầu xác thực.",
"authOverrideRequired": "Máy chủ này yêu cầu bạn nhập một trong những thông tin đăng nhập đã lưu trước khi có thể kết nối.",
"authOverridePrivateHint": "Thông tin đăng nhập này chỉ dành riêng cho bạn. Chủ sở hữu máy chủ và những người nhận khác không thể xem hoặc sử dụng nó.",
"authOverrideSaved": "Thông tin xác thực SSH cá nhân đã được lưu.",
"authOverrideCleared": "Xác thực SSH cá nhân đã bị xóa.",
"authOverrideClearedToShared": "Sử dụng xác thực máy chủ dùng chung",
"authOverrideLoadError": "Không thể tải thông tin xác thực SSH của bạn. Vui lòng thử lại.",
"authOverrideSaveError": "Không thể lưu thông tin xác thực SSH của bạn."
},
"guac": {
"connection": "Kết nối",
"authentication": "Xác thực",
"storedCredential": "Thông tin xác thực đã lưu",
"noCredential": "Không có thông tin xác thực (thông tin trực tiếp bên dưới)",
"authMethod": "Phương thức xác thực",
"authTypeDirect": "Trực tiếp",
"authTypeCredential": "Thông tin xác thực",
"authTypeNone": "Không có",
"authTypeNoneDesc": "Thông tin đăng nhập của bạn không được lưu trữ. Bạn sẽ được yêu cầu nhập tên người dùng và mật khẩu mỗi khi kết nối; chúng không được lưu lại.",
"selectCredential": "Chọn thông tin xác thực...",
"connectionSettings": "Cài đặt kết nối",
"displaySettings": "Cài đặt hiển thị",
"audioSettings": "Cài đặt âm thanh",
"rdpPerformance": "Hiệu suất RDP",
"deviceRedirection": "Chuyển hướng thiết bị",
"session": "Phiên làm việc",
"gateway": "Gateway",
"remoteApp": "RemoteApp",
"clipboard": "Clipboard",
"sessionRecording": "Ghi phiên",
"wakeOnLan": "Wake-on-LAN",
"vncSettings": "Cài đặt VNC",
"terminalSettings": "Cài đặt Terminal",
"rdpPort": "Cổng RDP",
"username": "Tên người dùng",
"password": "Mật khẩu",
"passwordSaved": "Mật khẩu đã được lưu, nhập để thay đổi",
"domain": "Miền",
"securityMode": "Chế độ bảo mật",
"colorDepth": "Độ sâu màu",
"width": "Chiều rộng",
"height": "Chiều cao",
"dpi": "DPI",
"resizeMethod": "Phương thức thay đổi kích thước",
"clientName": "Tên máy khách",
"initialProgram": "Chương trình ban đầu",
"serverLayout": "Bố cục máy chủ",
"timezone": "Múi giờ",
"loadBalanceInfo": "Thông tin cân bằng tải / Cookie",
"loadBalanceInfoDesc": "Cookie RD Connection Broker dùng cho cân bằng tải cụm RDS (vd: tsv://MS Terminal Services Plugin.1.CollectionName)",
"guacdProxy": "Proxy guacd",
"guacdHostname": "Máy chủ guacd",
"guacdHostnamePlaceholder": "Mặc định toàn cục",
"guacdPort": "Cổng guacd",
"guacdProxyDesc": "Ghi đè phiên bản guacd toàn cục cho kết nối này. Để trống để sử dụng guacd được cấu hình toàn cục.",
"gatewayHostname": "Tên máy chủ gateway",
"gatewayPort": "Cổng gateway",
"gatewayUsername": "Tên người dùng gateway",
"gatewayPassword": "Mật khẩu gateway",
"gatewayDomain": "Miền gateway",
"remoteAppProgram": "Chương trình RemoteApp",
"workingDirectory": "Thư mục làm việc",
"arguments": "Tham số",
"normalizeLineEndings": "Chuẩn hóa kết thúc dòng",
"recordingPath": "Đường dẫn ghi",
"recordingName": "Tên bản ghi",
"macAddress": "Địa chỉ MAC",
"broadcastAddress": "Địa chỉ broadcast",
"udpPort": "Cổng UDP",
"waitTimeS": "Thời gian chờ (s)",
"driveName": "Tên ổ đĩa",
"drivePath": "Đường dẫn ổ đĩa",
"ignoreCertificate": "Bỏ qua chứng chỉ",
"ignoreCertificateDesc": "Cho phép kết nối đến máy chủ có chứng chỉ tự ký",
"forceLossless": "Ép buộc Lossless",
"forceLosslessDesc": "Ép buộc mã hóa ảnh không mất dữ liệu (chất lượng cao hơn, tốn băng thông)",
"disableAudio": "Tắt âm thanh",
"disableAudioDesc": "Tắt tất cả âm thanh từ phiên từ xa",
"enableAudioInput": "Bật đầu vào âm thanh (micro)",
"enableAudioInputDesc": "Chuyển tiếp micro cục bộ đến phiên từ xa",
"wallpaper": "Hình nền",
"wallpaperDesc": "Hiển thị hình nền desktop (tắt để cải thiện hiệu suất)",
"theming": "Chủ đề",
"themingDesc": "Bật chủ đề và kiểu dáng trực quan",
"fontSmoothing": "Làm mịn phông chữ",
"fontSmoothingDesc": "Bật kết xuất phông chữ ClearType",
"fullWindowDrag": "Kéo toàn bộ cửa sổ",
"fullWindowDragDesc": "Hiển thị nội dung cửa sổ khi kéo",
"desktopComposition": "Tổ hợp màn hình nền",
"desktopCompositionDesc": "Bật hiệu ứng kính Aero",
"menuAnimations": "Hiệu ứng menu",
"menuAnimationsDesc": "Bật hiệu ứng mờ và trượt của menu",
"disableBitmapCaching": "Tắt bộ nhớ đệm bitmap",
"disableBitmapCachingDesc": "Tắt bộ nhớ đệm bitmap (có thể giúp tránh lỗi hiển thị)",
"disableOffscreenCaching": "Tắt bộ nhớ đệm ngoài màn hình",
"disableOffscreenCachingDesc": "Tắt bộ nhớ đệm ngoài màn hình",
"disableGlyphCaching": "Tắt bộ nhớ đệm glyph",
"disableGlyphCachingDesc": "Tắt bộ nhớ đệm glyph",
"enableGfx": "Bật GFX",
"enableGfxDesc": "Sử dụng pipeline đồ họa RemoteFX",
"enablePrinting": "Bật in",
"enablePrintingDesc": "Chuyển hướng máy in cục bộ đến phiên từ xa",
"enableDriveRedirection": "Bật chuyển hướng ổ đĩa",
"enableDriveRedirectionDesc": "Ánh xạ thư mục cục bộ thành ổ đĩa trong phiên từ xa",
"createDrivePath": "Tạo đường dẫn ổ đĩa",
"createDrivePathDesc": "Tự động tạo thư mục nếu chưa tồn tại",
"disableDownload": "Tắt tải xuống",
"disableDownloadDesc": "Ngăn tải file từ phiên từ xa",
"disableUpload": "Tắt tải lên",
"disableUploadDesc": "Ngăn tải file lên phiên từ xa",
"enableTouch": "Bật cảm ứng",
"enableTouchDesc": "Bật chuyển tiếp đầu vào cảm ứng",
"consoleSession": "Phiên console",
"consoleSessionDesc": "Kết nối tới console (phiên 0) thay vì phiên mới",
"sendWolPacket": "Gửi gói WOL",
"sendWolPacketDesc": "Gửi gói magic để đánh thức máy trước khi kết nối",
"disableCopy": "Tắt sao chép",
"disableCopyDesc": "Ngăn sao chép văn bản từ phiên từ xa",
"disablePaste": "Tắt dán",
"disablePasteDesc": "Ngăn dán văn bản vào phiên từ xa",
"createPathIfMissing": "Tạo đường dẫn nếu thiếu",
"createPathIfMissingDesc": "Tự động tạo thư mục ghi hình",
"excludeOutput": "Loại trừ đầu ra",
"excludeOutputDesc": "Không ghi hình màn hình (chỉ metadata)",
"excludeMouse": "Loại trừ chuột",
"excludeMouseDesc": "Không ghi lại chuyển động chuột",
"includeKeystrokes": "Bao gồm thao tác phím",
"includeKeystrokesDesc": "Ghi lại thao tác phím thô cùng với đầu ra màn hình",
"vncPort": "Cổng VNC",
"vncPassword": "Mật khẩu VNC",
"vncUsernameOptional": "Tên người dùng (tùy chọn)",
"vncLeaveBlank": "Để trống nếu không cần",
"cursorMode": "Chế độ con trỏ",
"swapRedBlue": "Hoán đổi Đỏ/Xanh",
"swapRedBlueDesc": "Hoán đổi kênh màu đỏ và xanh (khắc phục một số lỗi màu)",
"readOnly": "Chỉ đọc",
"readOnlyDesc": "Xem màn hình từ xa mà không gửi đầu vào",
"telnetPort": "Cổng Telnet",
"terminalType": "Loại terminal",
"fontName": "Tên phông chữ",
"fontSize": "Cỡ chữ",
"colorScheme": "Bảng màu",
"backspaceKey": "Phím Backspace",
"saveHostFirst": "Lưu máy chủ trước.",
"sharingOptionsAfterSave": "Tùy chọn chia sẻ khả dụng sau khi máy chủ đã được lưu.",
"permissionLevel": "Mức quyền",
"typeHeader": "Loại",
"targetHeader": "Mục tiêu",
"permissionHeader": "Quyền",
"cancelBtn": "Hủy",
"savingBtn": "Đang lưu...",
"updateHostBtn": "Cập nhật máy chủ",
"addHostBtn": "Thêm máy chủ"
},
"arrangeUnlockedSwitchedToManual": "Đã chuyển sang chế độ sắp xếp thủ công để đơn hàng của bạn được giữ nguyên.",
"dragToRearrange": "Kéo để sắp xếp lại",
"arrangeUnlocked": "Mở khóa chức năng kéo để sắp xếp lại.",
"tabWebUi": "Giao diện người dùng web",
"webUiEndpointLabel": "Điểm cuối {{number}}",
"webUiIntegration": "Giao diện người dùng web",
"webUiEndpointsSection": "Điểm cuối",
"webUiRequirementsText": "Trình duyệt của bạn sẽ mở một điểm cuối trực tiếp, vì vậy cổng của nó phải có thể truy cập được từ đây. Thay vào đó, Termix sẽ mở một đường hầm SSH thông qua kết nối SSH của máy chủ này, vì vậy cổng chỉ cần có thể truy cập được từ máy chủ đó.",
"enableWebUi": "Kích hoạt các điểm cuối web",
"enableWebUiDesc": "Mở giao diện web của máy chủ này từ thanh bên.",
"webUiAddEndpoint": "Thêm điểm cuối",
"webUiAddress": "Địa chỉ",
"webUiOpening": "Khai mạc",
"webUiBindHostDesc": "Đây là nơi phần máy chủ liên kết với phần máy khách. Để trống trường 127.0.0.1, chỉ máy chạy Termix mới có thể truy cập được.",
"webUiBindHostExposed": "Địa chỉ này có thể truy cập được từ bên ngoài máy Termix, vì vậy bất kỳ ai có thể truy cập được cổng này đều có thể sử dụng giao diện web này mà không cần đăng nhập.",
"webUiBindHostUnreachable": "Trình duyệt của bạn không thể truy cập 127.0.0.1 trên máy đang chạy Termix, vì vậy điểm cuối này sẽ không tải được. Hãy sử dụng địa chỉ mà máy đó có thể trả lời, chẳng hạn như 0.0.0.0.",
"webUiBindHostSharesSessionCookie": "Từ trình duyệt này, yêu cầu chuyển tiếp sẽ được truy cập tại cùng tên máy chủ mà Termix đang được phục vụ, do đó dịch vụ đường hầm sẽ nhận được phiên Termix của bạn. Cookie bỏ qua cổng. Điểm cuối này sẽ từ chối mở ở đây; nó hoạt động từ ứng dụng Termix dành cho máy tính để bàn hoặc khi Termix được mở tại localhost.",
"webUiLocalPort": "Cảng địa phương",
"webUiLocalPortAuto": "Tự động",
"webUiLocalPortDesc": "Chọn cổng mà bản ghi chuyển tiếp lắng nghe. Để trống để hệ thống tự chọn, hoặc đặt một cổng khi cần biết trước cổng, ví dụ như một container công bố cổng đó.",
"webUiNewEndpointLabel": "Điểm cuối mới",
"webUiErrorLabelRequired": "Điểm cuối {{row}} cần một nhãn.",
"webUiErrorLabelDuplicate": "Mỗi điểm cuối cần một tên khác nhau.",
"webUiErrorPortRange": "Điểm cuối {{row}} cần một cổng nằm trong khoảng từ 1 đến 65535.",
"webUiErrorPathInvalid": "Điểm cuối {{row}} có đường dẫn không hợp lệ. Hãy sử dụng đường dẫn như /admin.",
"webUiLabel": "Nhãn",
"webUiScheme": "Cơ chế",
"webUiPort": "Cảng",
"webUiPath": "Con đường",
"webUiAccess": "Truy cập",
"webUiAccessDirect": "Trực tiếp",
"webUiAccessTunnel": "Đường hầm SSH",
"webUiAccessTunnelUnavailable": "Đường hầm SSH cần có SSH được bật trên máy chủ này và nguồn kết nối là thiết bị này.",
"webUiRender": "Mở trong",
"webUiRenderExternal": "Cửa sổ màn hình nền riêng biệt",
"webUiRenderEmbedded": "Viên nén Termix",
"webUiRenderEmbeddedDesc": "Việc nhúng trang web chỉ mang tính chất tham khảo: một số giao diện web từ chối tải trong khung, và quá trình đăng nhập dựa vào cookie cùng trang có thể bị lặp lại. Trình duyệt bên ngoài luôn hoạt động bình thường.",
"webUiIgnoreCert": "Cho phép chứng chỉ không hợp lệ",
"webUiIgnoreCertDesc": "Chỉ áp dụng cho các điểm cuối trực tiếp. Giao diện vòng lặp đã được miễn trừ, vì vậy điều này không ảnh hưởng đến các điểm cuối đường hầm.",
"webUiRemoveEndpoint": "Xóa điểm cuối",
"webUiOpenFailed": "Không thể mở điểm cuối web"
},
"commandPalette": {
"searchPlaceholder": "Tìm kiếm máy chủ, lệnh hoặc cài đặt...",
"quickActions": "Hành động nhanh",
"navigation": "Điều hướng",
"orShortcut": "hoặc",
"hostManager": "Quản lý máy chủ",
"hostManagerDesc": "Quản lý, thêm hoặc sửa máy chủ",
"addNewHost": "Thêm máy chủ mới",
"addNewHostDesc": "Đăng ký máy chủ mới",
"adminSettings": "Cài đặt quản trị",
"adminSettingsDesc": "Cấu hình tùy chọn hệ thống và người dùng",
"userProfile": "Hồ sơ người dùng",
"userProfileDesc": "Quản lý tài khoản và tùy chọn của bạn",
"addCredential": "Thêm thông tin xác thực",
"addCredentialDesc": "Lưu trữ khóa SSH hoặc mật khẩu",
"tmuxMonitor": "Giám sát Tmux",
"tmuxMonitorDesc": "Giám sát phiên tmux trên các máy chủ",
"snippets": "Những đoạn trích",
"runSnippetDesc": "Chạy trong tab cửa sổ terminal đang hoạt động",
"noSnippetsFound": "Không tìm thấy đoạn mã nào khớp với \"{{search}}\"",
"recentActivity": "Hoạt động gần đây",
"serversAndHosts": "Máy chủ & Host",
"noHostsFound": "Không tìm thấy máy chủ nào khớp với \"{{search}}\"",
"links": "Liên kết",
"navigate": "Điều hướng",
"select": "Chọn",
"toggleWith": "Chuyển đổi với",
"localTerminal": "Ga địa phương",
"localTerminalDesc": "Mở cửa sổ dòng lệnh trên máy tính này."
},
"splitScreen": {
"paneEmpty": "Ngăn {{index}} - trống",
"noTabAssigned": "Không có tab nào được gán",
"focusedPane": "Ngăn đang hoạt động"
},
"connections": {
"noConnections": "Không có kết nối nào",
"noConnectionsDesc": "Mở terminal, trình quản lý tệp hoặc máy tính từ xa để xem kết nối tại đây",
"connectedFor": "Đã kết nối trong {{duration}}",
"connected": "Đã kết nối",
"disconnected": "Đã ngắt kết nối",
"closeTab": "Đóng tab",
"closeConnection": "Đóng kết nối",
"forgetTab": "Quên",
"removeBackground": "Xóa",
"reconnect": "Kết nối lại",
"reopenTab": "Mở lại",
"sectionOpen": "Đang mở",
"sectionBackground": "Nền",
"backgroundDesc": "Phiên kết nối sẽ duy trì trong {{minutes}} phút sau khi ngắt kết nối và có thể được kết nối lại.",
"persisted": "Đã duy trì trong nền",
"expiresIn": "Hết hạn trong {{duration}}",
"search": "Tìm kiếm kết nối...",
"noSearchResults": "Không có kết nối nào khớp với tìm kiếm của bạn",
"rename": "Đổi tên phiên",
"sectionSharedWithMe": "Đã chia sẻ với tôi",
"sharedBy": "Được chia sẻ bởi {{username}}",
"join": "Tham gia",
"sharedSessionLabel": "{{hostName}} (được chia sẻ)"
},
"collab": {
"createRoom": "Phòng mới",
"roomName": "Tên phòng",
"persistentRoom": "Phòng bền vững",
"persistentRoomHint": "Các phòng họp được lưu lại sẽ vẫn hiển thị sau khi cuộc họp kết thúc và có thể được sử dụng lại.",
"noRooms": "Chưa có phòng nào. Hãy tạo một phòng để bắt đầu cuộc họp.",
"openRoom": "Mở",
"endRoom": "Kết thúc cuộc họp",
"leaveRoom": "Rời khỏi",
"deleteMember": "Di dời",
"removeMember": "Xóa {{name}}",
"removeMemberTitle": "Xóa thành viên này?",
"removeMemberDescription": "{{name}} sẽ mất quyền truy cập vào phòng này ngay lập tức. Bất kỳ trình xem SSH nào đang hoạt động sẽ bị ngắt kết nối.",
"invite": "Mời",
"inviteTitle": "Mời thành viên",
"members": "Thành viên",
"membersPanel": "Thành viên phòng và yêu cầu kiểm soát",
"membersWithCount": "Thành viên ({{count}})",
"online": "trực tuyến",
"offline": "ngoại tuyến",
"you": "(Bạn)",
"hostBadge": "Chủ nhà",
"presenterBadge": "Giới thiệu",
"present": "Hiện tại",
"presentTitle": "Hãy lên sân khấu",
"presentHost": "Chủ nhà",
"searchHosts": "Tìm kiếm máy chủ",
"noHostsFound": "Không tìm thấy máy chủ nào khả dụng.",
"presentProtocol": "Giao thức",
"stopPresenting": "Dừng thuyết trình",
"takeOver": "Tiếp quản",
"takeOverConfirmTitle": "Bạn muốn thay thế bài thuyết trình hiện tại?",
"takeOverDescription": "{{name}} đang trình bày. Việc tiếp quản sẽ ngắt kết nối mọi người khỏi sân khấu đó.",
"emptyStage": "Hiện chưa có ai thuyết trình. Hãy lên sân khấu để chia sẻ một phiên thảo luận.",
"stageLoading": "Kết nối với sân khấu...",
"stageEnded": "Buổi thuyết trình kết thúc.",
"roomEnded": "Cuộc họp này đã kết thúc.",
"presenterLabel": "{{name}} đang trình bày",
"guestLink": "Liên kết khách",
"guestLinkOn": "Link dành cho khách đã được bật. Bất cứ ai có link đều có thể xem chương trình.",
"guestLinkOff": "Liên kết khách đã bị tắt.",
"copyLink": "Sao chép liên kết",
"rotateLink": "Xoay liên kết",
"disableLink": "Vô hiệu hóa liên kết",
"rotateLinkConfirmTitle": "Xoay liên kết khách?",
"rotateLinkDescription": "Kết nối hiện tại sẽ ngừng hoạt động ngay lập tức. Các máy khách SSH đang kết nối sẽ bị ngắt kết nối.",
"disableLinkConfirmTitle": "Vô hiệu hóa liên kết khách?",
"disableLinkDescription": "Những người xem SSH ẩn danh sẽ bị ngắt kết nối ngay lập tức và liên kết hiện tại sẽ ngừng hoạt động.",
"linkCopied": "Liên kết đã được sao chép",
"roles": "Vai trò",
"users": "Người dùng",
"searchUsers": "Tìm kiếm người dùng",
"endConfirmTitle": "Kết thúc cuộc họp này?",
"endDescription": "{{name}} sẽ kết thúc đối với tất cả mọi người và không thể mở lại.",
"endPersistentDescription": "Buổi thuyết trình đang diễn ra tại {{name}} sẽ dừng lại. Phòng vẫn có thể được sử dụng lại.",
"deleteRoom": "Xóa phòng",
"deleteConfirmTitle": "Xóa phòng này?",
"deleteDescription": "{{name}} sẽ bị xóa vĩnh viễn đối với tất cả mọi người và không thể hoàn tác.",
"invitedTo": "Bạn được mời đến \"{{name}}\"",
"guest": {
"title": "Cuộc họp",
"waiting": "Đang chờ người dẫn chương trình...",
"linkInvalid": "Liên kết dành cho khách này không hợp lệ hoặc cuộc họp đã kết thúc."
},
"reopenFromPanel": "Tab cuộc họp này đã hết hạn. Vui lòng mở lại phòng từ mục Cuộc họp.",
"requestControl": "Yêu cầu kiểm soát",
"cancelControlRequest": "Yêu cầu hủy bỏ",
"controlQueue": "Yêu cầu kiểm soát",
"noControlRequests": "Không có yêu cầu nào đang chờ xử lý.",
"grantControlTo": "Trao quyền điều khiển cho {{name}}",
"dismissControlRequest": "Bỏ qua yêu cầu điều khiển của {{name}}",
"releaseControl": "Kiểm soát giải phóng",
"grantControl": "Trao quyền kiểm soát",
"revokeControl": "Giành lại quyền kiểm soát",
"controlRequestedBy": "{{name}} yêu cầu quyền điều khiển",
"grant": "Khoản trợ cấp",
"controlBadge": "Trong tầm kiểm soát",
"youArePresenting": "Bạn đang thuyết trình ở một tab khác. Hãy dừng thuyết trình để nhường sân khấu.",
"created": "Phòng được tạo",
"invited": "Các thành viên được mời",
"roomTab": "Cuộc họp"
},
"sessionSharing": {
"guestView": {
"loading": "Đang kết nối đến phiên chia sẻ...",
"linkInvalid": "Liên kết chia sẻ này không hợp lệ, đã hết hạn hoặc đã bị thu hồi.",
"rateLimited": "Đã thử quá nhiều lần, vui lòng thử lại sau.",
"sessionEnded": "Phiên này đã kết thúc",
"readOnlyBadge": "Chỉ xem",
"ownerLabel": "Chủ nhà"
},
"modalTitle": "Chia sẻ phiên họp",
"shareButton": "Chia sẻ",
"notReadyToShare": "Buổi học chưa sẵn sàng để chia sẻ.",
"modeTab": {
"link": "Liên kết",
"user": "Người dùng"
},
"linkModeDescription": "Bất kỳ ai có liên kết này đều có thể tham gia, không cần tài khoản.",
"userModeDescription": "Chia sẻ với một người dùng cụ thể đã có quyền truy cập vào máy chủ này. Nếu họ chưa có quyền truy cập, hãy chia sẻ máy chủ với họ trước hoặc sử dụng liên kết thay thế. Sau khi chia sẻ, phiên làm việc sẽ xuất hiện trong tab Kết nối của họ.",
"permissionLevel": {
"label": "Cấp độ quyền hạn",
"readOnly": "Chỉ đọc",
"readOnlyDescription": "Có thể xem phiên trực tiếp nhưng không thể gõ chữ hoặc tương tác.",
"readWrite": "Đọc-viết",
"readWriteDescription": "Có thể nhập liệu và tương tác với phiên làm việc giống như chủ sở hữu."
},
"expiryLabel": "Liên kết hết hạn",
"createLinkButton": "Tạo liên kết",
"createShareButton": "Chia sẻ với người dùng",
"searchUsersPlaceholder": "Tìm kiếm người dùng...",
"noUsersFound": "Không tìm thấy người dùng nào",
"linkCreated": "Đã tạo liên kết chia sẻ",
"linkCopied": "Liên kết đã được sao chép vào clipboard",
"copyLink": "Sao chép liên kết",
"shareCreated": "Phiên họp đã được chia sẻ. Nó sẽ xuất hiện trong tab Kết nối của họ.",
"shareFailed": "Không thể tạo chia sẻ",
"userLacksHostAccess": "Người dùng đó chưa có quyền truy cập vào máy chủ này. Hãy chia sẻ thông tin máy chủ với họ trước, hoặc sử dụng liên kết thay thế.",
"activeShares": "Cổ phiếu tích cực",
"noActiveShares": "Hiện không có cổ phiếu nào đang được giao dịch trong phiên này.",
"revoke": "Thu hồi",
"revokeConfirmTitle": "Thu hồi cổ phần này?",
"revokeConfirmDescription": "Bất kỳ ai sử dụng thư mục chia sẻ này sẽ mất quyền truy cập ngay lập tức.",
"revoked": "Cổ phần đã bị thu hồi",
"revokeFailed": "Không thể thu hồi cổ phần",
"joinCount": "{{count}} tham gia",
"joinCount_other": "{{count}} tham gia",
"expiresAt": "Hết hạn {{date}}",
"linkShareBadge": "Liên kết",
"userShareBadge": "Người dùng: {{username}}",
"loadSharesFailed": "Không thể tải các chia sẻ đang hoạt động"
},
"guacamole": {
"connecting": "Đang kết nối đến phiên {{type}}...",
"checkingGuacd": "Kiểm tra dịch vụ máy tính từ xa...",
"requestingToken": "Yêu cầu mã thông báo kết nối {{type}}...",
"openingSession": "Khai mạc phiên {{type}}...",
"negotiating": "Đàm phán bằng cái bắt tay {{type}}...",
"sessionReady": "{{type}} phiên đã sẵn sàng",
"connectionError": "Lỗi kết nối",
"connectionFailed": "Kết nối thất bại",
"failedToConnect": "Không lấy được mã token kết nối",
"hostNotFound": "Không tìm thấy máy chủ",
"noHostSelected": "Chưa chọn máy chủ",
"reconnect": "Kết nối lại",
"retry": "Thử lại",
"guacdUnavailable": "Dịch vụ máy tính từ xa (guacd) không khả dụng. Vui lòng đảm bảo guacd đang chạy, có thể truy cập và được cấu hình đúng trong cài đặt quản trị.",
"credentialPromptTitle": "Nhập thông tin đăng nhập RDP",
"credentialPromptDescription": "Máy chủ này được thiết lập để yêu cầu thông tin đăng nhập khi kết nối. Thông tin này chỉ được sử dụng cho phiên này và không được lưu lại.",
"connect": "Kết nối",
"ctrlAltDel": "Ctrl+Alt+Del",
"files": {
"title": "Tệp ổ đĩa",
"parent": "Thư mục cha",
"refresh": "Làm cho khỏe lại",
"empty": "Thư mục này trống",
"listFailed": "Không thể đọc thư mục này.",
"download": "Tải xuống",
"downloadFailed": "Tải xuống không thành công {{name}}",
"upload": "Tải lên tệp",
"uploading": "Đang tải lên {{name}}...",
"uploaded": "Đã tải lên {{name}}",
"uploadFailed": "Tải lên không thành công {{name}}",
"uploadDisabled": "Chức năng tải lên đã bị vô hiệu hóa cho kết nối này.",
"driveUnavailable": "Hãy bật tính năng chuyển hướng ổ đĩa RDP trước khi tải lên tệp.",
"driveNotWritable": "guacd không thể ghi vào thư mục ổ đĩa. Hãy kiểm tra GUACD_DRIVE_PATH (hoặc Đường dẫn ổ đĩa của máy chủ) và quyền truy cập của nó.",
"dropToUpload": "Kéo thả tệp để tải lên"
},
"toolbar": {
"ctrlAltDel": "Ctrl+Alt+Del",
"winL": "Win+L (Khóa màn hình)",
"winKey": "Phím Windows",
"superL": "Super+L (Màn hình khóa)",
"superKey": "Siêu chìa khóa",
"super": "Siêu",
"cmdL": "Cmd+L (Khóa màn hình)",
"cmdKey": "Phím lệnh",
"cmd": "Lệnh",
"ctrl": "Ctrl",
"alt": "Alt",
"shift": "Shift",
"win": "Win",
"stickyActive": "{{key}} (đang giữ - nhấn để nhả)",
"stickyInactive": "{{key}} (nhấn để giữ)",
"esc": "Escape",
"tab": "Tab",
"home": "Home",
"end": "End",
"pageUp": "Page Up",
"pageDown": "Page Down",
"arrowUp": "Arrow Up",
"arrowDown": "Arrow Down",
"arrowLeft": "Arrow Left",
"arrowRight": "Arrow Right",
"fnToggle": "Phím chức năng",
"reconnect": "Kết nối lại phiên",
"collapse": "Thu gọn thanh công cụ",
"expand": "Mở rộng thanh công cụ",
"dragHandle": "Kéo để di chuyển",
"hide": "Ẩn tùy chọn này trong phiên làm việc hiện tại. Để tắt vĩnh viễn, hãy mở Cài đặt máy chủ → Chung → Thanh công cụ kết nối.",
"zoomIn": "Phóng to",
"zoomOut": "Thu nhỏ",
"resetZoom": "Đặt lại thu phóng",
"fitToScreen": "Vừa với màn hình",
"switchToTrackpad": "Chuyển sang chế độ bàn di chuột (kéo để di chuyển con trỏ, chạm để nhấp chuột)",
"switchToTouch": "Chuyển sang chế độ cảm ứng (chạm trực tiếp vào vị trí bạn muốn nhấp chuột)"
}
},
"terminal": {
"sessionExpiredNotice": "Phiên làm việc trước của bạn trên {{host}} đã hết hạn sau {{minutes}} phút bị ngắt kết nối; shell và mọi thứ đang chạy trong đó đều đã biến mất. Hãy bật Auto-Tmux trên máy chủ này để duy trì các phiên làm việc.",
"sessionExpiredNoticeNoMinutes": "Phiên làm việc trước của bạn trên {{host}} đã hết hạn khi bị ngắt kết nối; shell và mọi thứ đang chạy trong đó đều đã biến mất. Hãy bật Auto-Tmux trên máy chủ này để duy trì các phiên làm việc.",
"enableAutoTmuxAction": "Bật Auto-Tmux",
"autoTmuxEnabled": "Tính năng Auto-Tmux đã được bật cho {{host}}. Tính năng này sẽ được áp dụng từ lần kết nối tiếp theo.",
"autoTmuxEnableFailed": "Không thể bật Auto-Tmux.",
"connect": "Kết nối đến máy chủ",
"clear": "Xóa",
"paste": "Dán",
"reconnect": "Kết nối lại",
"connectionLost": "Mất kết nối",
"connected": "Đã kết nối",
"clipboardWriteFailed": "Sao chép vào clipboard thất bại. Đảm bảo trang được phục vụ qua HTTPS hoặc localhost.",
"clipboardReadFailed": "Đọc từ clipboard thất bại. Đảm bảo quyền truy cập clipboard đã được cấp.",
"clipboardHttpWarning": "Không thể đọc nội dung clipboard. Một số trình duyệt hạn chế quyền truy cập clipboard khi không sử dụng HTTPS - hãy thử Ctrl+V hoặc sử dụng HTTPS để chạy Termix.",
"passwordPromptFillTitle": "Điền mật khẩu đã lưu vào dòng nhắc này?",
"unknownError": "Lỗi không xác định đã xảy ra",
"websocketError": "Lỗi kết nối WebSocket",
"connecting": "Đang kết nối...",
"noHostSelected": "Chưa chọn máy chủ",
"reconnecting": "Đang kết nối lại... ({{attempt}}/{{max}})",
"reconnected": "Đã kết nối lại thành công",
"tmuxSessionCreated": "Đã tạo phiên tmux: {{name}}",
"tmuxSessionAttached": "Đã gắn vào phiên tmux: {{name}}",
"tmuxUnavailable": "tmux chưa được cài đặt trên máy chủ từ xa, chuyển sang shell tiêu chuẩn",
"tmuxSessionPickerTitle": "Phiên tmux",
"tmuxSessionPickerDesc": "Các phiên tmux hiện có trên máy chủ này. Chọn một phiên để gắn lại hoặc tạo phiên mới.",
"tmuxWindows": "Cửa sổ",
"tmuxWindowCount": "{{count}} cửa sổ",
"tmuxAttached": "Các máy khách đã gắn kết",
"tmuxAttachedCount": "{{count}} đã gắn kết",
"tmuxLastActivity": "Hoạt động cuối",
"tmuxTimeJustNow": "vừa xong",
"tmuxTimeMinutes": "{{count}} phút trước",
"tmuxTimeHours": "{{count}} giờ trước",
"tmuxTimeDays": "{{count}} ngày trước",
"tmuxCreateNew": "Tạo phiên mới",
"tmuxCopyHint": "Điều chỉnh lựa chọn và nhấn Enter để sao chép vào clipboard",
"tmuxDetach": "Ngắt khỏi phiên tmux",
"tmuxDetached": "Đã ngắt khỏi phiên tmux",
"searchPlaceholder": "Tìm thấy",
"searchCaseSensitive": "Hộp diêm",
"searchWholeWord": "Ghép toàn bộ từ",
"searchRegex": "Sử dụng biểu thức chính quy",
"searchNoResults": "Không có kết quả",
"searchResultCount": "{{index}} của {{count}}",
"searchNext": "Trận đấu tiếp theo (Nhập)",
"searchPrevious": "Kết quả khớp trước đó (Shift+Enter)",
"searchClose": "Đóng (Thoát)",
"maxReconnectAttemptsReached": "Đã đạt số lần kết nối lại tối đa",
"closeTab": "Đóng",
"connectionTimeout": "Hết thời gian kết nối",
"terminalTitle": "Terminal - {{host}}",
"terminalWithPath": "Terminal - {{host}}:{{path}}",
"runTitle": "Đang chạy {{command}} - {{host}}",
"totpRequired": "Yêu cầu xác thực hai yếu tố",
"totpCodeLabel": "Mã xác minh",
"totpVerify": "Xác minh",
"mfaPromptRequired": "Yêu cầu xác thực",
"mfaPushRequired": "Yêu cầu xác thực đẩy",
"mfaMenuPlaceholder": "Nhập câu trả lời của bạn",
"mfaWaitingApproval": "Đang chờ phê duyệt trên thiết bị của bạn...",
"mfaSendRequest": "Gửi yêu cầu",
"warpgateAuthRequired": "Yêu cầu xác thực Warpgate",
"warpgateSecurityKey": "Khóa bảo mật",
"warpgateAuthUrl": "URL xác thực",
"warpgateOpenBrowser": "Mở trong trình duyệt",
"warpgateContinue": "Tôi đã hoàn tất xác thực",
"certAuthRequired": "{{provider}} Cần đăng nhập",
"opksshAuthRequired": "Yêu cầu xác thực OPKSSH",
"opksshAuthDescription": "Hoàn tất xác thực trên trình duyệt để tiếp tục. Phiên làm việc này sẽ có hiệu lực trong 24 giờ.",
"opksshOpenBrowser": "Mở trình duyệt để xác thực",
"opksshWaitingForAuth": "Đang chờ xác thực trên trình duyệt...",
"opksshAuthenticating": "Đang xử lý xác thực...",
"opksshTimeout": "Xác thực đã hết thời gian chờ. Vui lòng thử lại.",
"opksshAuthFailed": "Xác thực thất bại. Vui lòng kiểm tra thông tin đăng nhập và thử lại.",
"opksshSignInWith": "Đăng nhập bằng {{provider}}",
"tailscaleCheckRequired": "Cần xác thực Tailscale",
"tailscaleCheckDescription": "Tailscale SSH yêu cầu kiểm tra bổ sung. Vui lòng xác thực trong trình duyệt của bạn để tiếp tục.",
"tailscaleCheckOpenBrowser": "Mở trình duyệt để xác thực.",
"tailscaleCheckWaiting": "Đang chờ xác thực Tailscale...",
"tailscaleCheckTimeout": "Quá trình xác thực Tailscale đã hết hạn. Vui lòng thử lại.",
"vaultAuthTitle": "Yêu cầu đăng nhập Vault",
"vaultAuthDescription": "Một cửa sổ đã mở để đăng nhập vào HashiCorp Vault. Hoàn tất đăng nhập ở đó; kết nối này sẽ tự động tiếp tục.",
"vaultAuthFailed": "Xác thực Vault thất bại. Vui lòng thử lại.",
"vaultReopen": "Mở lại cửa sổ đăng nhập",
"sudoPasswordPopupTitle": "Nhập mật khẩu?",
"linkDialogTitle": "Mở liên kết",
"linkDialogOpen": "Mở",
"linkDialogCopy": "Sao chép",
"websocketAbnormalClose": "Kết nối đóng đột ngột. Có thể do sự cố cấu hình reverse proxy hoặc SSL. Vui lòng kiểm tra nhật ký máy chủ.",
"connectionLogTitle": "Nhật ký kết nối",
"connectionLogCopy": "Sao chép nhật ký vào clipboard",
"connectionLogEmpty": "Chưa có nhật ký kết nối",
"connectionLogWaiting": "Đang chờ nhật ký kết nối...",
"connectionLogCopied": "Đã sao chép nhật ký kết nối vào clipboard",
"connectionLogCopyFailed": "Sao chép nhật ký vào clipboard thất bại",
"connectionRejected": "Kết nối bị máy chủ từ chối. Vui lòng kiểm tra xác thực và cấu hình mạng.",
"hostKeyRejected": "Xác minh khóa máy chủ SSH bị từ chối. Đã hủy kết nối.",
"sessionTakenOver": "Phiên đã được mở trong tab khác. Đang kết nối lại...",
"split": {
"splitTab": "Chia tab",
"addToSplit": "Thêm vào phần chia",
"removeFromSplit": "Xóa khỏi phần chia"
}
},
"fileManager": {
"noHostSelected": "Chưa chọn máy chủ",
"initializingEditor": "Đang khởi tạo trình soạn thảo...",
"file": "Tệp",
"folder": "Thư mục",
"uploadFile": "Tải tệp lên",
"downloadFile": "Tải xuống",
"extractArchive": "Giải nén lưu trữ",
"extractingArchive": "Đang giải nén {{name}}...",
"archiveExtractedSuccessfully": "{{name}} đã được giải nén thành công",
"extractFailed": "Giải nén thất bại",
"compressFile": "Nén tập tin",
"compressFiles": "Nén tập tin",
"compressFilesDesc": "Nén {{count}} mục vào một tệp nén",
"archiveName": "Tên tệp lưu trữ",
"enterArchiveName": "Nhập tên tệp lưu trữ...",
"compressionFormat": "Định dạng nén",
"selectedFiles": "Tập tin đã chọn",
"andMoreFiles": "và {{count}} tập tin khác...",
"compress": "Nén",
"compressingFiles": "Đang nén {{count}} mục vào {{name}}...",
"filesCompressedSuccessfully": "{{name}} đã được tạo thành công",
"compressFailed": "Nén thất bại",
"edit": "Chỉnh sửa",
"preview": "Xem trước",
"previous": "Trước",
"next": "Tiếp",
"pageXOfY": "Trang {{current}} / {{total}}",
"zoomOut": "Thu nhỏ",
"zoomIn": "Phóng to",
"newFile": "Tập tin mới",
"newFolder": "Thư mục mới",
"rename": "Đổi tên",
"uploading": "Đang tải lên...",
"uploadingFile": "Đang tải lên {{name}}...",
"fileName": "Tên tập tin",
"folderName": "Tên thư mục",
"fileUploadedSuccessfully": "Tập tin \"{{name}}\" đã được tải lên thành công",
"failedToUploadFile": "Tải tập tin lên thất bại",
"uploadingFolderFiles": "Đang tải lên {{count}} tập tin...",
"uploadedFolderFiles": "Đã tải lên {{count}} tập tin thành công",
"uploadedFolderPartial": "Đã tải lên {{uploaded}} tập tin, {{failed}} thất bại",
"fileDownloadedSuccessfully": "Tập tin \"{{name}}\" đã được tải xuống thành công",
"failedToDownloadFile": "Tải tập tin xuống thất bại",
"fileCreatedSuccessfully": "Tập tin \"{{name}}\" đã được tạo thành công",
"folderCreatedSuccessfully": "Thư mục \"{{name}}\" đã được tạo thành công",
"failedToCreateItem": "Không thể tạo mục",
"operationFailed": "Thao tác {{operation}} thất bại đối với {{name}}: {{error}}",
"failedToResolveSymlink": "Không thể theo dõi symlink",
"itemsDeletedSuccessfully": "Đã xóa thành công {{count}} mục",
"failedToDeleteItems": "Không thể xóa các mục",
"sudoPasswordRequired": "Yêu cầu mật khẩu quản trị",
"enterSudoPassword": "Nhập mật khẩu sudo để tiếp tục thao tác này",
"sudoPassword": "Mật khẩu sudo",
"sudoOperationFailed": "Thao tác sudo thất bại",
"sudoAuthFailed": "Xác thực sudo thất bại",
"dragFilesToUpload": "Kéo tệp vào đây để tải lên",
"dropToUploadHere": "Kéo thả để tải lên tại đây",
"dropToDownloadHere": "Kéo thả để tải xuống tại đây",
"localFiles": "Địa phương",
"showLocalFiles": "Hiển thị các tệp cục bộ (chế độ chia đôi màn hình)",
"hideLocalFiles": "Ẩn các tệp cục bộ",
"localHome": "Thư mục trang chủ",
"localPathPlaceholder": "Đường dẫn thư mục cục bộ",
"localShowHidden": "Hiển thị các tệp ẩn",
"localHideHidden": "Ẩn các tệp tin ẩn",
"localRevealInFileManager": "Hiển thị trong trình quản lý tệp hệ thống",
"localCannotOpenFolder": "Không thể mở thư mục",
"localItemCount": "{{count}} mục",
"localSelectedCount": "{{count}} đã chọn",
"back": "Mặt sau",
"forward": "Phía trước",
"up": "Hướng lên",
"kind": "Loại",
"localUploadingProgress": "Đang tải lên {{current}} trong số {{total}}",
"localDownloadingProgress": "Đang tải xuống {{current}} của {{total}}",
"localTransferInFlight": "{{count}} ngay lập tức",
"localPreparingDownload": "Đang chuẩn bị tải xuống...",
"localTransferCancelled": "Giao dịch bị hủy",
"localNothingToTransfer": "Không có gì để chuyển",
"localUploadComplete": "Đã tải lên {{count}} tập tin",
"localUploadFailed": "Tải lên thất bại",
"localUploadPartial": "Đã tải lên {{done}} tập tin, {{failed}} thất bại",
"localDownloadComplete": "Đã tải xuống {{count}} tập tin",
"localDownloadFailed": "Tải xuống thất bại",
"localDownloadPartial": "Đã tải xuống {{done}} tập tin, {{failed}} thất bại",
"localReplaceExistingPrompt": "{{count}} mục đã tồn tại trong thư mục này. Bạn có muốn thay thế chúng không?",
"localReplace": "Thay thế",
"localSkipExisting": "Nhảy",
"localSkippedExisting": "Đã bỏ qua {{count}} mục hiện có",
"localUnsafeNamesSkipped": "Đã bỏ qua {{count}} mục mà tên của chúng không thể sử dụng trên máy tính này.",
"localOpen": "Mở",
"localOpenFolder": "Mở thư mục",
"localUploadToRemote": "Tải lên máy chủ",
"localUploadToRemoteMany": "Tải lên {{count}} mục lên máy chủ",
"localMoveToTrash": "Chuyển vào thùng rác",
"localMoveToTrashMany": "Di chuyển {{count}} mục vào Thùng rác",
"localTrashConfirmSingle": "Di chuyển \"{{name}}\" vào Thùng rác?",
"localTrashConfirmFolder": "Di chuyển thư mục \"{{name}}\" và tất cả nội dung bên trong vào Thùng rác?",
"localTrashConfirmMany": "Di chuyển {{count}} mục vào Thùng rác?",
"localTrashed": "Đã chuyển {{count}} mục vào Thùng rác",
"localTrashFailed": "Không thể chuyển vào Thùng rác",
"localRenameFailed": "Đổi tên không thành công",
"localCreateFailed": "Không thể tạo mục",
"goToParentFolder": "Đi đến thư mục cha",
"resizeSidebar": "Kéo để thay đổi kích thước thanh bên (nhấp đúp để đặt lại về kích thước ban đầu)",
"resizeLocalPane": "Kéo chuột để thay đổi kích thước khung cục bộ (nhấp đúp chuột để đặt lại về kích thước ban đầu)",
"columns": "Cột",
"columnsHint": "Nhấp chuột phải để chọn cột",
"emptyFolder": "Thư mục này trống",
"searchFiles": "Tìm kiếm tệp...",
"upload": "Tải lên",
"selectHostToStart": "Chọn máy chủ để bắt đầu quản lý tệp",
"sshRequiredForFileManager": "Trình quản lý tệp yêu cầu SSH. Máy chủ này không bật SSH.",
"failedToConnect": "Kết nối SSH thất bại",
"failedToLoadDirectory": "Không thể tải thư mục",
"noSSHConnection": "Không có kết nối SSH",
"copy": "Sao chép",
"cut": "Cắt",
"paste": "Dán",
"copyPath": "Sao chép đường dẫn",
"copyPaths": "Sao chép các đường dẫn",
"delete": "Xóa",
"properties": "Thuộc tính",
"refresh": "Làm mới",
"downloadFiles": "Tải {{count}} tệp xuống trình duyệt",
"copyFiles": "Sao chép {{count}} mục",
"cutFiles": "Cắt {{count}} mục",
"deleteFiles": "Xóa {{count}} mục",
"filesCopiedToClipboard": "Đã sao chép {{count}} mục vào clipboard",
"filesCutToClipboard": "Đã cắt {{count}} mục vào clipboard",
"pathCopiedToClipboard": "Đã sao chép đường dẫn vào clipboard",
"pathsCopiedToClipboard": "Đã sao chép {{count}} đường dẫn vào clipboard",
"failedToCopyPath": "Không thể sao chép đường dẫn vào clipboard",
"copyFolderLink": "Sao chép liên kết đến thư mục",
"copyCurrentFolderLink": "Sao chép liên kết đến thư mục hiện tại",
"folderLinkCopied": "Đã sao chép liên kết thư mục vào clipboard",
"failedToCopyFolderLink": "Không thể sao chép liên kết thư mục",
"movedItems": "Đã di chuyển {{count}} mục",
"failedToDeleteItem": "Không thể xóa mục",
"itemRenamedSuccessfully": "Đã đổi tên {{type}} thành công",
"failedToRenameItem": "Không thể đổi tên mục",
"download": "Tải xuống",
"openExternalEditor": "Mở bên ngoài",
"chooseExternalEditor": "Chọn trình soạn thảo bên ngoài",
"externalEditorSelected": "Đã chọn trình soạn thảo bên ngoài",
"externalEditorDesktopOnly": "Trình soạn thảo bên ngoài chỉ khả dụng trong ứng dụng desktop",
"externalEditorOpened": "Đã mở bằng trình soạn thảo bên ngoài. Lưu ở đó sẽ tải các thay đổi lên máy chủ.",
"failedToOpenExternalEditor": "Không thể mở trình soạn thảo bên ngoài",
"failedToSelectExternalEditor": "Không thể chọn trình soạn thảo bên ngoài",
"permissions": "Quyền",
"size": "Kích thước",
"modified": "Đã sửa",
"path": "Đường dẫn",
"confirmDelete": "Bạn có chắc chắn muốn xóa {{name}}?",
"permissionDenied": "Quyền bị từ chối",
"serverError": "Lỗi máy chủ",
"fileSavedSuccessfully": "Đã lưu tệp thành công",
"failedToSaveFile": "Không thể lưu tệp",
"confirmDeleteSingleItem": "Bạn có chắc chắn muốn xóa vĩnh viễn \"{{name}}\"?",
"confirmDeleteMultipleItems": "Bạn có chắc chắn muốn xóa vĩnh viễn {{count}} mục?",
"confirmDeleteMultipleItemsWithFolders": "Bạn có chắc chắn muốn xóa vĩnh viễn {{count}} mục? Điều này bao gồm các thư mục và nội dung của chúng.",
"confirmDeleteFolder": "Bạn có chắc chắn muốn xóa vĩnh viễn thư mục \"{{name}}\" và tất cả nội dung của nó?",
"permanentDeleteWarning": "Hành động này không thể hoàn tác. (Các) mục sẽ bị xóa vĩnh viễn khỏi máy chủ.",
"moveToTrashWarning": "Các mục này sẽ được chuyển vào Thùng rác Termix và có thể được khôi phục trước khi thời hạn lưu giữ hết hạn.",
"itemsMovedToTrash": "{{count}} mục đã được chuyển vào Thùng rác",
"trash": "Rác",
"trashDescription": "Các mục đã xóa sẽ được lưu giữ trong {{days}} ngày trên máy chủ này.",
"trashLoadFailed": "Không thể tải Thùng rác",
"trashEmpty": "Thùng rác trống",
"trashRestore": "Khôi phục",
"trashRestored": "Đã khôi phục {{name}}",
"trashRestoreFailed": "Không thể khôi phục mục. Đường dẫn gốc có thể đã tồn tại.",
"trashDeletePermanently": "Xóa vĩnh viễn",
"trashDeleteConfirm": "Xóa vĩnh viễn {{name}}? Thao tác này không thể hoàn tác.",
"trashPermanentlyDeleted": "Đã xóa vĩnh viễn {{name}}",
"trashDeleteFailed": "Không thể xóa mục vĩnh viễn",
"trashEmptyAction": "Đổ rác",
"trashEmptyConfirm": "Xóa vĩnh viễn mọi mục trong Thùng rác? Thao tác này không thể hoàn tác.",
"trashEmptied": "Thùng rác đã được đổ",
"trashRetention": "Tự động dọn dẹp sau (ngày)",
"trashRetentionSaved": "Cập nhật thời gian lưu trữ rác",
"trashRetentionFailed": "Không thể cập nhật thời gian lưu trữ thùng rác.",
"trashUnavailableConfirm": "Không thể chuyển mục này vào Thùng rác, thường là do nó nằm trên hệ thống tệp khác hoặc yêu cầu quyền quản trị. Thay vào đó, hãy xóa vĩnh viễn mục này?",
"recent": "Gần đây",
"pinned": "Đã ghim",
"folderShortcuts": "Lối tắt thư mục",
"failedToReconnectSSH": "Không thể kết nối lại phiên SSH",
"openTerminalHere": "Mở terminal tại đây",
"run": "Chạy",
"openTerminalInFolder": "Mở terminal trong thư mục này",
"openTerminalInFileLocation": "Mở terminal tại vị trí tệp",
"runningFile": "Đang chạy - {{file}}",
"onlyRunExecutableFiles": "Chỉ chạy được tệp thực thi",
"directories": "Thư mục",
"removedFromRecentFiles": "Đã xóa \"{{name}}\" khỏi tệp gần đây",
"removeFailed": "Xóa thất bại",
"unpinnedSuccessfully": "Đã bỏ ghim \"{{name}}\" thành công",
"unpinFailed": "Bỏ ghim thất bại",
"removedShortcut": "Đã xóa lối tắt \"{{name}}\"",
"removeShortcutFailed": "Xóa lối tắt thất bại",
"clearedAllRecentFiles": "Đã xóa toàn bộ tệp gần đây",
"clearFailed": "Xóa thất bại",
"removeFromRecentFiles": "Xóa khỏi tệp gần đây",
"clearAllRecentFiles": "Xóa toàn bộ tệp gần đây",
"unpinFile": "Bỏ ghim tệp",
"removeShortcut": "Xóa lối tắt",
"pinFile": "Ghim tệp",
"addToShortcuts": "Thêm vào lối tắt",
"pasteFailed": "Dán thất bại",
"noUndoableActions": "Không có hành động hoàn tác được",
"undoCopySuccess": "Đã hoàn tác sao chép: Đã xóa {{count}} tệp đã sao chép",
"undoCopyFailedDelete": "Hoàn tác thất bại: Không thể xóa tệp đã sao chép",
"undoCopyFailedNoInfo": "Hoàn tác thất bại: Không tìm thấy thông tin tệp đã sao chép",
"undoMoveSuccess": "Đã hoàn tác di chuyển: Đã di chuyển {{count}} tệp về vị trí ban đầu",
"undoMoveFailedMove": "Hoàn tác thất bại: Không thể di chuyển tệp về vị trí cũ",
"undoMoveFailedNoInfo": "Hoàn tác thất bại: Không tìm thấy thông tin tệp đã di chuyển",
"undoDeleteNotSupported": "Không thể hoàn tác xóa: Tệp đã bị xóa vĩnh viễn khỏi máy chủ",
"undoTypeNotSupported": "Loại thao tác hoàn tác không được hỗ trợ",
"undoOperationFailed": "Thao tác hoàn tác thất bại",
"unknownError": "Lỗi không xác định",
"confirm": "Xác nhận",
"find": "Tìm kiếm...",
"replace": "Thay thế",
"downloadInstead": "Tải xuống thay thế",
"keyboardShortcuts": "Phím tắt",
"searchAndReplace": "Tìm & Thay thế",
"editing": "Chỉnh sửa",
"search": "Tìm kiếm",
"findNext": "Tìm tiếp",
"findPrevious": "Tìm trước",
"save": "Lưu",
"selectAll": "Chọn tất cả",
"undo": "Hoàn tác",
"redo": "Làm lại",
"moveLineUp": "Di chuyển dòng lên",
"moveLineDown": "Di chuyển dòng xuống",
"toggleComment": "Chuyển đổi chú thích",
"autoComplete": "Tự động hoàn thành",
"imageLoadError": "Lỗi tải ảnh",
"startTyping": "Bắt đầu nhập...",
"unknownSize": "Kích thước không xác định",
"fileIsEmpty": "Tệp trống",
"largeFileWarning": "Cảnh báo tệp lớn",
"largeFileWarningDesc": "Tệp này có kích thước {{size}}, có thể gây ra vấn đề hiệu suất khi mở dưới dạng văn bản.",
"fileNotFoundAndRemoved": "Tệp \"{{name}}\" không tìm thấy và đã bị xóa khỏi tệp gần đây/đã ghim",
"failedToLoadFile": "Lỗi tải tệp: {{error}}",
"serverErrorOccurred": "Đã xảy ra lỗi máy chủ. Vui lòng thử lại sau.",
"autoSaveFailed": "Tự động lưu không thành công",
"fileAutoSaved": "Tệp đã được tự động lưu",
"moveFileFailed": "Không thể di chuyển {{name}}",
"moveOperationFailed": "Thao tác di chuyển không thành công",
"canOnlyCompareFiles": "Chỉ có thể so sánh hai tệp",
"comparingFiles": "Đang so sánh tệp: {{file1}} và {{file2}}",
"dragFailed": "Thao tác kéo không thành công",
"filePinnedSuccessfully": "Tệp \"{{name}}\" đã được ghim thành công",
"pinFileFailed": "Không thể ghim tệp",
"fileUnpinnedSuccessfully": "Tệp \"{{name}}\" đã được bỏ ghim thành công",
"unpinFileFailed": "Không thể bỏ ghim tệp",
"shortcutAddedSuccessfully": "Đã thêm lối tắt thư mục \"{{name}}\" thành công",
"addShortcutFailed": "Không thể thêm lối tắt",
"operationCompletedSuccessfully": "Đã {{operation}} thành công {{count}} mục",
"operationCompleted": "Đã {{operation}} {{count}} mục",
"downloadFileSuccess": "Đã tải xuống tệp {{name}} thành công",
"downloadFileFailed": "Tải xuống thất bại",
"downloadingFile": "Đang tải xuống {{name}}…",
"downloadProgressBytes": "{{transferred}} / {{total}}",
"moveTo": "Di chuyển tới {{name}}",
"diffCompareWith": "So sánh khác biệt với {{name}}",
"dragOutsideToDownload": "Kéo ra ngoài cửa sổ để tải xuống ({{count}} tệp)",
"newFolderDefault": "Thư mục mới",
"newFileDefault": "Tệp mới.txt",
"successfullyMovedItems": "Đã di chuyển thành công {{count}} mục tới {{target}}",
"move": "Di chuyển",
"searchInFile": "Tìm trong tệp (Ctrl+F)",
"showKeyboardShortcuts": "Hiển thị phím tắt",
"decreaseFontSize": "Giảm cỡ chữ",
"increaseFontSize": "Tăng cỡ chữ",
"startWritingMarkdown": "Bắt đầu viết nội dung markdown...",
"loadingFileComparison": "Đang tải so sánh tệp...",
"reload": "Tải lại",
"compare": "So sánh",
"sideBySide": "Song song",
"inline": "Trong dòng",
"fileComparison": "So sánh tệp: {{file1}} vs {{file2}}",
"fileTooLarge": "Tệp quá lớn: {{error}}",
"sshConnectionFailed": "Kết nối SSH thất bại. Vui lòng kiểm tra kết nối tới {{name}} ({{ip}}:{{port}})",
"loadFileFailed": "Không thể tải tệp: {{error}}",
"connecting": "Đang kết nối...",
"connectedSuccessfully": "Đã kết nối thành công",
"totpVerificationFailed": "Xác minh TOTP thất bại",
"warpgateVerificationFailed": "Xác thực Warpgate thất bại",
"authenticationFailed": "Xác thực thất bại",
"incorrectPassphrase": "Cụm mật khẩu không đúng. Vui lòng thử lại.",
"verificationCodePrompt": "Mã xác minh:",
"changePermissions": "Thay đổi quyền",
"currentPermissions": "Quyền hiện tại",
"owner": "Chủ sở hữu",
"group": "Nhóm",
"others": "Khác",
"read": "Đọc",
"write": "Ghi",
"execute": "Thực thi",
"permissionsChangedSuccessfully": "Thay đổi quyền thành công",
"failedToChangePermissions": "Không thể thay đổi quyền",
"name": "Tên",
"sortByName": "Tên",
"sortByDate": "Ngày sửa đổi",
"sortBySize": "Kích thước",
"ascending": "Tăng dần",
"descending": "Giảm dần",
"root": "Thư mục gốc",
"new": "Mới",
"sortBy": "Sắp xếp theo",
"items": "Mục",
"selected": "Đã chọn",
"editor": "Soạn thảo",
"octal": "Bát phân",
"storage": "Lưu trữ",
"disk": "Đĩa",
"used": "Đã dùng",
"of": "của",
"toggleSidebar": "Ẩn/Hiện thanh bên",
"compactLayout": "Sử dụng bố cục nhỏ gọn",
"comfortableLayout": "Sử dụng bố cục thoải mái",
"cannotLoadPdf": "Không thể tải PDF",
"pdfLoadError": "Đã xảy ra lỗi khi tải tệp PDF này.",
"loadingPdf": "Đang tải PDF...",
"loadingPage": "Đang tải trang..."
},
"transfer": {
"copyToHost": "Sao chép đến máy chủ…",
"moveToHost": "Di chuyển đến máy chủ…",
"copyItemsToHost": "Sao chép {{count}} mục đến máy chủ…",
"moveItemsToHost": "Di chuyển {{count}} mục tới máy chủ…",
"noHostsConnected": "Không có máy chủ nào khác có Trình quản lý tệp khả dụng.",
"noHostsConnectedHint": "Thêm một máy chủ SSH khác đã bật Trình quản lý tệp trong Trình quản lý máy chủ.",
"selectDestinationHost": "Chọn máy chủ đích",
"destinationPath": "Đường dẫn đích",
"recentDestinations": "Đích gần đây",
"collapseRecentDestinations": "Thu gọn đích gần đây",
"expandRecentDestinations": "Mở rộng đích gần đây",
"browseFolders": "Duyệt thư mục đích",
"browseDestination": "Duyệt hoặc nhập đường dẫn",
"confirmCopy": "Sao chép",
"confirmMove": "Di chuyển",
"transferring": "Đang truyền tải…",
"progressVerifying": "Đang xác minh tính toàn vẹn của tệp…",
"progressBenchmarking": "Chọn tuyến đường chuyển tiếp nhanh nhất…",
"compressing": "Đang nén…",
"extracting": "Đang giải nén…",
"transferringItems": "Đang truyền tải {{current}}/{{total}} mục…",
"transferSuccess": "Truyền tải hoàn tất",
"transferError": "Truyền tải thất bại",
"transferPartial": "Truyền tải hoàn tất với {{count}} lỗi",
"transferPartialHint": "Không thể truyền tải: {{paths}}",
"itemsSummary": "{{count}} mục",
"destMustBeDirectory": "Đích phải là thư mục khi truyền tải nhiều mục",
"selectThisFolder": "Chọn thư mục này",
"browsePathWillBeCreated": "Thư mục này chưa tồn tại. Nó sẽ được tạo khi truyền tải bắt đầu.",
"browsePathError": "Không thể mở đường dẫn này trên máy chủ đích.",
"goUp": "Lên trên",
"copyFolderToHost": "Sao chép thư mục tới máy chủ…",
"moveFolderToHost": "Di chuyển thư mục tới máy chủ…",
"hostReady": "Sẵn sàng",
"hostConnecting": "Đang kết nối…",
"hostDisconnected": "Chưa kết nối",
"hostAuthRequired": "Yêu cầu xác thực — mở Trình quản lý tệp trên máy chủ này trước",
"hostConnectionFailed": "Kết nối thất bại",
"metricsTitle": "Thời gian truyền tải",
"metricsPrepare": "Chuẩn bị đích: {{duration}}",
"metricsCompress": "Nén tại nguồn: {{duration}}",
"metricsHopSourceRead": "Nguồn → máy chủ: {{throughput}}",
"metricsHopDestSftpWrite": "Máy chủ → đích (SFTP): {{throughput}}",
"metricsHopDestLocalWrite": "Máy chủ → đích (cục bộ): {{throughput}}",
"metricsTransfer": "Toàn trình: {{throughput}} ({{duration}})",
"metricsExtract": "Giải nén tại đích: {{duration}}",
"metricsVerify": "Đã xác thực SHA-256: {{duration}}",
"metricsRouteBenchmark": "Tìm đường dẫn — trực tiếp: {{direct}}, chuyển tiếp: {{relay}}",
"metricsSourceDelete": "Xóa khỏi nguồn: {{duration}}",
"metricsTotal": "Tổng: {{duration}}",
"progressCompressing": "Đang nén trên máy nguồn…",
"progressExtracting": "Đang giải nén tại đích…",
"progressTransferring": "Đang truyền dữ liệu…",
"progressReconnecting": "Đang kết nối lại…",
"parallelSegmentsLabel": "Làn truyền song song",
"parallelSegmentsOption": "{{count}} làn",
"parallelSegmentsHint": "Các tệp lớn được chia thành các khối 256 MB. Nhiều làn sử dụng các kết nối riêng biệt (như khởi chạy nhiều lần truyền) để tăng tổng thông lượng.",
"progressTotalSpeed": "{{speed}} tổng ({{lanes}} làn)",
"progressTransferringItems": "Đang truyền tệp ({{current}}/{{total}})…",
"progressBytes": "{{transferred}} / {{total}}",
"progressItems": "{{current}} / {{total}} tệp",
"sourceNotDeletedPartial": "Giữ tệp nguồn (truyền một phần)",
"jumpHostLimitation": "Cả hai máy chủ phải có thể truy cập từ máy chủ Termix. Không hỗ trợ định tuyến trực tiếp giữa các máy.",
"cancel": "Hủy",
"methodLabel": "Phương thức truyền",
"methodAuto": "Tự động",
"methodTar": "Lưu trữ tar",
"methodItemSftp": "SFTP từng tệp",
"methodAutoHint": "Chọn tar hoặc SFTP từng tệp dựa trên số lượng tệp, kích thước và khả năng nén. Tệp đơn lẻ luôn dùng SFTP truyền luồng.",
"methodTarHint": "Nén tại nguồn, truyền một tệp lưu trữ, giải nén tại đích. Yêu cầu tar trên cả hai máy Unix.",
"methodItemSftpHint": "Truyền từng tệp riêng lẻ qua SFTP. Hoạt động trên mọi máy, bao gồm Windows.",
"methodPreviewLoading": "Đang tính toán phương thức truyền…",
"methodPreviewError": "Không thể xem trước phương thức truyền. Máy chủ vẫn sẽ chọn phương thức khi bạn bắt đầu.",
"methodPreviewWillUseTar": "Sẽ dùng: Lưu trữ tar",
"methodPreviewWillUseItemSftp": "Sẽ dùng: SFTP từng tệp",
"methodPreviewScanSummary": "{{fileCount}} tệp, tổng {{totalSize}} (đã quét trên máy nguồn).",
"methodItemSftpLimitation": "Mỗi tệp sử dụng cùng một luồng SFTP như bản sao tệp đơn lẻ, lần lượt từng tệp một. Tiến trình được gộp chung cho tất cả tệp, do đó thanh tiến trình di chuyển chậm khi có tệp lớn.",
"methodReason": {
"user_item_sftp": "Bạn đã chọn SFTP từng tệp.",
"user_tar": "Bạn đã chọn dùng tar.",
"tar_unavailable": "Tar không có trên một hoặc cả hai máy — sẽ dùng SFTP từng tệp thay thế.",
"windows_host": "Có máy Windows — không dùng tar.",
"auto_multi_large": "Tự động: nhiều tệp bao gồm một tệp lớn ({{largestSize}}) có dữ liệu nén được — tar gộp thành một lần chuyển.",
"auto_single_large_in_archive": "Tự động: một tệp lớn ({{largestSize}}) trong tập này — SFTP từng tệp.",
"auto_many_incompressible": "Tự động: dữ liệu hầu như không nén được — SFTP từng tệp.",
"auto_many_files": "Tự động: nhiều tệp ({{fileCount}}) — tar giảm chi phí trên mỗi tệp.",
"auto_default": "Tự động: SFTP từng tệp cho tập này."
},
"progressCancel": "Hủy",
"progressCancelling": "Đang hủy…",
"progressStalled": "Đình trệ",
"resumedHint": "Đã kết nối lại với một tác vụ chuyển đang hoạt động được bắt đầu từ cửa sổ khác.",
"transferCancelled": "Đã hủy chuyển",
"transferCancelledCopyHint": "Các tệp chưa hoàn chỉnh có thể còn ở đích.",
"transferCancelledMoveHint": "Các tệp chưa hoàn chỉnh có thể còn ở đích. Tệp nguồn chưa bị xóa.",
"cleanupDestFiles": "Dọn dẹp đích",
"cleanupDestFilesSuccess": "Đã xóa các tệp chưa hoàn chỉnh ở đích",
"cleanupDestFilesPartial": "Không thể xóa một số tệp chưa hoàn chỉnh",
"cleanupDestFilesNothing": "Không có gì để dọn dẹp ở đích",
"cleanupDestFilesError": "Dọn dẹp thất bại",
"retryTransfer": "Thử lại",
"retryTransferError": "Thử lại thất bại",
"transferFailedRetryHint": "Dữ liệu chưa hoàn chỉnh được giữ ở đích. Thử lại sẽ tiếp tục khi kết nối được khôi phục."
},
"sftpTransfer": {
"title": "SFTP",
"description": "Truyền tệp giữa hai máy chủ SSH.",
"sourceServer": "Máy chủ nguồn",
"destinationServer": "Máy chủ đích",
"selectHost": "Chọn máy chủ",
"noHostSelected": "Chưa chọn máy chủ nào",
"move": "Di chuyển",
"copy": "Sao chép",
"upload": "Tải lên",
"itemsSelected": "{{count}} mục đã chọn",
"itemsSelected_other": "{{count}} mục đã chọn",
"ready": "Sẵn sàng",
"loadingHosts": "Đang tải máy chủ...",
"name": "Tên",
"modified": "Đã sửa đổi",
"size": "Kích cỡ",
"noFiles": "Không có tệp nào",
"open": "Mở",
"up": "Hướng lên",
"refresh": "Làm cho khỏe lại",
"copyToTarget": "Sao chép vào thư mục đích",
"rename": "Đổi tên",
"delete": "Xóa bỏ",
"editPermissions": "Chỉnh sửa quyền",
"createNewFolder": "Tạo thư mục mới",
"deleteSelectedItems": "Xóa các mục đã chọn",
"deleteConfirm": "Xóa mục đã chọn {{count}}?",
"deleteConfirm_other": "Xóa {{count}} mục đã chọn?",
"cancel": "Hủy bỏ",
"save": "Cứu",
"folderCreated": "Thư mục đã được tạo",
"itemRenamed": "Mục đã được đổi tên",
"actionFailed": "Hành động thất bại",
"itemsDeleted": "{{count}} mục đã bị xóa",
"itemsDeleted_other": "{{count}} mục đã bị xóa",
"deleteFailed": "Xóa không thành công",
"permissionsUpdated": "Quyền hạn đã được cập nhật",
"noRemoteSessionConnected": "Không có phiên kết nối từ xa nào được thiết lập.",
"failedToListFiles": "Không thể liệt kê các tệp.",
"failedToRefresh": "Không thể làm mới",
"destinationInsideSource": "Đường dẫn đích không được nằm bên trong đường dẫn nguồn đã chọn.",
"sameHostNoOp": "Thư mục nguồn và thư mục đích đều nằm trong cùng một thư mục."
},
"tunnels": {
"noSshTunnels": "Không có đường hầm SSH",
"createFirstTunnelMessage": "Bạn chưa tạo đường hầm SSH nào. Hãy cấu hình kết nối đường hầm trong Trình quản lý máy chủ để bắt đầu.",
"connected": "Đã kết nối",
"disconnected": "Đã ngắt kết nối",
"connecting": "Đang kết nối...",
"error": "Lỗi",
"canceling": "Đang hủy...",
"connect": "Kết nối",
"disconnect": "Ngắt kết nối",
"cancel": "Hủy",
"port": "Cổng",
"localPort": "Cổng cục bộ",
"remotePort": "Cổng từ xa",
"destinationPort": "Cảng đích",
"currentHostPort": "Cổng máy hiện tại",
"endpointPort": "Cổng điểm cuối",
"bindIp": "IP cục bộ",
"localAddress": "Địa chỉ địa phương",
"remoteAddress": "Địa chỉ từ xa",
"destinationAddress": "Địa chỉ đích",
"remoteBindAddress": "Địa chỉ liên kết từ xa",
"intermediateHost": "Máy chủ trung gian",
"endpointSshConfig": "Cấu hình SSH điểm cuối",
"endpointSshHost": "Máy chủ SSH điểm cuối",
"endpointSshHostPlaceholder": "Chọn máy chủ đã cấu hình",
"endpointSshHostRequired": "Chọn máy chủ SSH điểm cuối cho mỗi đường hầm máy khách.",
"attempt": "Lần thử {{current}} / {{max}}",
"nextRetryIn": "Thử lại sau {{seconds}} giây",
"clientTunnels": "Đường hầm máy khách",
"clientTunnel": "Đường hầm máy khách",
"addClientTunnel": "Thêm đường hầm máy khách",
"noClientTunnels": "Chưa có đường hầm máy khách nào được cấu hình trên máy này.",
"tunnelName": "Tên đường hầm",
"remoteHost": "Máy chủ từ xa",
"autoStart": "Tự động khởi động",
"clientAutoStartDesc": "Tự động khởi động khi mở ứng dụng máy khách và duy trì kết nối.",
"clientManualStartDesc": "Sử dụng nút Bắt đầu và Dừng trên dòng này. Termix sẽ không tự động mở.",
"clientRemoteServerNote": "Chuyển tiếp từ xa có thể yêu cầu AllowTcpForwarding và GatewayPorts trên máy chủ SSH điểm cuối. Cổng từ xa sẽ đóng khi máy này ngắt kết nối.",
"clientTunnelStarted": "Đường hầm máy khách đã khởi động",
"clientTunnelStopped": "Đường hầm máy khách đã dừng",
"tunnelTestSucceeded": "Kiểm tra đường hầm thành công",
"tunnelTestFailed": "Kiểm tra đường hầm thất bại",
"localSaved": "Đã lưu đường hầm máy khách",
"localSaveError": "Lưu đường hầm máy khách cục bộ thất bại",
"invalidBindIp": "IP cục bộ phải là địa chỉ IPv4 hợp lệ.",
"invalidLocalTargetIp": "IP đích cục bộ phải là địa chỉ IPv4 hợp lệ.",
"invalidRemoteAddress": "Cần có địa chỉ từ xa.",
"invalidLocalPort": "Cổng cục bộ phải nằm trong khoảng 1 đến 65535.",
"invalidRemotePort": "Cổng từ xa phải nằm trong khoảng 1 đến 65535.",
"invalidLocalTargetPort": "Cổng đích cục bộ phải nằm trong khoảng 1 đến 65535.",
"invalidEndpointPort": "Cổng điểm cuối phải nằm trong khoảng 1 đến 65535.",
"duplicateAutoStartBind": "Chỉ một đường hầm máy khách tự động có thể sử dụng {{bind}}.",
"manualControlError": "Cập nhật trạng thái đường hầm thất bại.",
"active": "Hoạt động",
"start": "Bắt đầu",
"stop": "Dừng",
"test": "Kiểm tra",
"type": "Loại đường hầm",
"typeLocal": "Cục bộ (-L)",
"typeRemote": "Từ xa (-R)",
"typeDynamic": "Động (-D)",
"typeServerLocalDesc": "Máy chủ hiện tại đến điểm cuối.",
"typeServerRemoteDesc": "Điểm cuối trở về máy chủ hiện tại.",
"typeClientLocalDesc": "Máy tính cục bộ đến điểm cuối.",
"typeClientRemoteDesc": "Điểm cuối trở về máy tính cục bộ.",
"typeClientDynamicDesc": "SOCKS trên máy tính cục bộ.",
"typeDynamicDesc": "Chuyển tiếp lưu lượng SOCKS5 CONNECT qua SSH",
"forwardDescriptionServerLocal": "Máy chủ hiện tại {{sourcePort}} → điểm cuối {{endpointPort}}.",
"forwardDescriptionServerRemote": "Điểm cuối {{endpointPort}} → máy chủ hiện tại {{sourcePort}}.",
"forwardDescriptionServerDynamic": "SOCKS trên máy chủ hiện tại {{sourcePort}}.",
"forwardDescriptionClientLocal": "Cục bộ {{sourcePort}} → từ xa {{endpointPort}}.",
"forwardDescriptionClientRemote": "Từ xa {{sourcePort}} → cục bộ {{endpointPort}}.",
"forwardDescriptionClientDynamic": "SOCKS trên cổng cục bộ {{sourcePort}}.",
"summaryClientLocal": "{{localHost}}:{{localPort}} → {{remoteHost}}:{{remotePort}} qua {{endpoint}}",
"summaryClientRemote": "{{remoteHost}}:{{remotePort}} trên {{endpoint}} → {{localHost}}:{{localPort}}",
"summaryClientDynamic": "{{localHost}}:{{localPort}} → SOCKS qua {{endpoint}}",
"autoNameClientLocal": "Cục bộ {{localPort}} → {{endpoint}} {{remotePort}}",
"autoNameClientRemote": "{{endpoint}} {{remotePort}} → cục bộ {{localPort}}",
"autoNameClientDynamic": "SOCKS {{localPort}} qua {{endpoint}}",
"route": "Tuyến:",
"lastStarted": "Lần bắt đầu cuối",
"lastTested": "Lần kiểm tra cuối",
"lastError": "Lỗi cuối cùng",
"maxRetries": "Số lần thử lại tối đa",
"maxRetriesDescription": "Số lần thử lại tối đa.",
"retryInterval": "Khoảng thời gian thử lại (giây)",
"retryIntervalDescription": "Thời gian chờ giữa các lần thử lại.",
"local": "Cục bộ",
"remote": "Từ xa",
"destination": "Điểm đến",
"host": "Máy chủ",
"mode": "Chế độ",
"noHostSelected": "Chưa chọn máy chủ",
"working": "Đang làm việc..."
},
"cardGrid": {
"dragToMove": "Kéo để di chuyển",
"dragToResize": "Kéo để thay đổi kích thước",
"changeWidth": "Thay đổi chiều rộng",
"removeCard": "Xóa {{label}}",
"addCard": "Thêm",
"columns": "Cột",
"empty": "Không có thẻ nào. Dùng Thêm bên dưới để đặt thẻ."
},
"hostMetrics": {
"cpu": "CPU",
"memory": "Bộ nhớ",
"disk": "Ổ đĩa",
"network": "Mạng",
"uptime": "Thời gian hoạt động",
"processes": "Tiến trình",
"available": "Khả dụng",
"free": "Trống",
"connecting": "Đang kết nối...",
"connectionFailed": "Kết nối máy chủ thất bại",
"naCpus": "N/A CPU",
"cpuCores_one": "{{count}} Lõi",
"cpuCores_other": "{{count}} Lõi",
"cpuUsage": "Mức sử dụng CPU",
"memoryUsage": "Mức sử dụng bộ nhớ",
"diskUsage": "Mức sử dụng ổ đĩa",
"selectFilesystem": "Chọn hệ thống tệp",
"temperature": "Nhiệt độ",
"highestTemperature": "Nhiệt độ cao nhất",
"primaryTemperatureSensor": "Cảm biến chính",
"gpu": {
"title": "GPU",
"noDevice": "Không phát hiện thấy GPU NVIDIA. Hãy cài đặt trình điều khiển NVIDIA (nó cung cấp lệnh nvidia-smi) để xem các thông số GPU.",
"driver": "Tài xế {{version}}",
"utilization": "Sử dụng",
"memory": "VRAM",
"temperature": "Nhiệt độ",
"power": "Quyền lực",
"fan": "Cái quạt",
"processes": "Các quy trình GPU",
"noProcesses": "Hiện không có tiến trình nào đang sử dụng GPU."
},
"failedToFetchHostConfig": "Không tải được cấu hình máy chủ",
"serverOffline": "Máy chủ ngoại tuyến",
"cannotFetchMetrics": "Không thể tải số liệu từ máy chủ ngoại tuyến",
"totpFailed": "Xác minh TOTP thất bại",
"noneAuthNotSupported": "Host Metrics không hỗ trợ kiểu xác thực 'none'.",
"noHostSelected": "Chưa chọn máy chủ",
"load": "Tải",
"systemInfo": "Thông tin hệ thống",
"hostname": "Tên máy chủ",
"operatingSystem": "Hệ điều hành",
"kernel": "Nhân",
"seconds": "giây",
"networkInterfaces": "Giao diện mạng",
"noInterfacesFound": "Không tìm thấy giao diện mạng nào",
"noProcessesFound": "Không tìm thấy tiến trình nào",
"processesTotal": "Tổng",
"processesRunning": "đang chạy",
"loginStats": "Thống kê đăng nhập SSH",
"noRecentLoginData": "Không có dữ liệu đăng nhập gần đây",
"executingQuickAction": "Đang thực thi {{name}}...",
"quickActionSuccess": "{{name}} đã hoàn tất thành công",
"quickActionFailed": "{{name}} thất bại",
"quickActionError": "Thực thi {{name}} thất bại",
"ports": {
"title": "Cổng đang lắng nghe",
"protocol": "Giao thức",
"port": "Cổng",
"address": "Địa chỉ",
"process": "Tiến trình",
"search": "Tìm kiếm cổng...",
"allProtocols": "Tất cả",
"noData": "Không có dữ liệu cổng đang lắng nghe"
},
"firewall": {
"title": "Tường lửa",
"inactive": "Không hoạt động",
"policy": "Chính sách",
"rules": "quy tắc",
"noRules": "Không có quy tắc nào trong chuỗi này",
"noData": "Không có dữ liệu tường lửa",
"action": "Hành động",
"protocol": "Giao thức",
"port": "Cổng",
"source": "Nguồn",
"anywhere": "Mọi nơi",
"chains": "chuỗi"
},
"loadAvg": "Tải trung bình",
"swap": "Swap",
"architecture": "Kiến trúc",
"refresh": "Làm mới",
"retry": "Thử lại",
"customize": "Tùy chỉnh bố cục",
"reset": "Đặt lại",
"tabLive": "Trực tiếp",
"editModeInstructions": "Kéo thẻ để sắp xếp lại, kéo cạnh dưới để thay đổi kích thước, và dùng nút chiều rộng để thay đổi độ rộng thẻ. Thêm hoặc xóa thẻ bên dưới.",
"managers": {
"services": "Dịch vụ",
"processInspector": "Trình kiểm tra tiến trình",
"logViewer": "Trình xem nhật ký",
"cron": "Cron Jobs",
"packages": "Gói",
"ssl": "Chứng chỉ SSL",
"firewall": "Tường lửa",
"users": "Người dùng & Quyền",
"healthCheck": "Kiểm tra sức khỏe",
"diskBreakdown": "Phân tích ổ đĩa",
"systemdTimers": "Bộ hẹn giờ",
"topMemory": "Top theo bộ nhớ",
"noData": "Không có dữ liệu",
"sudoHint": "Đặt mật khẩu sudo cho máy chủ này trong trình chỉnh sửa máy chủ để kích hoạt các hành động đặc quyền.",
"filter": "Lọc...",
"start": "Khởi động",
"stop": "Dừng",
"restart": "Khởi động lại",
"actionDone": "{{name}} được cập nhật",
"actionFailed": "Hành động thất bại",
"signalSent": "Đã gửi tín hiệu đến PID {{pid}}",
"killHint": "Nhấp: kết thúc (SIGTERM). Nhấp chuột phải: buộc kết thúc (SIGKILL).",
"working": "Đang làm việc...",
"update": "Cập nhật",
"upgradeAll": "Nâng cấp tất cả",
"allUpToDate": "Tất cả đều mới nhất",
"save": "Lưu",
"command": "Lệnh",
"enabled": "Đã bật",
"cronSaved": "Đã cập nhật crontab",
"clients": "Máy khách",
"dryRun": "Chạy thử",
"renew": "Gia hạn",
"noAcmeClient": "Không tìm thấy máy khách ACME (certbot hoặc acme.sh) trên máy này.",
"addInputRule": "Thêm quy tắc INPUT",
"firewallWarning": "Thay đổi chỉ tạm thời, chưa được lưu vĩnh viễn. Cẩn thận kẻo tự khóa mình ra ngoài.",
"ruleApplied": "Quy tắc đã được áp dụng",
"invalidPort": "Nhập cổng hợp lệ (1-65535)",
"newUsername": "Tên người dùng mới",
"addUser": "Thêm",
"deleteUser": "Xóa người dùng",
"noHealthChecks": "Chưa có kiểm tra trạng thái nào được cấu hình.",
"follow": "Theo dõi",
"noLogData": "Không có dữ liệu nhật ký.",
"tree": "Dạng cây",
"enableDisable": "Bật / tắt khi khởi động",
"grantSudo": "Cấp quyền sudo",
"revokeSudo": "Thu hồi quyền sudo",
"sslIssueCert": "Cấp chứng chỉ",
"sslExpired": "Đã hết hạn",
"sslInDays": "trong {{days}}d",
"sslNeedDomain": "Nhập ít nhất một tên miền",
"sslIssued": "Đã cấp chứng chỉ",
"sslDomainsPlaceholder": "example.com, www.example.com",
"sslHttpStandalone": "HTTP (độc lập)",
"sslHttpWebroot": "HTTP (webroot)",
"sslDns": "DNS",
"sslDnsProvider": "Nhà cung cấp DNS (ví dụ: cloudflare)",
"sslIssueHint": "Thông tin xác thực nhà cung cấp DNS phải được cấu hình trên máy chủ.",
"sslRevoke": "Thu hồi chứng chỉ",
"sslRevoked": "Chứng chỉ đã bị thu hồi",
"sslRevokeConfirm": "Thu hồi và xóa chứng chỉ \"{{name}}\"? Hành động này không thể hoàn tác.",
"healthRun": "Chạy",
"healthName": "Tên",
"healthTarget": "Máy chủ / địa chỉ",
"healthAddCheck": "Thêm kiểm tra",
"healthSaved": "Đã lưu kiểm tra sức khỏe",
"healthMissingFields": "Mỗi kiểm tra cần có tên và mục tiêu",
"logFile": "Tệp",
"logUnit": "Đơn vị",
"logCustomPath": "Đường dẫn tùy chỉnh trong /var/log (tùy chọn)",
"logGrep": "Lọc dòng...",
"firewallPersist": "Lưu quy tắc",
"firewallPersisted": "Đã lưu quy tắc tường lửa",
"wireguard": "WireGuard",
"tailscale": "Tailscale",
"wgNotInstalled": "WireGuard chưa được cài đặt trên máy chủ này",
"wgNoInterfaces": "Chưa cấu hình giao diện WireGuard nào",
"wgInterfaceUp": "Khởi động",
"wgInterfaceDown": "Dừng",
"wgBringingUp": "Đang khởi động {{name}}...",
"wgBringingDown": "Đang dừng {{name}}...",
"wgInterfaceUpDone": "{{name}} đã hoạt động",
"wgInterfaceDownDone": "{{name}} đã dừng",
"wgListenPort": "Cổng",
"wgPublicKey": "Khóa công khai",
"wgEndpoint": "Điểm cuối",
"wgAllowedIPs": "IP được phép",
"wgLastHandshake": "Lần bắt tay cuối",
"wgHandshakeNever": "Chưa bao giờ",
"wgTransfer": "Truyền tải",
"tsNotInstalled": "Tailscale chưa được cài đặt trên máy chủ này",
"tsRunning": "Đang chạy",
"tsStopped": "Đã dừng",
"tsEnable": "Kết nối",
"tsDisable": "Ngắt kết nối",
"tsEnabling": "Đang kết nối đến Tailscale...",
"tsDisabling": "Đang ngắt kết nối khỏi Tailscale...",
"tsEnabled": "Đã kết nối Tailscale",
"tsDisabled": "Đã ngắt kết nối Tailscale",
"tsIPs": "IP Tailscale",
"tsPeers": "Các máy ngang hàng",
"tsOnline": "Trực tuyến",
"tsOffline": "Ngoại tuyến",
"tsExitNode": "Nút thoát",
"tsExitNodeActive": "Nút thoát đang hoạt động",
"tsHostname": "Tên máy chủ"
}
},
"proxmoxStats": {
"tabTitle": "Thống kê Proxmox",
"cpuUsage": "Mức sử dụng CPU",
"memoryUsage": "Mức sử dụng bộ nhớ",
"diskUsage": "Mức sử dụng ổ đĩa",
"networkInterfaces": "Giao diện mạng",
"uptime": "Thời gian hoạt động",
"systemInfo": "Thông tin hệ thống",
"guestsSummary": "Khách",
"storagePools": "Các bể chứa",
"clusterHealth": "Cluster Health",
"cpuCores_one": "{{count}} Lõi",
"cpuCores_other": "{{count}} Lõi",
"used": "Đã sử dụng",
"total": "Tổng cộng",
"hostname": "Tên máy chủ",
"kernel": "Hạt nhân",
"pveVersion": "Phiên bản PVE",
"name": "Tên",
"status": "Trạng thái",
"type": "Kiểu",
"cpu": "CPU",
"mem": "Mem",
"disk": "Đĩa",
"running": "Đang chạy",
"stopped": "Đã dừng lại",
"guestCounts": "{{running}}/{{total}} đang chạy",
"inactive": "Không hoạt động",
"notClustered": "Nút độc lập (không thuộc cụm máy chủ)",
"quorate": "Quorate",
"notQuorate": "Không đủ số lượng",
"nodeOnline": "Trực tuyến",
"nodeOffline": "Ngoại tuyến",
"noHostSelected": "Chưa chọn máy chủ nào",
"pveshNotFound": "Không tìm thấy pvesh - đây có phải là một node Proxmox không?",
"nodeDetectionFailed": "Không thể xác định tên nút Proxmox hợp lệ.",
"connecting": "Đang kết nối...",
"connectionFailed": "Không thể kết nối đến nút Proxmox.",
"refresh": "Làm cho khỏe lại",
"searchGuests": "Tìm kiếm khách...",
"filterAll": "Tất cả",
"filterVm": "Máy ảo",
"filterLxc": "LXC",
"noGuests": "Không tìm thấy máy ảo hoặc vùng chứa LXC nào trên nút này.",
"noGuestsMatch": "Hiện không có khách nào phù hợp với bộ lọc hiện tại."
},
"auth": {
"tagline": "Quản lý SSH và máy tính từ xa tự lưu trữ",
"loginTitle": "Chào mừng trở lại",
"registerTitle": "Tạo tài khoản",
"forgotPassword": "Quên mật khẩu?",
"rememberMe": "Nhớ thiết bị trong 30 ngày (bao gồm TOTP)",
"noAccount": "Chưa có tài khoản?",
"hasAccount": "Đã có tài khoản?",
"twoFactorAuth": "Xác thực hai yếu tố",
"enterCode": "Nhập mã xác minh",
"backupCode": "Hoặc dùng mã dự phòng",
"verifyCode": "Xác minh mã",
"redirectingToApp": "Đang chuyển hướng đến ứng dụng...",
"sshAuthenticationRequired": "Yêu cầu xác thực SSH",
"sshNoKeyboardInteractive": "Xác thực tương tác bàn phím không khả dụng",
"sshAuthenticationFailed": "Xác thực thất bại",
"sshAuthenticationTimeout": "Hết thời gian xác thực",
"sshNoKeyboardInteractiveDescription": "Máy chủ không hỗ trợ xác thực tương tác bàn phím. Vui lòng cung cấp mật khẩu hoặc khóa SSH.",
"sshAuthFailedDescription": "Thông tin đăng nhập không chính xác. Vui lòng thử lại với thông tin hợp lệ.",
"sshTimeoutDescription": "Quá trình xác thực đã hết thời gian. Vui lòng thử lại.",
"sshProvideCredentialsDescription": "Vui lòng cung cấp thông tin SSH để kết nối đến máy chủ này.",
"sshPasswordDescription": "Nhập mật khẩu cho kết nối SSH này.",
"sshKeyPasswordDescription": "Nếu khóa SSH của bạn được mã hóa, hãy nhập cụm mật khẩu tại đây.",
"passphraseRequired": "Yêu cầu cụm mật khẩu",
"passphraseRequiredDescription": "Khóa SSH đã được mã hóa. Vui lòng nhập cụm mật khẩu để mở khóa.",
"back": "Quay lại",
"firstUser": "Người dùng đầu tiên",
"firstUserMessage": "Bạn là người dùng đầu tiên và sẽ được đặt làm quản trị viên. Bạn có thể xem cài đặt quản trị trong menu thả xuống người dùng ở thanh bên. Nếu bạn cho rằng đây là nhầm lẫn, hãy kiểm tra nhật ký Docker hoặc tạo một issue trên GitHub.",
"external": "Bên ngoài",
"loginWithExternal": "Đăng nhập bằng Nhà cung cấp Bên ngoài",
"loginWithExternalDesc": "Đăng nhập bằng nhà cung cấp danh tính bên ngoài đã được cấu hình",
"externalNotSupportedInElectron": "Xác thực bên ngoài chưa được hỗ trợ trong ứng dụng Electron. Vui lòng sử dụng phiên bản web để đăng nhập OIDC.",
"loginWithProvider": "Đăng nhập bằng {{name}}",
"orContinueWith": "hoặc tiếp tục với",
"ldapUsername": "Tên người dùng LDAP",
"ldapPassword": "Mật khẩu LDAP",
"ldapSignIn": "Đăng nhập",
"ldapLoginFailed": "Đăng nhập LDAP thất bại",
"resetPasswordButton": "Đặt lại mật khẩu",
"sendResetCode": "Gửi mã đặt lại",
"resetCodeDesc": "Nhập tên người dùng của bạn để nhận mã đặt lại mật khẩu. Mã sẽ được ghi trong nhật ký container Docker.",
"resetCode": "Mã đặt lại",
"verifyCodeButton": "Xác minh mã",
"enterResetCode": "Nhập mã 6 chữ số từ nhật ký container Docker cho người dùng:",
"newPassword": "Mật khẩu mới",
"confirmNewPassword": "Xác nhận mật khẩu",
"enterNewPassword": "Nhập mật khẩu mới của bạn cho người dùng:",
"signUp": "Đăng ký",
"desktopApp": "Ứng dụng máy tính",
"loggingInToDesktopApp": "Đang đăng nhập vào ứng dụng máy tính",
"loadingServer": "Đang tải máy chủ...",
"dataLossWarning": "Đặt lại mật khẩu theo cách này sẽ xóa tất cả các máy chủ SSH đã lưu, thông tin đăng nhập và dữ liệu mã hóa khác. Hành động này không thể hoàn tác. Chỉ sử dụng khi bạn đã quên mật khẩu và chưa đăng nhập.",
"authenticationDisabled": "Xác thực bị vô hiệu",
"authenticationDisabledDesc": "Tất cả các phương thức xác thực đang bị vô hiệu. Vui lòng liên hệ quản trị viên của bạn.",
"passwordLoginDisabledDesc": "Đăng nhập bằng mật khẩu bị vô hiệu. Hãy sử dụng khóa truy cập hoặc nhà cung cấp xác thực bên ngoài.",
"signInWithPasskey": "Đăng nhập bằng khóa truy cập",
"passkeyLoginFailed": "Đăng nhập bằng passkey thất bại",
"attemptsRemaining": "Còn {{count}} lần thử",
"confirmResetDataWipe": "Tài khoản này chưa đăng nhập kể từ khi nâng cấp mã hóa, do đó dữ liệu đã lưu không thể khôi phục nếu không có mật khẩu cũ. Việc đặt lại sẽ xóa vĩnh viễn các máy chủ, thông tin xác thực và đoạn mã. Tiếp tục?"
},
"hostKey": {
"verifyNewHost": "Xác minh khóa máy chủ SSH",
"keyChangedWarning": "Khóa máy chủ SSH đã thay đổi",
"firstConnectionTitle": "Lần đầu kết nối đến máy chủ này",
"firstConnectionDescription": "Không thể xác thực danh tính của máy chủ này. Xác minh dấu vân tay khớp với mong đợi.",
"keyChangedDescription": "Khóa máy chủ cho máy chủ này đã thay đổi kể từ lần kết nối trước. Điều này có thể là dấu hiệu của vấn đề bảo mật.",
"previousKey": "Khóa trước đó",
"newFingerprint": "Dấu vân tay mới",
"fingerprint": "Dấu vân tay",
"verifyInstructions": "Nếu bạn tin tưởng máy chủ này, nhấn Chấp nhận để tiếp tục và lưu dấu vân tay này cho các kết nối sau.",
"securityWarning": "Cảnh báo bảo mật",
"acceptAndContinue": "Chấp nhận & Tiếp tục",
"acceptNewKey": "Chấp nhận Khóa Mới & Tiếp tục"
},
"errors": {
"databaseConnection": "Không thể kết nối tới cơ sở dữ liệu",
"embeddedServerFailed": "Máy chủ cục bộ của Termix không thể khởi động.",
"unknownError": "Lỗi không xác định",
"loginFailed": "Đăng nhập thất bại",
"failedPasswordReset": "Không thể bắt đầu đặt lại mật khẩu",
"failedVerifyCode": "Không thể xác minh mã đặt lại",
"failedCompleteReset": "Không thể hoàn tất đặt lại mật khẩu",
"invalidTotpCode": "Mã TOTP không hợp lệ",
"failedOidcLogin": "Không thể bắt đầu đăng nhập OIDC",
"silentSigninOidcUnavailable": "Đã yêu cầu đăng nhập tự động, nhưng đăng nhập OIDC không khả dụng.",
"failedUserInfo": "Không thể lấy thông tin người dùng sau khi đăng nhập",
"oidcAuthFailed": "Xác thực OIDC thất bại",
"invalidAuthUrl": "URL ủy quyền không hợp lệ nhận được từ máy chủ",
"requiredField": "Trường này là bắt buộc",
"minLength": "Độ dài tối thiểu là {{min}}",
"passwordMismatch": "Mật khẩu không khớp",
"passwordLoginDisabled": "Đăng nhập bằng tên người dùng/mật khẩu hiện đang bị vô hiệu hóa",
"sessionExpired": "Phiên làm việc đã hết hạn - vui lòng đăng nhập lại",
"totpRateLimited": "Giới hạn tốc độ: Quá nhiều lần thử xác thực TOTP. Vui lòng thử lại sau.",
"totpRateLimitedWithTime": "Giới hạn tốc độ: Quá nhiều lần thử xác thực TOTP. Vui lòng đợi {{time}} giây trước khi thử lại.",
"resetCodeRateLimited": "Giới hạn tốc độ: Quá nhiều lần thử xác thực. Vui lòng thử lại sau.",
"resetCodeRateLimitedWithTime": "Hạn chế tốc độ: Quá nhiều lần xác minh. Vui lòng chờ {{time}} giây trước khi thử lại.",
"authTokenSaveFailed": "Lưu token xác thực thất bại",
"authTokenMissing": "Máy chủ không trả về mã xác thực mới. Vui lòng đăng nhập lại.",
"authTokenRejected": "Máy chủ từ xa đã từ chối mã thông báo xác thực mới.",
"keyringUnavailable": "Đã đăng nhập, nhưng phiên làm việc không thể được lưu lại: hệ thống này không có khóa mã hóa nào để sử dụng. Hãy khởi động một dịch vụ mã hóa bí mật (như gnome-keyring hoặc KWallet) và đăng nhập lại.",
"failedToLoadServer": "Tải máy chủ thất bại",
"remoteServerRequired": "Cần có máy chủ từ xa. Kết nối máy chủ từ xa trong Cài đặt để sử dụng loại kết nối này."
},
"messages": {
"registrationDisabled": "Đăng ký tài khoản mới hiện bị quản trị viên vô hiệu hóa. Vui lòng đăng nhập hoặc liên hệ quản trị viên.",
"userNotAllowed": "Tài khoản của bạn không được phép đăng ký. Vui lòng liên hệ quản trị viên.",
"databaseConnectionFailed": "Kết nối máy chủ cơ sở dữ liệu thất bại",
"embeddedServerPortInUse": "Cổng {{port}} hiện đang được sử dụng bởi một chương trình khác. Thông thường, đây là một container Docker của Termix hoặc một tiến trình Termix còn sót lại từ phiên trước. Hãy đóng nó lại, sau đó khởi động lại Termix.",
"embeddedServerPortInUseUnknownPort": "Một trong các cổng mà Termix cần đang được một chương trình khác sử dụng. Hãy đóng chương trình đang sử dụng cổng đó, sau đó khởi động lại Termix.",
"embeddedServerCrashed": "Máy chủ cục bộ đã dừng hoạt động đột ngột. Hãy khởi động lại Termix và kiểm tra nhật ký trên máy tính để bàn nếu sự cố này tiếp diễn.",
"resetCodeSent": "Mã đặt lại đã được gửi đến nhật ký Docker",
"codeVerified": "Xác minh mã thành công",
"passwordResetSuccess": "Đặt lại mật khẩu thành công",
"loginSuccess": "Đăng nhập thành công",
"registrationSuccess": "Đăng ký thành công"
},
"profile": {
"c2sTunnelConfigDesc": "Đường hầm máy tính cục bộ trỏ đến các máy chủ SSH đã cấu hình.",
"c2sTunnelPresets": "Cài đặt sẵn Đường hầm Máy khách",
"c2sTunnelPresetsDesc": "Lưu danh sách đường hầm cục bộ của máy khách này thành cài đặt sẵn trên máy chủ có tên, hoặc tải cài đặt sẵn trở lại máy khách này.",
"c2sTunnelPresetsUnavailable": "Cài đặt sẵn đường hầm máy khách chỉ khả dụng trên ứng dụng máy tính.",
"c2sPresetName": "Tên cài đặt sẵn",
"c2sPresetNamePlaceholder": "Tên cài đặt sẵn máy khách",
"c2sPresetToLoad": "Cài đặt sẵn để tải",
"c2sNoPresetSelected": "Chưa chọn cài đặt sẵn",
"c2sNoPresets": "Chưa lưu cài đặt sẵn nào",
"c2sLoadPreset": "Tải",
"c2sCurrentLocalConfig": "{{count}} đường hầm máy khách cục bộ đã được cấu hình trên máy tính này.",
"c2sPresetSyncNote": "Cài đặt sẵn là ảnh chụp tức thời; tải một cài đặt sẽ thay thế danh sách đường hầm máy khách cục bộ trên máy này.",
"c2sPresetSaved": "Đã lưu cài đặt sẵn đường hầm máy khách",
"c2sPresetLoaded": "Đã tải cài đặt sẵn đường hầm máy khách cục bộ",
"c2sPresetRenamed": "Đã đổi tên cài đặt sẵn đường hầm máy khách",
"c2sPresetDeleted": "Đã xóa cài đặt sẵn đường hầm máy khách",
"c2sPresetLoadError": "Tải cài đặt sẵn đường hầm máy khách thất bại"
},
"placeholders": {
"maxRetries": "3",
"retryInterval": "10",
"language": "Ngôn ngữ",
"keyPassword": "mật khẩu khóa",
"pastePrivateKey": "Dán khóa riêng tư của bạn vào đây...",
"localListenerHost": "127.0.0.1 (lắng nghe cục bộ)",
"localTargetHost": "127.0.0.1 (đích trên máy này)",
"remoteTargetHost": "127.0.0.1 (mục tiêu từ điểm cuối)",
"remoteBindHost": "127.0.0.1 (lắng nghe trên điểm cuối)",
"socksListenerHost": "127.0.0.1 (Trình nghe SOCKS)",
"enterPassword": "Nhập mật khẩu của bạn",
"defaultPort": "22",
"defaultEndpointPort": "224"
},
"dashboard": {
"title": "Bảng điều khiển",
"loading": "Đang tải bảng điều khiển...",
"github": "GitHub",
"support": "Hỗ trợ",
"discord": "Discord",
"docs": "Tài liệu",
"donate": "Ủng hộ",
"serverOverview": "Tổng quan máy chủ",
"version": "Phiên bản",
"upToDate": "Đã cập nhật",
"updateAvailable": "Có bản cập nhật",
"beta": "Beta",
"uptime": "Thời gian hoạt động",
"database": "Cơ sở dữ liệu",
"healthy": "Ổn định",
"error": "Lỗi",
"totalHosts": "Tổng số máy chủ",
"totalTunnels": "Tổng số đường hầm",
"totalCredentials": "Tổng số thông tin xác thực",
"recentActivity": "Hoạt động gần đây",
"reset": "Đặt lại",
"loadingRecentActivity": "Đang tải hoạt động gần đây...",
"noRecentActivity": "Không có hoạt động gần đây",
"quickActions": "Hành động nhanh",
"addHost": "Thêm máy chủ",
"addCredential": "Thêm thông tin xác thực",
"adminSettings": "Cài đặt quản trị",
"userProfile": "Hồ sơ người dùng",
"serverStats": "Thống kê máy chủ",
"loadingServerStats": "Đang tải thống kê máy chủ...",
"noServerData": "Không có dữ liệu máy chủ",
"cpu": "CPU",
"ram": "RAM",
"customizeLayout": "Tùy chỉnh Bảng điều khiển",
"dashboardSettings": "Cài đặt Bảng điều khiển",
"enableDisableCards": "Bật/Tắt Thẻ",
"resetLayout": "Đặt lại về mặc định",
"serverOverviewCard": "Tổng quan Máy chủ",
"recentActivityCard": "Hoạt động Gần đây",
"networkGraphCard": "Biểu đồ Mạng",
"networkGraph": "Biểu đồ Mạng",
"quickActionsCard": "Thao tác nhanh",
"serverStatsCard": "Thống kê máy chủ",
"panelMain": "Chính",
"panelSide": "Bên",
"justNow": "vừa xong",
"serviceLinks": "Liên kết Dịch vụ",
"homepagePreview": "Xem trước Trang chủ"
},
"donation": {
"title": "Bạn thích Termix chứ?",
"body": "Termix là phần mềm miễn phí và mã nguồn mở, được xây dựng và duy trì bởi một nhóm hai người trong thời gian rảnh. Nếu nó đã thay thế một công cụ thương mại mà bạn đáng lẽ phải trả tiền, một khoản quyên góp sẽ giúp trang trải chi phí hosting và duy trì phát triển. Hiện tại, quyên góp chỉ chấp nhận tiền mã hóa.",
"milestones": "Quyên góp cũng giúp tài trợ thời gian nghiên cứu và học hỏi những gì cần thiết để xây dựng các tính năng như hỗ trợ SAML và Kubernetes. Xem tiến độ trên trang quyên góp.",
"cta": "Quyên góp",
"dismiss": "Để sau"
},
"dashboardTab": {
"stable": "ỔN ĐỊNH",
"hostsOnline": "Máy chủ Trực tuyến",
"activeTunnels": "Đường hầm hoạt động",
"registerNewServer": "Đăng ký máy chủ mới",
"storeSshKeysOrPasswords": "Lưu trữ khóa SSH hoặc mật khẩu",
"manageUsersAndRoles": "Quản lý người dùng và vai trò",
"manageYourAccount": "Quản lý tài khoản của bạn",
"hostStatus": "Trạng thái Máy chủ",
"noHostsConfigured": "Chưa cấu hình máy chủ nào",
"online": "TRỰC TUYẾN",
"offline": "NGOẠI TUYẾN",
"checking": "ĐANG KIỂM TRA",
"onlineLower": "Trực tuyến",
"nodes": "{{count}} node",
"add": "Thêm:",
"commandPalette": "Bảng lệnh",
"done": "Xong",
"editModeInstructions": "Kéo thẻ để sắp xếp lại · Kéo dải phân cách cột để thay đổi kích thước cột · Kéo cạnh dưới của thẻ để thay đổi chiều cao · Kéo vào thùng rác để xóa",
"empty": "Trống",
"clear": "Xóa",
"serviceLinksTitle": "Liên kết dịch vụ",
"serviceLinksEmpty": "Chưa có liên kết dịch vụ nào",
"serviceLinksAddLabel": "Nhãn",
"serviceLinksAddUrl": "URL",
"serviceLinksAdd": "Thêm",
"serviceLinksLabelPlaceholder": "Dịch vụ của tôi",
"serviceLinksUrlPlaceholder": "http://192.168.1.10:8080",
"serviceLinksInvalidUrl": "Nhập địa chỉ web hợp lệ",
"serviceLinksAddFailed": "Thêm liên kết dịch vụ thất bại",
"disk": "Ổ đĩa",
"viewServerDetails": "Xem chi tiết máy chủ"
},
"sessionLogs": {
"title": "Nhật ký phiên",
"noLogs": "Chưa có nhật ký phiên nào",
"noLogsDesc": "Bật ghi nhật ký phiên trên máy chủ để bắt đầu ghi",
"duration": "Thời lượng",
"viewLog": "Xem nhật ký",
"downloadLog": "Tải xuống",
"downloadAsText": "Tải xuống dưới dạng văn bản",
"deleteLog": "Xóa",
"confirmDelete": "Xóa nhật ký phiên này?",
"confirmDeleteDesc": "Hành động này không thể hoàn tác.",
"copyContent": "Sao chép",
"copied": "Đã sao chép!",
"loadError": "Tải nhật ký phiên thất bại",
"deleteError": "Xóa nhật ký phiên thất bại",
"filterByHost": "Lọc theo máy chủ..."
},
"networkGraph": {
"addHost": "Thêm máy chủ",
"addGroup": "Thêm nhóm",
"addLink": "Thêm liên kết",
"zoomIn": "Phóng to",
"zoomOut": "Thu nhỏ",
"resetView": "Đặt lại khung nhìn",
"selectHost": "Chọn máy chủ",
"chooseHost": "Chọn một máy chủ...",
"parentGroup": "Nhóm cha",
"noGroup": "Không nhóm",
"groupName": "Tên nhóm",
"color": "Màu sắc",
"source": "Nguồn",
"target": "Đích",
"moveToGroup": "Di chuyển vào nhóm",
"selectGroup": "Chọn nhóm...",
"addConnection": "Thêm kết nối",
"hostDetails": "Chi tiết máy chủ",
"removeFromGroup": "Xóa khỏi nhóm",
"addHostHere": "Thêm máy chủ tại đây",
"editGroup": "Sửa nhóm",
"delete": "Xóa",
"add": "Thêm",
"create": "Tạo",
"move": "Di chuyển",
"connect": "Kết nối",
"createGroup": "Tạo nhóm",
"selectSourcePlaceholder": "Chọn nguồn...",
"selectTargetPlaceholder": "Chọn đích...",
"invalidFile": "Tệp không hợp lệ",
"hostAlreadyExists": "Máy chủ đã có trong cấu trúc liên kết",
"connectionExists": "Kết nối đã tồn tại",
"unknown": "Không xác định",
"name": "Tên",
"ip": "IP",
"status": "Trạng thái",
"failedToAddNode": "Không thể thêm nút",
"sourceDifferentFromTarget": "Nguồn và đích phải khác nhau",
"exportJSON": "Xuất JSON",
"importJSON": "Nhập JSON",
"terminal": "Terminal",
"fileManager": "Trình quản lý file",
"tunnel": "Đường hầm",
"docker": "Docker",
"serverStats": "Số liệu máy chủ",
"hostMetrics": "Số liệu máy chủ",
"noNodes": "Chưa có nút nào"
},
"docker": {
"notEnabled": "Docker chưa được kích hoạt cho máy chủ này",
"validating": "Đang kiểm tra Docker...",
"connecting": "Đang kết nối...",
"error": "Lỗi",
"version": "{{runtime}} {{version}}",
"connectionFailed": "Kết nối Docker thất bại",
"containerStarted": "Container {{name}} đã khởi động",
"failedToStartContainer": "Khởi động container {{name}} thất bại",
"containerStopped": "Container {{name}} đã dừng",
"failedToStopContainer": "Dừng container {{name}} thất bại",
"containerRestarted": "Container {{name}} đã khởi động lại",
"failedToRestartContainer": "Khởi động lại container {{name}} thất bại",
"containerPaused": "Container {{name}} đã tạm dừng",
"containerUnpaused": "Container {{name}} đã tiếp tục",
"failedToTogglePauseContainer": "Chuyển đổi trạng thái tạm dừng cho container {{name}} thất bại",
"containerRemoved": "Container {{name}} đã bị xóa",
"failedToRemoveContainer": "Xóa container {{name}} thất bại",
"image": "Image",
"ports": "Cổng",
"noPorts": "Không có cổng nào",
"start": "Khởi động",
"confirmRemoveContainer": "Bạn có chắc chắn muốn xóa container '{{name}}' không? Hành động này không thể hoàn tác.",
"runningContainerWarning": "Cảnh báo: Container này đang chạy. Xóa nó sẽ dừng container trước.",
"loadingContainers": "Đang tải danh sách container...",
"manager": "Quản lý Docker",
"autoRefresh": "Tự động làm mới",
"timestamps": "Dấu thời gian",
"lines": "Dòng",
"filterLogs": "Lọc nhật ký...",
"refresh": "Làm mới",
"download": "Tải xuống",
"clear": "Xóa",
"logsDownloaded": "Đã tải xuống nhật ký thành công",
"last50": "50 cuối cùng",
"last100": "100 cuối cùng",
"last500": "500 cuối cùng",
"last1000": "1000 cuối cùng",
"allLogs": "Tất cả nhật ký",
"noLogsMatching": "Không có nhật ký nào khớp với \"{{query}}\"",
"noLogsAvailable": "Không có nhật ký khả dụng",
"noContainersFound": "Không tìm thấy container",
"noContainersFoundHint": "Không có container Docker nào trên máy chủ này",
"searchPlaceholder": "Tìm kiếm container...",
"allStatuses": "Tất cả trạng thái",
"stateRunning": "Đang chạy",
"statePaused": "Tạm dừng",
"stateExited": "Đã thoát",
"stateRestarting": "Đang khởi động lại",
"noContainersMatchFilters": "Không có container nào khớp bộ lọc của bạn",
"noContainersMatchFiltersHint": "Hãy thử điều chỉnh tiêu chí tìm kiếm hoặc lọc",
"failedToFetchStats": "Không thể lấy số liệu thống kê container",
"containerNotRunning": "Container không chạy",
"startContainerToViewStats": "Khởi động container để xem số liệu thống kê",
"loadingStats": "Đang tải số liệu thống kê...",
"errorLoadingStats": "Lỗi khi tải số liệu thống kê",
"noStatsAvailable": "Không có số liệu thống kê",
"cpuUsage": "Sử dụng CPU",
"current": "Hiện tại",
"memoryUsage": "Sử dụng bộ nhớ",
"networkIo": "I/O mạng",
"input": "Nhập",
"output": "Đầu ra",
"blockIo": "I/O khối",
"read": "Đọc",
"write": "Ghi",
"pids": "PIDs",
"containerInformation": "Thông tin container",
"name": "Tên",
"id": "ID",
"state": "Trạng thái",
"containerMustBeRunning": "Container phải đang chạy để truy cập bảng điều khiển",
"verificationCodePrompt": "Nhập mã xác minh",
"totpVerificationFailed": "Xác minh TOTP thất bại. Vui lòng thử lại.",
"warpgateVerificationFailed": "Xác thực Warpgate thất bại. Vui lòng thử lại.",
"connectedTo": "Đã kết nối đến {{containerName}}",
"disconnected": "Đã ngắt kết nối",
"consoleError": "Lỗi bảng điều khiển",
"errorMessage": "Lỗi: {{message}}",
"failedToConnect": "Không thể kết nối đến container",
"console": "Bảng điều khiển",
"selectShell": "Chọn shell",
"bash": "Bash",
"sh": "sh",
"ash": "ash",
"connect": "Kết nối",
"disconnect": "Ngắt kết nối",
"notConnected": "Chưa kết nối",
"clickToConnect": "Nhấn Kết nối để bắt đầu phiên shell",
"connectingTo": "Đang kết nối đến {{containerName}}...",
"containerNotFound": "Không tìm thấy container",
"backToList": "Quay lại danh sách",
"logs": "Nhật ký",
"stats": "Thống kê",
"consoleTab": "Bảng điều khiển",
"startContainerToAccess": "Khởi động container để truy cập bảng điều khiển"
},
"admin": {
"sectionGeneral": "Chung",
"sectionOidc": "OIDC",
"sectionSso": "Nhà cung cấp SSO",
"ssoAddProvider": "Thêm nhà cung cấp",
"ssoDocsLink": "Xem tài liệu",
"ssoProviderDocsLink": "Xem tài liệu",
"ssoNoProviders": "Chưa có nhà cung cấp SSO.",
"ssoProviderName": "Tên hiển thị",
"ssoProviderType": "Loại nhà cung cấp",
"ssoDeleteProvider": "Xóa nhà cung cấp",
"ssoDeleteConfirm": "Xóa nhà cung cấp này? Người dùng liên kết sẽ không thể đăng nhập.",
"ssoTypeOidc": "OIDC",
"ssoTypeLdap": "LDAP",
"ssoTypeGithub": "GitHub",
"ssoTypeGoogle": "Google",
"ssoEnabled": "Đã bật",
"ssoDisabled": "Đã tắt",
"ssoSaveProvider": "Lưu nhà cung cấp",
"ssoTestConnection": "Kiểm tra kết nối",
"ssoEditProvider": "Chỉnh sửa nhà cung cấp",
"ldapHost": "Máy chủ LDAP",
"ldapPort": "Cổng",
"ldapUseTls": "Dùng TLS (LDAPS)",
"ldapBindDn": "Bind DN",
"ldapBindPassword": "Mật khẩu Bind",
"ldapUserSearchBase": "Cơ sở tìm kiếm người dùng",
"ldapUserSearchFilter": "Bộ lọc tìm kiếm người dùng",
"ldapUsernameAttr": "Thuộc tính tên người dùng",
"ldapDisplayNameAttr": "Thuộc tính tên hiển thị",
"ldapGroupSearchBase": "Cơ sở tìm kiếm nhóm",
"ldapAdminGroup": "Nhóm quản trị",
"ldapAllowedUsers": "Người dùng được phép",
"sectionUsers": "Người dùng",
"sectionSessions": "Phiên",
"sectionRoles": "Vai trò",
"sectionDatabase": "Cơ sở dữ liệu",
"sectionApiKeys": "Khóa API",
"sectionAuditLog": "Nhật ký kiểm tra",
"sectionSsl": "SSL / Let's Encrypt",
"sectionTouchInput": "Nhập liệu cảm ứng",
"touchEnabled": "Cho phép nhập liệu cảm ứng",
"touchEnabledDesc": "Cho phép cuộn bằng một ngón tay trong cửa sổ dòng lệnh.",
"touchMomentumEnabled": "Tạo đà",
"touchMomentumEnabledDesc": "Tiếp tục cuộn xuống một chút sau khi vuốt.",
"touchAdvanced": "Trình độ cao",
"touchDragThreshold": "Ngưỡng kéo",
"touchMaxWheelDelta": "Chênh lệch bánh xe tối đa",
"touchMomentumSampleWindow": "Cửa sổ mẫu động lượng",
"touchReleaseGracePeriod": "thời gian ân hạn thả",
"touchMinimumVelocity": "Vận tốc tối thiểu",
"touchMaximumVelocity": "Vận tốc tối đa",
"touchMaximumDuration": "Thời gian tối đa",
"touchMaximumTravel": "Hành trình tối đa",
"touchDecayTime": "Thời gian phân rã",
"touchPixelsPerTick": "Số pixel trên mỗi tick",
"touchMaximumFrameInterval": "Khoảng thời gian khung hình tối đa",
"touchMaximumTicksPerFrame": "Số tick tối đa mỗi khung hình",
"touchResetDefaults": "Khôi phục về cài đặt mặc định",
"touchSaved": "Cài đặt nhập liệu cảm ứng đã được lưu",
"touchSaveFailed": "Không thể lưu cài đặt nhập liệu cảm ứng.",
"sectionImageStorage": "Lưu trữ hình ảnh",
"imageStorageMode": "Chế độ lưu trữ",
"imageStorageModeDesc": "Nơi hiển thị hình ảnh từ thiết bị đầu cuối được dán và tải lên. Chức năng tự động chọn theo kết nối, cục bộ và từ xa (SFTP) được cố định.",
"imageStorageModeAuto": "Tự động",
"imageStorageModeLocal": "Địa phương",
"imageStorageModeRemoteSftp": "Từ xa (SFTP)",
"imageStorageLocalDir": "Thư mục cục bộ",
"imageStorageLocalDirDesc": "Đường dẫn tuyệt đối trên hệ thống quản trị của Termix. Không hiển thị sau khi lưu vì lý do bảo mật.",
"imageStorageLocalDirPlaceholder": "Để trống phần này.",
"imageStorageHostPath": "Đường dẫn máy chủ",
"imageStorageHostPathDesc": "Đây là giao diện phía máy chủ của thư mục cục bộ mà các tác nhân đầu cuối nhận được.",
"imageStorageTtl": "TTL (ms)",
"imageStorageMaxCount": "Số lượng ảnh tối đa",
"imageStorageMaxBytes": "Số byte lưu trữ tối đa",
"imageStorageSaved": "Cài đặt lưu trữ hình ảnh đã được lưu",
"imageStorageSaveFailed": "Không thể lưu cài đặt lưu trữ hình ảnh.",
"imageStorageInstanceId": "ID phiên bản phiên thiết bị đầu cuối",
"imageStorageInstanceIdDesc": "ID phiên bản của một trong các tab thiết bị đầu cuối được kết nối của bạn, được sử dụng để kiểm tra khả năng hiển thị.",
"imageStorageInstanceIdRequired": "Trước tiên, hãy nhập ID phiên bản thiết bị đầu cuối.",
"imageStorageTest": "Bài kiểm tra",
"imageStorageTesting": "Đang thử nghiệm...",
"imageStorageTestFailed": "Không thể kiểm tra lưu trữ hình ảnh",
"imageStorageTestConnected": "Phiên kết nối terminal đã được thiết lập.",
"imageStorageTestNotConnected": "Không có phiên làm việc thiết bị đầu cuối nào được kết nối với ID phiên bản này.",
"imageStorageTestSelectedMode": "Quá trình tải lên sẽ sử dụng: {{mode}}",
"imageStorageSelectedModeUnavailable": "Không khả dụng",
"imageStorageTestLocalVisible": "Thư mục cục bộ có thể được nhìn thấy từ máy chủ được kết nối.",
"imageStorageTestLocalNotVisible": "Thư mục cục bộ KHÔNG hiển thị từ máy chủ được kết nối.",
"sectionBranding": "Nhãn trắng",
"brandingAppName": "Tên ứng dụng",
"brandingAppNameDesc": "Hiển thị trên màn hình đăng nhập và tab trình duyệt. Để trống để sử dụng \"Termix\".",
"brandingTagline": "Khẩu hiệu",
"brandingTaglineDesc": "Hiển thị bên dưới tên ứng dụng trên màn hình đăng nhập. Để trống để sử dụng khẩu hiệu mặc định.",
"brandingLogo": "Logo",
"brandingLogoDesc": "Định dạng PNG, JPEG hoặc WEBP, dung lượng tối đa 750 KB. Thay thế biểu tượng mặc định trên màn hình đăng nhập và tab trình duyệt.",
"brandingLogoUpload": "Tải lên logo",
"brandingLogoReset": "Khôi phục về mặc định",
"brandingLogoInvalid": "Hình ảnh không hợp lệ. Vui lòng sử dụng tệp PNG, JPEG hoặc WEBP có dung lượng tối đa 750 KB.",
"brandingSaved": "Cài đặt thương hiệu đã được lưu",
"brandingSaveFailed": "Không thể lưu cài đặt thương hiệu.",
"sslDescription": "Tự động cấp và gia hạn chứng chỉ SSL tin cậy từ Let's Encrypt. Yêu cầu tên miền công khai và quyền truy cập cổng 80 hoặc DNS.",
"sslDocsLink": "Xem tài liệu SSL",
"sslDomain": "Tên miền",
"sslDomainPlaceholder": "termix.example.com",
"sslDomainDesc": "Tên miền công khai để cấp chứng chỉ.",
"sslEmail": "Email",
"sslEmailPlaceholder": "admin@example.com",
"sslEmailDesc": "Email liên hệ để nhận thông báo và tài khoản từ Let's Encrypt.",
"sslChallengeType": "Loại thử thách",
"sslChallengeTypeDesc": "Cách chứng minh quyền sở hữu tên miền với Let's Encrypt.",
"sslChallengeHttp": "HTTP (webroot) - yêu cầu cổng 80 có thể truy cập từ internet",
"sslChallengeDns": "DNS (Cloudflare) - yêu cầu Token API Cloudflare",
"sslCloudflareToken": "Token API Cloudflare",
"sslCloudflareTokenPlaceholder": "Nhập token...",
"sslCloudflareTokenDesc": "Token có phạm vi với quyền Zone:DNS:Edit cho tên miền của bạn.",
"sslCertStatus": "Trạng thái chứng chỉ",
"sslCertStatusNone": "Không có chứng chỉ",
"sslCertStatusValid": "Hợp lệ",
"sslCertStatusExpiring": "Sắp hết hạn",
"sslCertStatusExpired": "Đã hết hạn",
"sslCertExpiresAt": "Hết hạn {{date}}",
"sslLastIssued": "Cấp lần cuối {{date}}",
"sslRequestCert": "Cấp / Gia hạn chứng chỉ",
"sslRequestCertLoading": "Đang yêu cầu chứng chỉ...",
"sslRequestCertSuccess": "Chứng chỉ đã được cấp và cài đặt thành công",
"sslRequestCertFailed": "Yêu cầu chứng chỉ thất bại",
"sslSave": "Lưu cài đặt",
"sslSaved": "Đã lưu cài đặt SSL",
"sslSaveFailed": "Không thể lưu cài đặt SSL",
"sslRequiresDomain": "Cần có tên miền và email",
"sslInfoNote": "Sau khi cấp hoặc tải lên chứng chỉ, Termix sẽ tự động bật HTTPS trên SSL_PORT (mặc định là 8443) bên cạnh cổng HTTP hiện có. Hãy đảm bảo rằng cổng đó đã được công bố/ánh xạ tới vùng chứa này để có thể truy cập được.",
"sslManualOption": "Hướng dẫn thủ công (tải lên chứng chỉ)",
"sslManualCert": "Chứng chỉ (PEM)",
"sslManualCertPlaceholder": "-----BẮT ĐẦU GIẤY CHỨNG NHẬN-----",
"sslManualKey": "Khóa riêng tư (PEM)",
"sslManualKeyPlaceholder": "-----BEGIN PRIVATE KEY-----",
"sslManualDesc": "Hãy dán chứng chỉ và khóa riêng hiện có của bạn, bao gồm cả chuỗi chứng chỉ đầy đủ nếu CA yêu cầu.",
"sslManualUpload": "Tải lên và cài đặt chứng chỉ",
"sslManualUploadLoading": "Đang tải chứng chỉ lên...",
"sslManualUploadSuccess": "Chứng chỉ đã được tải lên và cài đặt thành công.",
"sslManualUploadFailed": "Tải lên chứng chỉ không thành công",
"sslManualRequiresFields": "Cần có chứng chỉ và khóa riêng.",
"auditLogTotal": "Tổng số {{total}} mục",
"auditLogEmpty": "Không tìm thấy mục nhật ký kiểm tra",
"auditLogSuccess": "Thành công",
"auditLogFailed": "Thất bại",
"auditLogClearFilters": "Xóa bộ lọc",
"auditLogPage": "Trang {{page}} / {{totalPages}} (tổng {{total}})",
"auditLogIp": "IP",
"auditLogResourceId": "ID tài nguyên",
"auditLogFilterUser": "Người dùng",
"auditLogFilterAction": "Hành động",
"auditLogFilterResourceType": "Loại tài nguyên",
"auditLogFilterStatus": "Trạng thái",
"auditLogFilterFrom": "Từ",
"auditLogFilterTo": "Đến",
"auditLogFilterAll": "Tất cả",
"allowRegistration": "Cho phép đăng ký người dùng",
"allowRegistrationDesc": "Cho phép người dùng mới tự đăng ký bằng tên người dùng và mật khẩu",
"allowPasswordLogin": "Cho phép đăng nhập bằng mật khẩu",
"allowPasswordLoginDesc": "Đăng nhập bằng tên người dùng/mật khẩu",
"oidcAutoProvision": "Tự động cung cấp OIDC",
"oidcAutoProvisionDesc": "Tự động tạo tài khoản cho người dùng OIDC/SSO khi đăng nhập lần đầu (độc lập với nút bật đăng ký)",
"oidcSilentLoginDefault": "Đăng nhập OIDC tự động mặc định",
"oidcSilentLoginDefaultDesc": "Tự động chuyển hướng đến đăng nhập OIDC mỗi lần truy cập, bỏ qua hoàn toàn biểu mẫu đăng nhập",
"oidcSilentLoginDefaultLockedDesc": "Cài đặt này bị khóa bởi biến môi trường OIDC_SILENT_LOGIN_DEFAULT và không thể thay đổi ở đây.",
"allowPasswordReset": "Cho phép đặt lại mật khẩu",
"allowPasswordResetDesc": "Mã đặt lại qua nhật ký Docker",
"commandHistoryEnabled": "Lịch sử lệnh",
"commandHistoryEnabledDesc": "Cho phép ghi lịch sử lệnh. Khi tắt, lịch sử sẽ không được lưu bất kể cài đặt từng máy chủ.",
"updateCommandHistoryFailed": "Không thể cập nhật cài đặt lịch sử lệnh",
"analyticsEnabled": "Chia sẻ số liệu thống kê sử dụng ẩn danh",
"analyticsEnabledDesc": "Gửi báo cáo hàng ngày ẩn danh về số lượng người dùng, máy chủ và mức sử dụng tính năng để giúp cải thiện Termix. Không có dữ liệu cá nhân hoặc chi tiết kết nối nào được tiết lộ.",
"analyticsEnabledLockedDesc": "Cài đặt này bị khóa bởi biến môi trường ENABLE_TELEMETRY và không thể thay đổi ở đây.",
"updateAnalyticsFailed": "Không thể cập nhật cài đặt phân tích.",
"sessionSharingGloballyEnabled": "Cho phép chia sẻ phiên",
"auditForwardingTitle": "Chuyển tiếp đến SIEM",
"auditForwardingDesc": "Gửi một bản sao của mỗi mục kiểm toán đến một đơn vị thu thập dữ liệu bên ngoài dưới dạng NDJSON. Nhật ký cục bộ vẫn là nguồn thông tin chính xác.",
"auditForwardingEnvNotice": "Một biến môi trường cũng cấu hình việc chuyển tiếp; URL được lưu ở đây sẽ được ưu tiên.",
"auditForwardingToken": "Thẻ người mang (tùy chọn)",
"auditForwardingTokenStored": "Mã thông báo người mang (đã lưu trữ)",
"auditForwardingSaved": "Cài đặt chuyển tiếp kiểm toán đã được lưu",
"auditForwardingSaveError": "Không thể lưu cài đặt chuyển tiếp kiểm toán.",
"sessionSharingGloballyEnabledDesc": "Cho phép chia sẻ các phiên terminal trực tiếp, RDP, VNC và Telnet trên toàn bộ máy chủ. Khi bị vô hiệu hóa, tùy chọn này sẽ ghi đè lên mọi tùy chọn chia sẻ trên từng máy chủ riêng lẻ.",
"updateSessionSharingFailed": "Không thể cập nhật cài đặt chia sẻ phiên.",
"sessionTimeout": "Thời gian chờ phiên",
"hours": "giờ",
"sessionTimeoutRange": "Tối thiểu 1h · Tối đa 720h",
"monitoringDefaults": "Mặc định giám sát",
"statusCheck": "Kiểm tra trạng thái",
"metrics": "Số liệu",
"sec": "giây",
"logLevel": "Mức nhật ký",
"enableGuacamole": "Bật Guacamole",
"enableGuacamoleDesc": "Kết nối RDP/VNC từ xa",
"enableGuacamoleDocsLink": "Xem tài liệu",
"guacdUrl": "URL guacd",
"tailscaleApiKey": "Khóa API Tailscale",
"tailscaleApiKeyDescription": "Được sử dụng để phát hiện thiết bị trong trình chỉnh sửa máy chủ. Hỗ trợ khóa Tailscale (tskey-) và Headscale (hskey-). Tạo khóa tại tailscale.com/admin/settings/keys hoặc từ phiên bản Headscale của bạn.",
"tailscaleApiKeyDocsLink": "Xem tài liệu",
"tailscaleApiBaseUrl": "URL cơ sở của API",
"tailscaleApiBaseUrlDescription": "Tùy chọn. Trỏ đến một phiên bản Headscale tự lưu trữ thay vì api.tailscale.com. Để trống để sử dụng mặc định của Tailscale.",
"oidcDescription": "Cấu hình OpenID Connect cho SSO. Các trường đánh dấu * là bắt buộc.",
"oidcDocsLink": "Xem tài liệu",
"oidcClientId": "Client ID",
"oidcClientSecret": "Client Secret",
"oidcAuthUrl": "URL ủy quyền",
"oidcIssuerUrl": "Issuer URL",
"oidcTokenUrl": "Token URL",
"oidcUserIdentifier": "Đường dẫn định danh người dùng",
"oidcDisplayName": "Đường dẫn tên hiển thị",
"oidcScopes": "Phạm vi",
"oidcUserinfoUrl": "Ghi đè URL Userinfo",
"oidcAllowedUsers": "Người dùng được phép",
"oidcAllowedUsersDesc": "Mỗi email một dòng. Để trống để cho phép tất cả.",
"oidcAdminGroup": "Nhóm Admin",
"oidcAdminGroupDesc": "Người dùng trong nhóm này được cấp quyền admin. Để trống để tắt đồng bộ nhóm.",
"oidcGroupClaim": "Group Claim",
"oidcGroupClaimDesc": "Tùy chọn. Đường dẫn claim chứa các nhóm của người dùng. Mặc định là groups, roles, rồi group. Sử dụng cho các nhà cung cấp có claim tùy chỉnh (ví dụ: Zitadel).",
"oidcCaCert": "Chứng chỉ CA tùy chỉnh",
"oidcCaCertDesc": "Tùy chọn. Chứng chỉ CA mã hóa PEM cho các nhà cung cấp OIDC sử dụng CA riêng hoặc tự ký. Để trống để sử dụng kho tin cậy hệ thống.",
"removeOidc": "Xóa",
"usersCount": "{{count}} người dùng",
"searchUsers": "Tìm kiếm người dùng...",
"noUsers": "Không có người dùng",
"noUsersMatch": "Không có người dùng nào phù hợp với tìm kiếm của bạn.",
"pageOf": "Trang {{page}} trên {{total}}",
"createUser": "Tạo",
"newRole": "Vai trò mới",
"roleName": "Tên",
"roleDisplayName": "Tên hiển thị",
"roleDescription": "Mô tả",
"rolesCount": "{{count}} vai trò",
"createRole": "Tạo",
"creating": "Đang tạo...",
"exportDatabase": "Xuất cơ sở dữ liệu",
"exportDatabaseDesc": "Tải xuống bản sao lưu SQLite di động chứa tất cả máy chủ, thông tin đăng nhập và cài đặt.",
"export": "Xuất",
"exporting": "Đang xuất...",
"importDatabase": "Nhập cơ sở dữ liệu",
"importDatabaseDesc": "Khôi phục từ bản sao lưu .sqlite di động trên bất kỳ hệ thống cơ sở dữ liệu nào.",
"importDatabaseSelected": "Đã chọn: {{name}}",
"selectFile": "Chọn tệp",
"changeFile": "Đổi tệp",
"import": "Nhập",
"importing": "Đang nhập...",
"apiKeysCount": "{{count}} khóa",
"apiKeysDocsLink": "Xem tài liệu",
"apiKeysCliHint": "Sử dụng khóa API với Termix CLI để quản lý máy chủ từ thiết bị đầu cuối của bạn.",
"apiKeysCliLink": "Xem tài liệu CLI",
"newApiKey": "Khóa API mới",
"apiKeyCreatedWarning": "Khóa đã tạo - sao chép ngay, sẽ không hiển thị lại.",
"apiKeyName": "Tên",
"apiKeyUser": "Người dùng",
"apiKeySelectUser": "Chọn người dùng...",
"apiKeyExpiresAt": "Hết hạn lúc",
"createKey": "Tạo khóa",
"apiKeyNoExpiry": "Không hết hạn",
"revokedBadge": "ĐÃ THU HỒI",
"authTypeDual": "Xác thực kép",
"authTypeOidc": "OIDC",
"authTypeLocal": "Cục bộ",
"adminStatusAdministrator": "Quản trị viên",
"adminStatusRegularUser": "Người dùng thông thường",
"adminBadge": "QUẢN TRỊ VIÊN",
"systemBadge": "HỆ THỐNG",
"customBadge": "TÙY CHỈNH",
"youBadge": "BẠN",
"sessionsActive": "{{count}} đang hoạt động",
"sessionActive": "Hoạt động: {{time}}",
"sessionExpires": "Hết hạn: {{time}}",
"revokeAll": "Tất cả",
"revokeAllSessionsSuccess": "Đã thu hồi tất cả phiên của người dùng",
"revokeAllSessionsFailed": "Không thể thu hồi phiên",
"revokeSessionFailed": "Không thể thu hồi phiên",
"addRole": "Thêm vai trò",
"noCustomRoles": "Chưa định nghĩa vai trò tùy chỉnh",
"removeRoleFailed": "Không thể xóa vai trò",
"assignRoleFailed": "Không thể gán vai trò",
"deleteRoleFailed": "Không thể xóa vai trò",
"userAdminAccess": "Quản trị viên",
"userAdminAccessDesc": "Toàn quyền truy cập tất cả cài đặt quản trị",
"userRoles": "Vai trò",
"revokeAllUserSessions": "Thu hồi tất cả phiên",
"revokeAllUserSessionsDesc": "Buộc đăng nhập lại trên tất cả thiết bị",
"revoke": "Thu hồi",
"deleteUserWarning": "Việc xóa người dùng này là vĩnh viễn.",
"deleteUser": "Xóa {{username}}",
"deleting": "Đang xóa...",
"deleteUserFailed": "Không thể xóa người dùng",
"deleteUserSuccess": "Đã xóa người dùng \"{{username}}\"",
"deleteRoleSuccess": "Đã xóa vai trò \"{{name}}\"",
"revokeKeySuccess": "Đã thu hồi khóa \"{{name}}\"",
"revokeKeyFailed": "Không thể thu hồi khóa",
"copiedToClipboard": "Đã sao chép vào bộ nhớ tạm",
"done": "Hoàn tất",
"createUserTitle": "Tạo người dùng",
"createUserDesc": "Tạo tài khoản cục bộ mới.",
"createUserUsername": "Tên đăng nhập",
"createUserPassword": "Mật khẩu",
"createUserPasswordHint": "Tối thiểu 6 ký tự.",
"createUserEnterUsername": "Nhập tên đăng nhập",
"createUserEnterPassword": "Nhập mật khẩu",
"createUserSubmit": "Tạo người dùng",
"editUserTitle": "Quản lý người dùng: {{username}}",
"editUserDesc": "Chỉnh sửa vai trò, trạng thái quản trị, phiên và cài đặt tài khoản.",
"editUserUsername": "Tên đăng nhập",
"editUserAuthType": "Loại xác thực",
"editUserAdminStatus": "Trạng thái quản trị",
"editUserUserId": "ID người dùng",
"linkAccountTitle": "Liên kết tài khoản",
"linkAccountDesc": "Hợp nhất tài khoản OIDC {{username}} với một tài khoản cục bộ hiện có.",
"linkAccountDescLocal": "Liên kết tài khoản cục bộ {{username}} với một tài khoản chỉ dùng OIDC hiện có.",
"linkAccountWarningTitle": "Hành động này sẽ:",
"linkAccountEffect1": "Xóa tài khoản chỉ dùng OIDC",
"linkAccountEffect2": "Thêm đăng nhập OIDC vào tài khoản đích",
"linkAccountEffect3": "Cho phép cả đăng nhập OIDC và mật khẩu",
"linkAccountTargetUsername": "Tên đăng nhập tài khoản cục bộ",
"linkAccountTargetPlaceholder": "Nhập tên đăng nhập tài khoản cục bộ để liên kết",
"linkAccountOidcUsername": "Tên đăng nhập tài khoản OIDC",
"linkAccountOidcPlaceholder": "Nhập tên đăng nhập tài khoản chỉ dùng OIDC để hợp nhất vào",
"linkAccountOidcNotFound": "Không tìm thấy tài khoản chỉ dùng OIDC nào với tên đăng nhập đó",
"linkAccounts": "Liên kết tài khoản",
"linkAccountSuccess": "Liên kết tài khoản thành công",
"linkAccountFailed": "Liên kết tài khoản thất bại",
"linkAccountInProgress": "Đang liên kết...",
"unlinkAccountTitle": "Hủy liên kết OIDC",
"unlinkAccountDesc": "Xóa xác thực OIDC khỏi {{username}}. Người dùng sẽ chỉ có thể đăng nhập bằng mật khẩu.",
"unlinkAccountWarning": "Hành động này sẽ xóa đăng nhập OIDC khỏi tài khoản này. Người dùng phải thiết lập mật khẩu để tiếp tục đăng nhập.",
"unlinkAccount": "Hủy liên kết OIDC",
"unlinkAccountInProgress": "Đang hủy liên kết...",
"unlinkAccountSuccess": "Hủy liên kết OIDC thành công",
"unlinkAccountFailed": "Hủy liên kết OIDC thất bại",
"saving": "Đang lưu...",
"updateRegistrationFailed": "Cập nhật cài đặt đăng ký thất bại",
"updatePasswordLoginFailed": "Cập nhật cài đặt đăng nhập bằng mật khẩu thất bại",
"cannotDisablePasswordLoginWithTotp": "Không thể vô hiệu hóa đăng nhập bằng mật khẩu khi 2FA đang được bật cho một hoặc nhiều người dùng. Hãy tắt 2FA trước.",
"updateOidcAutoProvisionFailed": "Cập nhật cài đặt tự động cấp quyền OIDC thất bại",
"updateOidcSilentLoginDefaultFailed": "Cập nhật cài đặt đăng nhập OIDC im lặng thất bại",
"updatePasswordResetFailed": "Cập nhật cài đặt đặt lại mật khẩu thất bại",
"sessionTimeoutRange2": "Thời gian chờ phiên phải từ 1 đến 720 giờ",
"sessionTimeoutSaved": "Thời gian chờ phiên đã được lưu",
"sessionTimeoutSaveFailed": "Lưu thời gian chờ phiên thất bại",
"monitoringIntervalInvalid": "Giá trị khoảng thời gian không hợp lệ",
"monitoringSaved": "Cài đặt giám sát đã được lưu",
"monitoringSaveFailed": "Lưu cài đặt giám sát thất bại",
"metricsHistoryRetention": "Thời gian lưu trữ lịch sử số liệu",
"metricsHistoryRetentionRange": "1 đến 90 ngày",
"days": "ngày",
"guacamoleSaved": "Cài đặt Guacamole đã được lưu",
"guacamoleSaveFailed": "Lưu cài đặt Guacamole thất bại",
"guacamoleUpdateFailed": "Cập nhật cài đặt Guacamole thất bại",
"tailscaleSettingsSaved": "Cài đặt Tailscale đã được lưu",
"tailscaleSettingsSaveFailed": "Lưu cài đặt Tailscale thất bại",
"logLevelUpdateFailed": "Cập nhật mức ghi nhật ký thất bại",
"oidcSaved": "Cấu hình OIDC đã được lưu",
"oidcSaveFailed": "Lưu cấu hình OIDC thất bại",
"oidcRemoved": "Cấu hình OIDC đã được gỡ bỏ",
"oidcRemoveFailed": "Gỡ bỏ cấu hình OIDC thất bại",
"createUserRequired": "Tên đăng nhập và mật khẩu là bắt buộc",
"createUserPasswordTooShort": "Mật khẩu phải có ít nhất 6 ký tự",
"createUserSuccess": "Người dùng \"{{username}}\" đã được tạo",
"createUserFailed": "Tạo người dùng thất bại",
"updateAdminStatusFailed": "Cập nhật trạng thái quản trị viên thất bại",
"allSessionsRevoked": "Tất cả các phiên đã bị thu hồi",
"revokeSessionsFailed": "Thu hồi phiên thất bại",
"manageUserData": "Quản lý dữ liệu người dùng",
"backToUsers": "Quay lại danh sách người dùng",
"manageTabAccount": "Tài khoản",
"manageTabHosts": "Máy chủ",
"manageTabCredentials": "Thông tin xác thực",
"manageTabSnippets": "Đoạn mã",
"manageTabSessions": "Phiên",
"manageTabDanger": "Nguy hiểm",
"manageEditorBack": "Quay lại dữ liệu của {{username}}",
"dataLockedBadge": "ĐÃ KHÓA",
"dataLockedNotice": "Dữ liệu của {{username}} vẫn bị khóa cho đến khi họ đăng nhập lần tiếp theo. Máy chủ, thông tin đăng nhập và đoạn mã của họ không thể xem hoặc chỉnh sửa cho đến lúc đó.",
"resetPasswordTitle": "Đặt lại mật khẩu",
"resetPasswordOidcOnly": "Người dùng này đăng nhập qua nhà cung cấp bên ngoài và không có mật khẩu.",
"resetPasswordPlaceholder": "Mật khẩu mới",
"resetPasswordBtn": "Đặt lại",
"resetPasswordWorking": "Đang đặt lại...",
"resetPasswordSuccess": "Đã đặt lại mật khẩu",
"resetPasswordSuccessWiped": "Đã đặt lại mật khẩu. Dữ liệu mã hóa của người dùng đã bị xóa.",
"resetPasswordFailed": "Không thể đặt lại mật khẩu",
"resetPasswordConfirmWipe": "{{username}} chưa đăng nhập kể từ khi nâng cấp mã hóa, do đó dữ liệu của họ không thể khôi phục. Đặt lại ngay bây giờ sẽ xóa máy chủ, thông tin đăng nhập và đoạn mã của họ. Tiếp tục?",
"totpSectionTitle": "Xác thực hai yếu tố",
"totpStatusEnabled": "TOTP đã được bật cho người dùng này",
"totpStatusDisabled": "TOTP chưa được bật cho người dùng này",
"disableTotp": "Vô hiệu hóa",
"disableTotpConfirm": "Vô hiệu hóa xác thực hai yếu tố cho {{username}}? Họ sẽ có thể đăng nhập chỉ bằng mật khẩu.",
"totpDisabledSuccess": "Đã vô hiệu hóa TOTP",
"totpDisableFailed": "Không thể vô hiệu hóa TOTP",
"manageApiKeys": "Khóa API",
"apiKeyNamePlaceholder": "Tên khóa",
"apiKeyCopyNotice": "Sao chép khóa này ngay, sẽ không hiển thị lại.",
"noApiKeysForUser": "Không có khóa API",
"apiKeyDeleteFailed": "Không thể xóa khóa API",
"exportUserData": "Xuất dữ liệu",
"exportUserDataDesc": "Tải xuống máy chủ, thông tin đăng nhập và dữ liệu quản lý tệp của người dùng này dưới dạng JSON. Các bí mật được giải mã.",
"exportUserDataSuccess": "Đã xuất dữ liệu người dùng",
"exportUserDataFailed": "Không thể xuất dữ liệu người dùng",
"hostsCount": "{{count}} máy chủ",
"addHostForUser": "Thêm máy chủ",
"noHostsForUser": "Người dùng này không có máy chủ nào",
"connectToHost": "Kết nối",
"deleteHostConfirm": "Xóa máy chủ \"{{name}}\" thuộc về {{username}}?",
"hostDeletedSuccess": "Đã xóa máy chủ",
"hostDeleteFailed": "Không thể xóa máy chủ",
"credentialsCount": "{{count}} thông tin đăng nhập",
"addCredentialForUser": "Thêm thông tin đăng nhập",
"noCredentialsForUser": "Người dùng này không có thông tin xác thực",
"deleteCredentialConfirm": "Xóa thông tin xác thực \"{{name}}\" của {{username}}?",
"credentialDeletedSuccess": "Đã xóa thông tin xác thực",
"credentialDeleteFailed": "Xóa thông tin xác thực thất bại",
"snippetsCount": "{{count}} đoạn mã",
"addSnippetForUser": "Thêm đoạn mã",
"noSnippetsForUser": "Người dùng này không có đoạn mã nào",
"snippetRequiredFields": "Cần tên và nội dung đoạn mã",
"snippetNamePlaceholder": "Tên đoạn mã",
"snippetContentPlaceholder": "Nội dung lệnh",
"snippetFolderPlaceholder": "Thư mục (tùy chọn)",
"snippetSaved": "Đã lưu đoạn mã",
"snippetSaveFailed": "Lưu đoạn mã thất bại",
"deleteSnippetConfirm": "Xóa đoạn mã \"{{name}}\" của {{username}}?",
"snippetDeletedSuccess": "Đã xóa đoạn mã",
"snippetDeleteFailed": "Xóa đoạn mã thất bại",
"noSessionsForUser": "Không có phiên làm việc đang hoạt động",
"deleteSuccessorLabel": "Hãy chuyển giao máy chủ và thông tin đăng nhập cho",
"deleteSuccessorMe": "Tôi (người quản trị xóa)",
"deleteSuccessorNone": "Không ai cả — hãy xóa chúng đi",
"deleteSuccessorDesc": "Mọi thứ người dùng này chia sẻ vẫn hoạt động bình thường dưới quyền sở hữu mới; việc chọn \"không ai\" sẽ xóa máy chủ, thông tin đăng nhập và các thư mục chia sẻ của họ.",
"deleteUserDangerDesc": "Xóa vĩnh viễn {{username}} và toàn bộ dữ liệu (máy chủ, thông tin xác thực, đoạn mã, lịch sử). Không thể hoàn tác.",
"deleteUserConfirm": "Xóa vĩnh viễn {{username}} và toàn bộ dữ liệu?",
"deleteUserAdminBlocked": "Hãy bỏ quyền quản trị trước khi xóa người dùng này.",
"createRoleRequired": "Cần tên và tên hiển thị",
"createRoleSuccess": "Đã tạo vai trò \"{{name}}\"",
"createRoleFailed": "Tạo vai trò thất bại",
"apiKeyNameRequired": "Cần tên khóa",
"apiKeyUserRequired": "Cần ID người dùng",
"apiKeyCreatedSuccess": "Đã tạo khóa API \"{{name}}\"",
"apiKeyCreateFailed": "Tạo khóa API thất bại",
"exportSuccess": "Đã xuất cơ sở dữ liệu thành công",
"exportFailed": "Xuất cơ sở dữ liệu thất bại",
"importSelectFile": "Vui lòng chọn tệp trước",
"importCompleted": "Đã nhập xong: đã nhập {{total}} mục, bỏ qua {{skipped}}",
"importFailed": "Nhập thất bại: {{error}}",
"importError": "Nhập cơ sở dữ liệu thất bại",
"sectionHostDefaults": "Mặc định máy chủ",
"hostDefaultsDesc": "Cài đặt được áp dụng tự động khi tạo máy chủ mới. Các máy chủ riêng lẻ vẫn có thể ghi đè.",
"hostDefaultsSocks5": "Proxy SOCKS5",
"hostDefaultsUseSocks5": "Bật Proxy SOCKS5",
"hostDefaultsUseSocks5Desc": "Điền sẵn proxy SOCKS5 cho tất cả máy chủ mới",
"hostDefaultsSocks5Host": "Máy chủ / Cổng proxy",
"hostDefaultsSocks5Username": "Tên đăng nhập proxy",
"hostDefaultsSocks5Password": "Mật khẩu proxy",
"hostDefaultsMetrics": "Số liệu máy chủ",
"hostDefaultsMetricsEnabled": "Bật số liệu",
"hostDefaultsMetricsEnabledDesc": "Mặc định thu thập CPU, bộ nhớ và các số liệu khác trên máy chủ mới",
"hostDefaultsStatusCheckEnabled": "Bật kiểm tra trạng thái",
"hostDefaultsStatusCheckEnabledDesc": "Mặc định kiểm tra trạng thái trực tuyến/ngoại tuyến trên máy chủ mới",
"hostDefaultsTerminal": "Terminal",
"hostDefaultsAutoTmux": "Auto-Tmux",
"hostDefaultsAutoTmuxDesc": "Chạy các cửa sổ terminal của máy chủ mới bên trong tmux để đảm bảo phiên làm việc vẫn hoạt động sau khi ngắt kết nối (cần cài đặt tmux trên máy chủ).",
"terminalSessionTimeout": "Duy trì phiên đầu cuối",
"terminalSessionTimeoutDesc": "Thời gian duy trì kết nối của một thiết bị đầu cuối bị ngắt kết nối trên máy chủ trước khi nó bị đóng. Tối thiểu 1 phút · Tối đa 1440 phút. Đối với các phiên cần duy trì lâu hơn thời gian này, hãy bật Auto-Tmux trên máy chủ.",
"terminalSessionTimeoutRange": "Nhập giá trị nằm trong khoảng từ 1 đến 1440 phút.",
"terminalSessionTimeoutSaved": "Lưu trữ phiên làm việc của thiết bị đầu cuối",
"terminalSessionTimeoutSaveFailed": "Không thể lưu trạng thái phiên làm việc của thiết bị đầu cuối",
"minutes": "phút",
"hostDefaultsSessionLogging": "Ghi phiên",
"hostDefaultsSessionLoggingDesc": "Mặc định ghi lại phiên terminal trên máy chủ mới",
"hostDefaultsCommandHistory": "Lịch sử lệnh",
"hostDefaultsCommandHistoryDesc": "Mặc định theo dõi lịch sử lệnh trên máy chủ mới",
"hostDefaultsSaved": "Đã lưu mặc định máy chủ",
"hostDefaultsSaveFailed": "Không lưu được mặc định máy chủ",
"rolePermissions": {
"count": "{{count}} quyền",
"editAction": "Chỉnh sửa quyền",
"loadError": "Không tải được danh mục quyền",
"saved": "Đã lưu quyền vai trò",
"saveError": "Không lưu được quyền vai trò",
"save": "Lưu",
"saving": "Đang lưu..."
},
"aiGloballyEnabled": "Trợ lý AI",
"aiGloballyEnabledDesc": "Cho phép người dùng bật trợ lý AI. Khi trợ lý này tắt, nó sẽ bị ẩn và chặn đối với tất cả mọi người.",
"aiPrivateEndpoints": "Cho phép máy chủ AI riêng",
"aiPrivateEndpointsDesc": "Các máy chủ trên mạng riêng của bạn mà người dùng có thể trỏ đến nhà cung cấp, chẳng hạn như Ollama tự lưu trữ. Phân tách chúng bằng dấu phẩy.",
"stepCa": "Bước CA",
"stepCaDesc": "Cấp chứng chỉ SSH có thời hạn ngắn từ CA smallstep. Nhập URL của CA, dấu vân tay gốc của nó (như hiển thị bởi step ca bootstrap) và tên của trình cung cấp OIDC; sau đó chọn \"Step CA\" làm loại xác thực của máy chủ. Để trống cả ba trường để vô hiệu hóa.",
"stepCaFingerprint": "Dấu vân tay gốc (SHA-256)",
"stepCaProvisioner": "Tên trình cung cấp OIDC",
"stepCaSaved": "Cài đặt bước CA đã được lưu",
"stepCaSaveFailed": "Không thể lưu cài đặt Bước CA.",
"secretSourcePrivateEndpoints": "Các máy chủ nguồn bí mật riêng tư được cho phép",
"secretSourcePrivateEndpointsDesc": "Các máy chủ riêng tư mà các nguồn bí mật (1Password Connect) có thể liên hệ. Phân tách chúng bằng dấu phẩy.",
"updateSecretSourceEndpointsFailed": "Không thể cập nhật danh sách cho phép điểm cuối nguồn bí mật.",
"stepCaPrivateEndpoints": "Cho phép máy chủ Step CA riêng tư",
"stepCaPrivateEndpointsDesc": "Các máy chủ riêng mà quy trình chứng chỉ CA từng bước có thể liên hệ: chính CA và, nếu là máy chủ nội bộ, nhà cung cấp danh tính của bạn. Phân tách chúng bằng dấu phẩy.",
"updateStepCaEndpointsFailed": "Không thể cập nhật danh sách cho phép điểm cuối Step CA.",
"notificationPrivateEndpoints": "Cho phép máy chủ thông báo riêng tư",
"notificationPrivateEndpointsDesc": "Liệt kê chính xác các máy chủ riêng mà kênh thông báo có thể liên hệ. Phân tách chúng bằng dấu phẩy.",
"updateNotificationEndpointsFailed": "Không thể cập nhật danh sách cho phép điểm cuối thông báo.",
"updateAiEnabledFailed": "Không thể cập nhật cài đặt AI.",
"updateAiEndpointsFailed": "Không thể cập nhật các máy chủ được cho phép"
},
"newUi": {
"sidebar": {
"quickConnect": {
"hostLabel": "Máy chủ",
"hostPlaceholder": "192.168.1.1 or example.com",
"portLabel": "Cổng",
"portPlaceholder": "22",
"usernameLabel": "Tên đăng nhập",
"usernamePlaceholder": "tên đăng nhập",
"authLabel": "Xác thực",
"passwordLabel": "Mật khẩu",
"passwordPlaceholder": "mật khẩu",
"privateKeyLabel": "Khóa riêng",
"privateKeyPlaceholder": "Dán khóa riêng...",
"credentialLabel": "Thông tin đăng nhập",
"credentialPlaceholder": "Chọn thông tin đăng nhập đã lưu",
"protocolLabel": "Giao thức",
"domainLabel": "Lãnh địa",
"domainPlaceholder": "không bắt buộc",
"connectToRdp": "Kết nối qua RDP",
"connectToVnc": "Kết nối qua VNC",
"connectToTerminal": "Kết nối đến Terminal",
"connectToFiles": "Kết nối đến Files"
},
"history": {
"noTerminalSelected": "Chưa chọn terminal",
"noTerminalSelectedHint": "Mở một tab terminal SSH để xem lịch sử lệnh",
"searchPlaceholder": "Tìm kiếm lịch sử...",
"clearAll": "Xóa tất cả",
"noHistoryEntries": "Không có mục lịch sử",
"trackingDisabled": "Tính năng ghi lịch sử đã bị tắt",
"trackingDisabledHint": "Bật tính năng này trong cài đặt terminal của máy chủ."
},
"sshTools": {
"keyRecordingTitle": "Ghi phím",
"recordToTerminals": "Ghi vào các terminal",
"selectAll": "Tất cả",
"selectNone": "Không chọn",
"noTerminalTabsOpen": "Không có tab terminal nào mở",
"selectTerminalsAbove": "Chọn các terminal ở trên",
"broadcastInputPlaceholder": "Nhập vào đây để phát tán thao tác phím...",
"fillPassword": "Điền mật khẩu",
"fillPasswordSuccess": "Đã điền mật khẩu vào {{count}} terminal",
"fillPasswordMissing": "Không có mật khẩu đã lưu cho {{count}} terminal đã chọn",
"stopRecording": "Dừng ghi",
"startRecording": "Bắt đầu ghi",
"settingsTitle": "Cài đặt",
"enableRightClickCopyPaste": "Bật sao chép/dán bằng chuột phải",
"copyOnSelect": "Sao chép văn bản đã chọn tự động"
},
"splitScreen": {
"layoutTitle": "Bố cục",
"selectLayoutAbove": "Chọn bố cục bên trên",
"selectLayoutHint": "Chọn số lượng ô hiển thị",
"panesTitle": "Các ô",
"openTabsTitle": "Các tab đang mở",
"dragTabsHint": "Kéo tab vào các ô phía trên, hoặc dùng Gán nhanh",
"dropHere": "Thả vào đây",
"emptyPane": "Trống",
"dashboard": "Bảng điều khiển",
"clearSplitScreen": "Xóa chia màn hình",
"quickAssign": "Gán nhanh",
"alreadyAssigned": "Khung {{index}}",
"splitTab": "Tách tab",
"addToSplit": "Thêm vào chia màn hình",
"removeFromSplit": "Xóa khỏi chia màn hình",
"assignToPane": "Gán vào khung",
"hotkeysTitle": "Phím tắt",
"hotkeysSplitRight": "Bật/tắt chia đôi",
"hotkeysSplitBelow": "Bật/tắt chia ba",
"hotkeysNavigatePane": "Điều hướng khung",
"hotkeysNextTab": "Tab tiếp theo",
"hotkeysPrevTab": "Tab trước",
"hotkeysJumpTab": "Chuyển đến tab"
},
"snippets": {
"title": "Đoạn mã",
"createSnippetTitle": "Tạo đoạn mã",
"createSnippetDescription": "Tạo đoạn mã lệnh mới để thực thi nhanh",
"nameLabel": "Tên",
"namePlaceholder": "Ví dụ: Khởi động lại Nginx",
"descriptionLabel": "Mô tả",
"descriptionPlaceholder": "Mô tả tùy chọn",
"optional": "Tùy chọn",
"folderLabel": "Thư mục",
"noFolder": "Không thư mục (Chưa phân loại)",
"commandLabel": "Lệnh",
"commandPlaceholder": "Ví dụ: sudo systemctl restart nginx",
"typeLabel": "Kiểu",
"typeCommand": "Yêu cầu",
"typeNote": "Ghi chú",
"noteLabel": "Ghi chú",
"notePlaceholder": "Ví dụ: một lời nhắc hoặc văn bản nhắc nhở có thể tái sử dụng.",
"cancel": "Hủy",
"createSnippetButton": "Tạo đoạn mã",
"createFolderTitle": "Tạo thư mục",
"createFolderDescription": "Sắp xếp đoạn mã vào các thư mục",
"folderNameLabel": "Tên thư mục",
"folderNamePlaceholder": "Ví dụ: Lệnh hệ thống, Docker Scripts",
"folderColorLabel": "Màu thư mục",
"folderIconLabel": "Biểu tượng thư mục",
"previewLabel": "Xem trước",
"folderNameFallback": "Tên thư mục",
"createFolderButton": "Tạo thư mục",
"targetTerminals": "Terminal đích",
"selectAll": "Tất cả",
"selectNone": "Không chọn",
"noTerminalTabsOpen": "Không có tab terminal nào mở",
"searchPlaceholder": "Tìm kiếm snippet...",
"newSnippet": "Snippet mới",
"newFolder": "Thư mục mới",
"run": "Chạy",
"noSnippetsInFolder": "Không có snippet nào trong thư mục này",
"uncategorized": "Chưa phân loại",
"editSnippetTitle": "Chỉnh sửa snippet",
"editSnippetDescription": "Cập nhật snippet lệnh này",
"saveSnippetButton": "Lưu thay đổi",
"createSuccess": "Đã tạo snippet thành công",
"createFailed": "Tạo snippet thất bại",
"updateSuccess": "Đã cập nhật snippet thành công",
"updateFailed": "Cập nhật snippet thất bại",
"deleteFailed": "Xóa snippet thất bại",
"folderCreateSuccess": "Đã tạo thư mục thành công",
"folderCreateFailed": "Tạo thư mục thất bại",
"editFolderTitle": "Chỉnh sửa thư mục",
"editFolderDescription": "Đổi tên hoặc thay đổi hình thức của thư mục này",
"saveFolderButton": "Lưu thay đổi",
"editFolder": "Chỉnh sửa thư mục",
"deleteFolder": "Xóa thư mục",
"folderDeleteSuccess": "Đã xóa thư mục \"{{name}}\"",
"folderDeleteFailed": "Xóa thư mục thất bại",
"folderEditSuccess": "Đã cập nhật thư mục thành công",
"folderEditFailed": "Cập nhật thư mục thất bại",
"confirmRunMessage": "Chạy \"{{name}}\"?",
"confirmRunButton": "Chạy",
"runSuccess": "Đã chạy \"{{name}}\" trên {{count}} terminal",
"pasteSuccess": "Đã dán \"{{name}}\" vào {{count}} thiết bị đầu cuối",
"pasteToTerminal": "Dán",
"copySuccess": "Đã sao chép \"{{name}}\" vào clipboard",
"shareTitle": "Chia sẻ snippet",
"shareUser": "Người dùng",
"shareRole": "Vai trò",
"selectUser": "Chọn người dùng...",
"selectRole": "Chọn vai trò...",
"shareSuccess": "Đã chia sẻ đoạn mã thành công",
"shareFailed": "Chia sẻ đoạn mã thất bại",
"revokeSuccess": "Đã thu hồi quyền truy cập",
"revokeFailed": "Thu hồi quyền truy cập thất bại",
"currentAccess": "Quyền truy cập hiện tại",
"shareLoadError": "Tải dữ liệu chia sẻ thất bại",
"loading": "Đang tải...",
"close": "Đóng",
"reorderFailed": "Lưu thứ tự đoạn mã thất bại",
"importExport": "Nhập / Xuất",
"exportBtn": "Xuất JSON",
"importBtn": "Nhập JSON",
"exportSuccess": "Đã xuất đoạn mã thành công",
"exportFailed": "Xuất đoạn mã thất bại",
"importTitle": "Nhập đoạn mã",
"importDescription": "Nhập đoạn mã và thư mục từ tệp JSON được Termix xuất ra",
"importDropOrClick": "Kéo thả tệp JSON vào đây hoặc nhấn để duyệt",
"importSelectedFile": "Đã chọn: {{name}}",
"importOverwrite": "Ghi đè đoạn mã hiện có cùng tên và thư mục",
"importStartBtn": "Nhập",
"importSuccess": "Nhập xong: đã thêm {{snippets}} đoạn mã, cập nhật {{updated}}, bỏ qua {{skipped}}, thêm {{folders}} thư mục",
"importFailed": "Nhập đoạn mã thất bại",
"importInvalidFile": "Tệp không hợp lệ: cần một đối tượng JSON với mảng đoạn mã hoặc thư mục",
"targetHostsLabel": "Máy chủ đích",
"targetHostsHint": "Gán máy chủ để chạy đoạn mã này trực tiếp mà không cần mở terminal.",
"noHostsAvailable": "Chưa cấu hình máy chủ nào",
"clearTargetHosts": "Xóa tất cả",
"hasTargetHosts": "Có máy chủ đích",
"runOnTargets": "Chạy trên máy đích",
"directRunSuccess": "Đã chạy \"{{name}}\" trên {{count}} máy chủ",
"directRunPartialFail": "\"{{name}}\" chạy thất bại trên một hoặc nhiều máy chủ",
"executionResultTitle": "Kết quả thực thi: {{name}}",
"executionResultDescription": "Kết quả từ việc chạy đoạn mã trên từng máy đích.",
"executionSuccess": "Thành công",
"executionFailed": "Thất bại",
"expandAll": "Mở rộng tất cả các thư mục",
"collapseAll": "Thu gọn tất cả các thư mục",
"settings": "Cài đặt đoạn mã",
"variablesHint": "Biến: $HOST, $USER, $PORT, $NAME, ${INPUT_1:Label}",
"variablesDialogTitle": "Chạy \"{{name}}\"",
"variablesDialogDescription": "Hãy điền đầy đủ các giá trị cần thiết cho đoạn mã này trước khi chạy.",
"variablesPreviewLabel": "Xem trước",
"variablesConfirmButton": "Chạy"
},
"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.",
"emptyChannels": "Chưa có kênh nào. Thêm một kênh để gửi thông báo đến đâu đó.",
"noChannelsHint": "Chưa có kênh nào được thiết lập. Thêm một kênh trong tab Kênh.",
"addChannel": "Thêm kênh",
"testChannel": "Bài kiểm tra",
"channelTestSent": "Thông báo kiểm tra đã được gửi",
"channelTestFailed": "Thông báo kiểm tra thất bại",
"channelDeleted": "Kênh đã bị xóa",
"deleteChannelConfirm": "Xóa kênh này? Các tự động hóa sử dụng kênh này sẽ ngừng gửi thông báo.",
"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": "Sự miêu 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": "Cứ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ó chạy theo từng 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": "Cò súng",
"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": "Không 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ả người chủ trì"
},
"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": "Dừng lại"
},
"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": "Chủ nhà",
"metric": "Số liệu",
"mount": "Điểm gắn kết",
"operator": "Là",
"value": "Giá trị",
"forSeconds": "Duy trì trong (giây)",
"cooldown": "Thời gian hồi chiêu (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": "Yêu cầu",
"url": "URL",
"method": "Phương pháp",
"body": "Thân hình",
"channels": "Kênh",
"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"
}
},
"fleets": {
"title": "Hạm đội",
"createFleet": "Tạo đội tàu",
"createFleetTitle": "Tạo đội tàu",
"editFleetTitle": "Chỉnh sửa đội xe",
"createFleetDescription": "Hạm đội là một nhóm máy chủ được đặt tên mà bạn có thể thực hiện các hành động chống lại chúng như một đơn vị.",
"nameLabel": "Tên",
"namePlaceholder": "Ví dụ: Máy chủ web",
"nameRequired": "Tên đội xe là bắt buộc",
"descriptionLabel": "Sự miêu tả",
"descriptionPlaceholder": "Mô tả tùy chọn",
"colorLabel": "Màu sắc",
"tagRulesLabel": "Quy tắc gắn thẻ",
"tagRulesPlaceholder": "web sản xuất, cạnh",
"tagRulesHint": "Các máy chủ có bất kỳ thẻ nào trong số này sẽ tự động được thêm vào, bên cạnh các máy chủ được thêm thủ công.",
"fleetCreated": "Hạm đội đã tạo ra",
"fleetUpdated": "Đội tàu được cập nhật",
"fleetDeleted": "Hạm đội đã bị xóa",
"saveFailed": "Không thể cứu hạm đội.",
"deleteFailed": "Không thể xóa đội tàu",
"loadFailed": "Không thể tải đội xe",
"deleteFleetTitle": "Xóa hạm đội",
"deleteFleetDescription": "Bạn có chắc chắn muốn xóa \"{{name}}\" không? Thao tác này không xóa các máy chủ thành viên.",
"searchFleets": "Các hạm đội tìm kiếm...",
"noFleets": "Chưa có hạm đội nào. Hãy tạo một hạm đội để bắt đầu.",
"memberCount": "{{count}} máy chủ",
"memberCount_other": "{{count}} máy chủ",
"manageMembers": "Quản lý thành viên",
"manageMembersTitle": "Quản lý thành viên đội xe",
"manageMembersDescription": "Cho phép thêm hoặc xóa các máy chủ khỏi tư cách thành viên cố định của nhóm này. Các máy chủ phù hợp với quy tắc gắn thẻ luôn được bao gồm.",
"searchHosts": "Tìm kiếm máy chủ...",
"noHostsFound": "Không tìm thấy máy chủ nào",
"noMembers": "Hạm đội này chưa có thành viên nào. Thêm máy chủ hoặc thiết lập quy tắc gắn thẻ.",
"membersLoadFailed": "Không thể tải thông tin thành viên đội xe",
"memberUpdateFailed": "Không thể cập nhật thông tin thành viên đội tàu",
"tabRun": "Chạy lệnh",
"tabTransfer": "Chuyển tập tin",
"tabInventory": "Hàng tồn kho",
"openInventoryTab": "Mở ở chế độ toàn màn hình",
"tabPackages": "Gói hàng",
"runOnFleet": "Chạy trên Fleet",
"commandPlaceholder": "thời gian hoạt động && df -h",
"commandRequired": "Cần có lệnh",
"commandInputsLabel": "Đầu vào lệnh",
"commandSucceeded": "Lệnh đã được thực thi thành công trên tất cả các máy chủ.",
"commandPartialFailure": "{{failed}} trong số {{total}} máy chủ đã bị lỗi",
"commandFailed": "Không thể chạy lệnh.",
"resultSuccess": "Thành công",
"resultFailed": "Thất bại",
"push": "Xô",
"pull": "Sự lôi kéo",
"remotePathLabel": "Đường dẫn từ xa",
"remotePathRequired": "Cần có một đường dẫn từ xa.",
"fileLabel": "Tài liệu",
"fileRequired": "Cần có một tập tin.",
"pushHint": "Tệp đã chọn sẽ được ghi vào đúng đường dẫn này trên mọi máy chủ trong hệ thống.",
"pullHint": "Tệp tại đường dẫn này được đọc từ mọi máy chủ và tải xuống dưới dạng một tệp zip duy nhất, mỗi máy chủ một thư mục.",
"transferComplete": "Giao dịch hoàn tất",
"transferFailed": "Giao dịch chuyển khoản thất bại",
"refreshInventory": "Làm mới kho hàng",
"inventoryLoadFailed": "Không thể tải kho hàng",
"inventoryRefreshed": "Hàng tồn kho được cập nhật",
"inventoryRefreshFailed": "Không thể làm mới kho hàng",
"inventoryNoData": "Chưa có dữ liệu tồn kho - hãy làm mới trang để thu thập dữ liệu.",
"inventoryHost": "Chủ nhà",
"inventoryCollectedCount": "{{count}}/{{total}} đã thu thập",
"inventoryOs": "Hệ điều hành",
"inventoryKernel": "Hạt nhân",
"inventoryArch": "Vòm",
"inventoryUptime": "Thời gian hoạt động",
"inventoryPackageManager": "Trình quản lý gói",
"inventoryCollectedAt": "Đã thu thập",
"packageActionLabel": "Hoạt động",
"packageInstall": "Cài đặt",
"packageRemove": "Di dời",
"packageUpgradeAll": "Nâng cấp tất cả các gói",
"packageNameLabel": "Tên gói",
"packageNameRequired": "Cần phải có tên gói.",
"packageHint": "Yêu cầu quyền truy cập cấp quản trị cho mỗi máy chủ và nâng quyền bằng mật khẩu sudo được lưu trữ trên máy chủ đó."
},
"workspaces": {
"title": "Không gian làm việc",
"saveCurrent": "Lưu hiện tại",
"saveCurrentTitle": "Lưu không gian làm việc hiện tại",
"saveCurrentDescription": "Lưu tất cả các tab đang mở, bố cục chia màn hình và cách sắp xếp khung cửa sổ dưới dạng một không gian làm việc mới có tên.",
"nameLabel": "Tên",
"namePlaceholder": "Ví dụ: Gỡ lỗi sản phẩm",
"nameRequired": "Tên không gian làm việc là bắt buộc",
"colorLabel": "Màu sắc",
"workspaceCreated": "Không gian làm việc đã được lưu",
"workspaceUpdated": "Không gian làm việc đã được cập nhật",
"workspaceDeleted": "Không gian làm việc đã bị xóa",
"workspaceDuplicated": "Không gian làm việc được sao chép",
"saveFailed": "Không thể lưu không gian làm việc",
"updateFailed": "Không thể cập nhật không gian làm việc",
"deleteFailed": "Không thể xóa không gian làm việc",
"duplicateFailed": "Không thể sao chép không gian làm việc",
"loadFailed": "Không thể tải không gian làm việc",
"applyFailed": "Không thể áp dụng không gian làm việc",
"deleteWorkspaceTitle": "Xóa không gian làm việc",
"deleteWorkspaceDescription": "Bạn có chắc chắn muốn xóa \"{{name}}\" không? Thao tác này không thể hoàn tác.",
"noWorkspaces": "Chưa có không gian làm việc nào được lưu. Hãy lưu cách bố trí tab hiện tại của bạn để bắt đầu.",
"tabCount": "{{count}} tab",
"tabCount_other": "{{count}} tab",
"apply": "Áp dụng",
"applyConfirmTitle": "Áp dụng Không gian làm việc",
"applyConfirmDescription": "Áp dụng \"{{name}}\" sẽ đóng các tab hiện tại của bạn và thay thế chúng bằng bố cục đã lưu của không gian làm việc này. Các thay đổi chưa được lưu đối với bố cục hiện tại của bạn sẽ bị mất.",
"applyConfirmButton": "Áp dụng Không gian làm việc",
"updateWithCurrent": "Cập nhật với thông tin hiện tại",
"updateWithCurrentConfirm": "Bạn có muốn ghi đè \"{{name}}\" bằng cách sắp xếp tab hiện tại của mình không?",
"rename": "Đổi tên",
"duplicate": "Nhân bản",
"duplicateNameSuffix": "{{name}} (copy)",
"setDefault": "Đặt làm mặc định",
"unsetDefault": "Xóa khỏi danh sách mặc định",
"defaultBadge": "Mặc định",
"lastSession": "Phiên cuối cùng",
"lastSessionDescription": "Tự động cập nhật với cách sắp xếp tab gần đây nhất của bạn. Áp dụng để khôi phục các tab bạn đã mở trước đó.",
"lastUsed": "Lần sử dụng cuối cùng {{time}}",
"neverUsed": "Chưa từng ứng tuyển",
"tabsSkipped": "Không gian làm việc đã được áp dụng — {{count}} tab đã bị bỏ qua (máy chủ không còn tồn tại): {{names}}"
},
"keybindings": {
"title": "Phím tắt",
"description": "Tùy chỉnh các phím tắt sao chép, dán và điều khiển trong terminal, hoặc gán phím để gửi văn bản hoặc chạy một đoạn mã.",
"defaultsHeading": "Phím tắt tích hợp sẵn",
"customHeading": "Phím tắt tùy chỉnh",
"addBinding": "Thêm lối tắt",
"addBindingTitle": "Thêm lối tắt",
"editBindingTitle": "Chỉnh sửa phím tắt",
"loading": "Đang tải...",
"noCustomBindings": "Chưa có phím tắt tùy chỉnh nào.",
"defaultBadge": "Mặc định",
"customizedBadge": "Tùy chỉnh",
"customize": "Tùy chỉnh",
"resetToDefault": "Khôi phục về mặc định",
"resetAllToDefaults": "Khôi phục tất cả về cài đặt mặc định",
"close": "Đóng",
"cancel": "Hủy bỏ",
"saveBinding": "Lưu lối tắt",
"saveError": "Không thể lưu các phím tắt",
"pressKeysToRecord": "Tổ hợp phím",
"pressKeysPlaceholder": "Nhấp chuột và nhấn phím",
"recording": "Nhấn các phím...",
"comboRequiredError": "Trước tiên, hãy nhấn tổ hợp phím.",
"textRequiredError": "Nhập văn bản cần gửi",
"controlCodeRequiredError": "Nhập một chữ cái duy nhất cho mã điều khiển.",
"snippetRequiredError": "Chọn một đoạn trích",
"conflictWarning": "Sự kết hợp này đã được liên kết với {{combo}}. Lưu lại sẽ khiến cả hai đều bốc cháy.",
"actionLabel": "Hoạt động",
"actionCopy": "Sao chép lựa chọn",
"actionPaste": "Dán",
"actionSendControlCode": "Gửi tín hiệu Ctrl+chữ cái",
"actionSendText": "Gửi tin nhắn",
"actionRunSnippet": "Chạy đoạn mã hiện có",
"actionNextTab": "Chuyển sang tab tiếp theo",
"actionPreviousTab": "Chuyển về tab trước",
"actionOpenCommandPalette": "Mở tìm kiếm nhanh",
"controlCodeLabel": "Thư",
"textLabel": "Văn bản để gửi",
"appendEnterLabel": "Nhấn Enter sau khi gửi",
"snippetLabel": "Đoạn trích",
"selectSnippetPlaceholder": "Chọn một đoạn trích",
"orphanedSnippetWarning": "Không tìm thấy đoạn mã.",
"clipboardPermissionNote": "Một số trình duyệt có thể yêu cầu quyền truy cập clipboard khi sử dụng lần đầu."
},
"connectionDefaults": {
"title": "Cài đặt mặc định kết nối",
"description": "Đặt các giá trị mà mọi máy chủ đều kế thừa trừ khi nó ghi đè lên các giá trị đó.",
"manage": "Quản lý",
"dialogDescription": "Các quy định này áp dụng cho các máy chủ không thiết lập bất kỳ cài đặt nào. Bất kỳ cài đặt nào được thiết lập trên máy chủ đều sẽ được ưu tiên.",
"tabTerminal": "Phần cuối",
"tabRemoteDesktop": "Máy tính từ xa",
"inherit": "Kế thừa",
"on": "TRÊN",
"off": "Tắt",
"resizeDisplayUpdate": "Cập nhật hiển thị",
"resizeReconnect": "Kết nối lại",
"clearAll": "Xóa tất cả",
"saved": "Cài đặt kết nối mặc định đã được lưu",
"saveFailed": "Không thể lưu cài đặt kết nối mặc định."
},
"userProfile": {
"donateTitle": "Duy trì Termix",
"donateDescription": "Termix là phần mềm miễn phí, tự lưu trữ, và được xây dựng bởi một vài người trong thời gian rảnh. Nếu nó giúp bạn tiết kiệm thời gian hoặc tiền bạc, một khoản quyên góp tiền mã hóa sẽ giúp duy trì dự án.",
"donateMilestones": "Các khoản quyên góp giúp tài trợ thời gian nghiên cứu và học hỏi để xây dựng hỗ trợ SAML, Kubernetes và Agent. Xem tiến độ và quyên góp.",
"donateButton": "Quyên góp tiền mã hóa",
"storageModeLocal": "Trình duyệt",
"storageModeCloud": "Cơ sở dữ liệu",
"storageModeDescription": "Trình duyệt chỉ lưu cài đặt trong trình duyệt này. Cơ sở dữ liệu đồng bộ với máy chủ và tải trên mọi thiết bị.",
"resetToDefaults": "Đặt lại mặc định",
"resetToDefaultsSuccess": "Đã đặt lại cài đặt về mặc định.",
"storageModeSwitch": "Lưu trữ tùy chọn",
"sectionAccount": "Tài khoản",
"desktopProfileTitle": "Hồ sơ máy tính để bàn cục bộ tự động",
"desktopProfileDescription": "Hồ sơ này chỉ dành cho hệ thống phụ trợ nhúng và đăng nhập tự động. Nó không có mật khẩu đăng nhập; Chức năng Đồng bộ từ xa bên dưới sử dụng một tài khoản máy chủ riêng biệt.",
"sectionInterface": "Giao diện",
"interfacePresetDesc": "Termix hiển thị rất nhiều chi tiết. Mọi tính năng đều được giữ nguyên.",
"preset_simple": "Đơn giản",
"preset_simple_desc": "Chỉ những thứ thiết yếu.",
"preset_balanced": "Cân bằng",
"preset_balanced_desc": "Bố cục tiêu chuẩn.",
"preset_advanced": "Trình độ cao",
"preset_advanced_desc": "Mọi thứ đều được bật, sắp xếp dày đặc.",
"presetClearOverrides": "Đặt lại tất cả",
"presetOverridesTitle": "Tùy chỉnh",
"presetRevertArea": "Hoàn tác",
"presetConfirmTitle": "Chuyển sang {{preset}}?",
"presetConfirmDesc": "Thao tác này sẽ đặt lại thanh bên, điều hướng, bố cục bảng điều khiển, thanh công cụ thiết bị đầu cuối và chế độ xem trình quản lý tập tin của bạn. Thông tin máy chủ, thông tin đăng nhập và trang chủ của bạn không bị thay đổi.",
"presetConfirmApply": "Áp dụng cài đặt sẵn",
"runSetupAgainDesc": "Hãy thực hiện lại các bước thiết lập ban đầu.",
"runSetupAgainButton": "Chạy thiết lập",
"uiArea_chrome": "Ứng dụng Chrome",
"uiArea_hostList": "Danh sách máy chủ",
"uiArea_credentialList": "Danh sách thông tin xác thực",
"uiArea_rail": "Điều hướng",
"uiArea_dashboard": "Bảng điều khiển",
"uiArea_terminal": "Phần cuối",
"uiArea_fileManager": "Trình quản lý tập tin",
"uiArea_docker": "Docker",
"uiArea_hostMetrics": "Số liệu máy chủ",
"uiArea_hostEditor": "Biên tập viên chủ trì",
"uiArea_homepage": "Trang chủ",
"sectionAppearance": "Giao diện",
"sectionSecurity": "Bảo mật",
"sectionApiKeys": "Khóa API",
"sectionData": "Dữ liệu",
"sectionC2sTunnels": "Đường hầm C2S",
"usernameLabel": "Tên người dùng",
"roleLabel": "Vai trò",
"roleAdministrator": "Quản trị viên",
"authMethodLabel": "Phương thức xác thực",
"authMethodLocal": "Cục bộ",
"twoFaLabel": "2FA",
"twoFaOn": "Bật",
"twoFaOff": "Tắt",
"versionLabel": "Phiên bản",
"betaProgramTitle": "Chương trình Beta",
"betaProgramDescription": "Dùng thử sớm các tính năng sắp ra mắt với thẻ Docker :beta cập nhật hàng tuần. Chưa ổn định, không dùng cho môi trường thực tế.",
"betaProgramFeedback": "Tìm thấy lỗi? Báo cáo tại đây.",
"betaProgramLearnMore": "Tìm hiểu thêm",
"cliTitle": "Công cụ dòng lệnh Termix",
"cliDescription": "Mở cửa sổ dòng lệnh, chạy các lệnh và di chuyển tập tin từ trình shell của riêng bạn.",
"cliLearnMore": "Tìm hiểu thêm",
"deleteAccount": "Xóa tài khoản",
"deleteAccountDescription": "Xóa vĩnh viễn tài khoản của bạn",
"changeServerDescription": "Chuyển sang máy chủ backend Termix khác",
"deleteButton": "Xóa",
"deleteAccountPermanent": "Hành động này là vĩnh viễn và không thể hoàn tác.",
"deleteAccountWarning": "Tất cả phiên, máy chủ, thông tin xác thực và cài đặt sẽ bị xóa vĩnh viễn.",
"confirmPasswordDeletePlaceholder": "Nhập mật khẩu để xác nhận",
"languageLabel": "Ngôn ngữ",
"themeLabel": "Giao diện",
"fontSizeLabel": "Cỡ chữ",
"interfaceFontLabel": "Phông chữ giao diện",
"interfaceFontDescription": "Thay đổi phông chữ giao diện ứng dụng. Các cấu hình thiết bị đầu cuối giữ nguyên cài đặt phông chữ riêng của chúng.",
"accentColorLabel": "Màu nhấn",
"settingsTerminal": "Terminal",
"commandAutocomplete": "Tự động hoàn thành lệnh",
"commandAutocompleteDesc": "Hiển thị tính năng tự động hoàn thành khi gõ nếu bạn nhấn phím Tab",
"localEcho": "Tiếng vọng địa phương",
"localEchoDesc": "Giảm độ trễ đầu vào cảm nhận được bằng cách sử dụng tính năng dự đoán thao tác gõ phím cục bộ an toàn.",
"keyboardShortcuts": "Phím tắt",
"keyboardShortcutsDescription": "Tùy chỉnh các phím tắt sao chép, dán và lệnh trong terminal.",
"manageShortcuts": "Quản lý",
"terminalLinkBehavior": "Hành vi khi nhấp liên kết trong Terminal",
"terminalLinkBehaviorDesc": "Hành vi mặc định khi nhấp vào liên kết trong terminal",
"historyTracking": "Theo dõi lịch sử",
"historyTrackingDesc": "Theo dõi các lệnh đã nhập",
"commandPalette": "Bảng lệnh",
"commandPaletteDesc": "Bật phím tắt",
"reopenTabsOnLogin": "Mở lại các tab khi đăng nhập",
"reopenTabsOnLoginDesc": "Khôi phục các tab đang mở khi đăng nhập hoặc tải lại trang, kể cả từ thiết bị khác",
"confirmTabClose": "Xác nhận đóng tab",
"confirmTabCloseDesc": "Hỏi trước khi đóng tab terminal",
"transferConcurrency": "Truyền tệp đồng thời",
"transferConcurrencyDesc": "Số lượng tệp mà trình quản lý cục bộ/từ xa song song tải lên hoặc tải xuống cùng lúc. Giảm giá trị này nếu máy chủ của bạn giới hạn số kênh SFTP.",
"settingsAppRail": "Đường ray ứng dụng",
"sidebarSettingsMoved": "Các cài đặt hiển thị thanh bên của máy chủ đã được chuyển sang bảng Tùy chỉnh thanh bên, được mở từ thanh công cụ Máy chủ.",
"showHostTags": "Hiển thị thẻ máy chủ",
"showHostTagsDesc": "Hiển thị thẻ trong danh sách máy chủ",
"hostTrayOnClick": "Nhấp để mở rộng hành động máy chủ",
"hostTrayOnClickDesc": "Luôn hiển thị nút kết nối; nhấp để mở rộng tùy chọn quản lý thay vì di chuột",
"compactHostView": "Chế độ xem máy chủ thu gọn",
"compactHostViewDesc": "Thu gọn mỗi máy chủ thành một dòng chỉ hiển thị tên và địa chỉ",
"statusColors": "Màu trạng thái thực",
"statusColorsDesc": "Dùng màu xanh/đỏ cho trạng thái trực tuyến/ngoại tuyến thay vì màu nhấn",
"pinAppRail": "Ghim thanh ứng dụng",
"pinAppRailDesc": "Giữ thanh ứng dụng bên trái luôn mở rộng thay vì chỉ mở khi di chuột",
"openFullscreenSettings": "Mở cài đặt ở chế độ toàn màn hình",
"exitFullscreenSettings": "Thoát khỏi chế độ toàn màn hình",
"expandAppRailOnHover": "Mở rộng thanh ứng dụng khi di chuột",
"expandAppRailOnHoverDesc": "Cho phép thanh ứng dụng bên trái mở rộng khi con trỏ di chuyển qua",
"showPinAppRailButton": "Hiển thị nút Pin App Rail",
"showPinAppRailButtonDesc": "Hiển thị nút ở thanh ứng dụng để ghim ứng dụng luôn mở. Mặc định là tắt.",
"settingsNavigation": "Điều hướng",
"navigationTabsDesc": "Chọn các tab sẽ hiển thị trên thanh bên",
"showSnippetCommands": "Hiển thị lệnh",
"showSnippetCommandsDesc": "Hiển thị lệnh của mỗi đoạn mã ngay bên dưới tên của nó. Tắt tùy chọn này để có danh sách gọn gàng hơn.",
"foldersCollapsed": "Thu gọn thư mục",
"foldersCollapsedDesc": "Mặc định thu gọn thư mục",
"confirmExecution": "Xác nhận thực thi",
"confirmExecutionDesc": "Xác nhận trước khi chạy đoạn mã",
"settingsUpdates": "Cập nhật",
"disableUpdateChecks": "Tắt kiểm tra cập nhật",
"disableUpdateChecksDesc": "Ngừng kiểm tra cập nhật",
"totpAuthenticator": "Trình xác thực TOTP",
"totpEnabled": "2FA đã được bật",
"totpDisabled": "Thêm bảo mật đăng nhập bổ sung",
"totpAddAuthenticator": "Thêm thiết bị",
"totpAddTitle": "Thêm thiết bị xác thực",
"totpAddDescription": "Xác nhận danh tính của bạn để đăng ký một thiết bị xác thực khác có cùng khóa TOTP bảo mật.",
"totpAddInputRequired": "Nhập mã TOTP hoặc mật khẩu của bạn",
"totpAddFailed": "Thêm trình xác thực không thành công",
"totpAddScanInstructions": "Quét mã QR này bằng thiết bị xác thực bổ sung. Các thiết bị xác thực hiện có vẫn sẽ hoạt động bình thường.",
"totpAddSuccess": "Đã đăng ký thêm trình xác thực.",
"disable": "Tắt",
"enable": "Bật",
"setupTotp": "Thiết lập TOTP",
"qrCode": "Mã QR",
"totpInstructions": "Quét mã QR hoặc nhập mã bí mật vào ứng dụng xác thực, sau đó nhập mã 6 chữ số",
"totpCodePlaceholder": "000000",
"verify": "Xác minh",
"changePassword": "Đổi mật khẩu",
"currentPasswordLabel": "Mật khẩu hiện tại",
"currentPasswordPlaceholder": "Mật khẩu hiện tại",
"newPasswordLabel": "Mật khẩu mới",
"newPasswordPlaceholder": "Mật khẩu mới",
"confirmPasswordLabel": "Xác nhận mật khẩu mới",
"confirmPasswordPlaceholder": "Xác nhận mật khẩu mới",
"updatePassword": "Cập nhật mật khẩu",
"createApiKeyTitle": "Tạo khóa API",
"createApiKeyDescription": "Tạo khóa API mới để truy cập lập trình.",
"apiKeyNameLabel": "Tên",
"apiKeyNamePlaceholder": "ví dụ: CI Pipeline",
"expiryDateLabel": "Ngày hết hạn",
"optional": "tùy chọn",
"cancel": "Hủy",
"createKey": "Tạo khóa",
"apiKeyCreatedWarning": "Mã khóa đã được tạo - hãy sao chép ngay, mã này sẽ không hiển thị lại nữa.",
"copyApiKey": "Sao chép khóa API",
"copiedToClipboard": "Đã sao chép vào clipboard",
"apiKeyCount": "{{count}} khóa",
"newKey": "Tạo khóa mới",
"noApiKeys": "Chưa có khóa API nào.",
"apiKeyActive": "Đang hoạt động",
"apiKeyUsageHint": "Thêm khóa của bạn vào",
"apiKeyUsageHintHeader": "tiêu đề.",
"apiKeyPermissionsHint": "Khóa kế thừa quyền của người dùng tạo.",
"exportData": "Xuất dữ liệu của tôi",
"exportDataDesc": "Tải xuống bản sao lưu máy chủ, thông tin đăng nhập và cài đặt của bạn để chuyển sang thiết bị khác.",
"export": "Xuất khẩu",
"exporting": "Đang xuất khẩu...",
"importData": "Nhập dữ liệu của tôi",
"importDataDesc": "Khôi phục máy chủ, thông tin đăng nhập và cài đặt của bạn từ tệp sao lưu .sqlite.",
"importDataSelected": "Đã chọn: {{name}}",
"selectFile": "Chọn tệp",
"changeFile": "Thay đổi",
"import": "Nhập khẩu",
"importing": "Đang nhập khẩu...",
"exportSuccess": "Dữ liệu đã được xuất thành công.",
"exportFailed": "Xuất dữ liệu thất bại",
"importSelectFile": "Vui lòng chọn tệp trước",
"importCompleted": "Quá trình nhập khẩu hoàn tất: {{total}} mục đã được nhập, {{skipped}} mục bị bỏ qua",
"importFailed": "Nhập khẩu thất bại: {{error}}",
"roleUser": "Người dùng",
"authMethodDual": "Xác thực kép",
"authMethodOidc": "OIDC",
"totpSetupFailed": "Không khởi động được cài đặt TOTP",
"totpEnter6Digits": "Nhập mã 6 chữ số",
"totpEnabledSuccess": "Đã bật xác thực hai yếu tố",
"totpInvalidCode": "Mã không hợp lệ, vui lòng thử lại",
"totpDisableInputRequired": "Nhập mã TOTP hoặc mật khẩu của bạn",
"totpDisabledSuccess": "Đã tắt xác thực hai yếu tố",
"totpDisableFailed": "Không tắt được 2FA",
"totpDisableTitle": "Tắt 2FA",
"totpDisablePlaceholder": "Nhập mã TOTP hoặc mật khẩu",
"totpDisableConfirm": "Tắt 2FA",
"totpContinueVerify": "Tiếp tục xác minh",
"totpVerifyTitle": "Xác minh mã",
"totpBackupTitle": "Mã dự phòng",
"totpDownloadBackup": "Tải mã dự phòng",
"passkeys": "Passkeys",
"passkeysDesc": "Sử dụng thông tin đăng nhập WebAuthn/FIDO2 để đăng nhập không cần mật khẩu",
"passkeyName": "Tên passkey",
"passkeyUvPreferred": "Ưu tiên",
"passkeyUvRequired": "Bắt buộc",
"passkeyUvDiscouraged": "Không khuyến khích",
"addPasskey": "Thêm Passkey",
"noPasskeys": "Chưa đăng ký passkey nào.",
"passkeyAdded": "Đã thêm Passkey",
"passkeyAddFailed": "Không thêm được Passkey",
"passkeyDeleted": "Đã xóa Passkey",
"passkeyDeleteFailed": "Xóa passkey thất bại",
"done": "Xong",
"secretCopied": "Đã sao chép mã bí mật vào clipboard",
"apiKeyNameRequired": "Tên khóa là bắt buộc",
"apiKeyCreated": "Đã tạo khóa API \"{{name}}\"",
"apiKeyCreateFailed": "Tạo khóa API thất bại",
"apiKeyUser": "Người dùng",
"apiKeyExpires": "Hết hạn",
"apiKeyRevoked": "Đã thu hồi khóa API \"{{name}}\"",
"apiKeyRevokeFailed": "Thu hồi khóa API thất bại",
"passwordFieldsRequired": "Cần nhập mật khẩu hiện tại và mật khẩu mới",
"passwordMismatch": "Mật khẩu không khớp",
"passwordTooShort": "Mật khẩu phải có ít nhất 6 ký tự",
"passwordUpdated": "Cập nhật mật khẩu thành công",
"passwordUpdateFailed": "Cập nhật mật khẩu thất bại",
"deletePasswordRequired": "Cần mật khẩu để xóa tài khoản",
"deleteFailed": "Xóa tài khoản thất bại",
"deleting": "Đang xóa...",
"colorPickerTooltip": "Mở bảng chọn màu",
"themeSystem": "Hệ thống",
"themeLight": "Sáng",
"themeDark": "Tối",
"themeDracula": "Dracula",
"themeCatppuccin": "Catppuccin",
"themeNord": "Nord",
"themeSolarized": "Solarized",
"themeTokyoNight": "Tokyo Night",
"themeOneDark": "One Dark",
"themeGruvbox": "Gruvbox"
}
}
},
"terminalToolbar": {
"title": "Thanh công cụ thiết bị đầu cuối",
"showActions": "Hiển thị thanh công cụ",
"hideToolbar": "Ẩn thanh công cụ",
"showToolbar": "Mở rộng thanh công cụ",
"moveToolbar": "Di chuyển thanh công cụ",
"moveToolbarHint": "Kéo để định vị lại thanh công cụ",
"layout": "Chế độ hiển thị thanh công cụ",
"layoutIcon": "Chỉ có biểu tượng",
"layoutLabeled": "Biểu tượng và nhãn",
"layoutExpanded": "Đã mở rộng với các số liệu",
"image": "Thao tác với hình ảnh (chỉ áp dụng cho hình ảnh)",
"upload": "Tải ảnh lên",
"paste": "Dán hình ảnh",
"detachTmux": "Tách tmux",
"detachTmuxDescription": "Tách phiên tmux",
"imageActionFailed": "Thao tác xử lý hình ảnh thất bại",
"retry": "Thử lại",
"dismissError": "Bỏ qua lỗi hình ảnh",
"cpu": "CPU",
"memory": "Ký ức",
"disk": "Đĩa",
"statsUnavailable": "Số liệu thống kê trực tiếp không khả dụng",
"tmuxDetach": "Tách phiên tmux",
"uploadImage": "Tải ảnh lên máy chủ",
"uploadingImage": "Đang tải lên...",
"pasteImage": "Dán hình ảnh từ clipboard (chỉ áp dụng cho hình ảnh)",
"openFiles": "Đang mở tệp",
"openDocker": "Mở Docker",
"openTunnel": "Đường hầm mở",
"openHostMetrics": "Số liệu máy chủ mở",
"openProxmoxStats": "Mở thống kê Proxmox",
"openTmuxMonitor": "Mở Tmux Monitor"
},
"tmuxMonitor": {
"title": "Giám sát Tmux",
"failedToLoadHosts": "Tải danh sách máy chủ thất bại",
"failedToLoad": "Tải phiên tmux thất bại",
"tmuxUnavailable": "tmux chưa được cài đặt trên máy chủ này",
"noSessions": "Không có phiên tmux nào trên máy chủ này",
"noHostSelected": "Chưa chọn máy chủ",
"attached": "Đã đính kèm",
"detached": "Đã tách rời",
"attach": "Đính kèm",
"editTags": "Sửa nhãn",
"tagsHint": "Nhãn phân cách bằng dấu phẩy (ví dụ: YOLO, lab, training)",
"tagsSaved": "Nhãn đã lưu",
"tagsSaveFailed": "Lưu nhãn thất bại",
"searchPlaceholder": "Tìm kiếm đầu ra qua các phiên...",
"searchResults": "{{count}} kết quả khớp",
"searchFailed": "Tìm kiếm thất bại",
"selectPaneHint": "Chọn một pane để xem trước đầu ra",
"closePreview": "Đóng xem trước",
"newSession": "Phiên mới",
"newSessionHint": "Tên phiên (chữ cái, chữ số, _ @ % + = -)",
"newSessionPlaceholder": "my-session",
"create": "Tạo",
"sessionCreated": "Đã tạo phiên \"{{name}}\"",
"sessionCreateFailed": "Tạo phiên thất bại",
"splitRight": "Chia sang phải",
"splitDown": "Chia xuống dưới",
"splitFailed": "Chia pane thất bại",
"newWindow": "Cửa sổ mới",
"windowCreateFailed": "Tạo cửa sổ thất bại",
"attachSessionTooltip": "Đính kèm vào {{session}}",
"refresh": "Làm mới",
"refreshFailed": "Làm mới phiên thất bại",
"collapseAll": "Thu gọn tất cả",
"expandAll": "Mở rộng tất cả",
"moreActions": "Thao tác khác",
"sessionStats": "Thống kê phiên",
"renameSessionTitle": "Đổi tên phiên \"{{name}}\"",
"rename": "Đổi tên",
"sessionRenamed": "Đã đổi tên phiên thành \"{{name}}\"",
"sessionRenameFailed": "Đổi tên phiên thất bại",
"editTagsTitle": "Sửa nhãn cho \"{{name}}\"",
"killPane": "Hủy pane",
"resizeTree": "Kéo để thay đổi kích thước — nhấn đúp để đặt lại",
"reattach": "Gắn lại (sửa hiển thị bị rối)",
"killWindow": "Hủy cửa sổ",
"killWindowTitle": "Hủy cửa sổ {{index}} của \"{{session}}\"?",
"killWindowBody": "Mọi pane và tiến trình trong cửa sổ này sẽ bị kết thúc. Hủy cửa sổ cuối cùng sẽ kết thúc phiên.",
"windowKillFailed": "Không thể hủy cửa sổ",
"statusActivity": "Hoạt động",
"statusWindows": "Cửa sổ",
"statusPanes": "Pane",
"statusTags": "Thẻ",
"killPaneTitle": "Hủy pane {{id}}?",
"killPaneBody": "Tiến trình đang chạy trong pane này sẽ bị kết thúc. Hủy pane cuối cùng sẽ đóng cửa sổ của nó.",
"paneKillFailed": "Không thể hủy pane",
"killSessionTitle": "Hủy phiên \"{{name}}\"?",
"killSessionBody": "Tất cả cửa sổ và tiến trình đang chạy trong phiên này sẽ bị kết thúc. Hành động này không thể hoàn tác.",
"kill": "Hủy",
"sessionKilled": "Phiên \"{{name}}\" đã bị hủy",
"sessionKillFailed": "Không thể hủy phiên",
"hostUnreachable": "Không thể kết nối đến máy chủ. Kiểm tra xem máy chủ có trực tuyến và có thể truy cập được không.",
"noServer": "Không có máy chủ tmux nào đang chạy trên máy chủ này.",
"searchTruncated": "Kết quả bị cắt bớt — tìm kiếm bao gồm {{lines}} dòng cuối của mỗi pane và tối đa {{panes}} pane.",
"closeSearchResults": "Đóng kết quả tìm kiếm",
"retry": "Thử lại",
"noHosts": "Không có máy chủ SSH nào",
"noHostsHint": "Bật tùy chọn Tmux Monitor trên máy chủ SSH (Host Manager → tab Terminal) để giám sát phiên tmux của nó.",
"tmuxInstallHint": "Cài đặt nó trên máy chủ bằng lệnh:",
"attachTooltip": "Mở terminal đến {{host}}",
"attachTooltipPane": "Mở terminal đến {{host}} — phiên tmux {{session}}",
"timeJustNow": "vừa xong",
"timeMinutes": "{{count}} phút trước",
"timeHours": "{{count}} giờ trước",
"timeDays": "{{count}} ngày trước"
},
"mobileKeyboard": {
"shift": "Shift",
"ctrl": "Ctrl",
"esc": "Esc",
"tab": "Tab",
"backTab": "⇥",
"arrowUp": "Mũi tên lên",
"arrowDown": "Mũi tên xuống",
"arrowLeft": "Mũi tên trái",
"arrowRight": "Mũi tên phải",
"home": "Home",
"end": "End",
"pageUp": "PgUp",
"pageDown": "PgDn",
"delete": "Del",
"paste": "Dán",
"editQuickKeys": "Chỉnh sửa phím tắt",
"quickKeysTitle": "Phím tắt",
"quickKeysDesc": "Nhấn × để xóa. Hỗ trợ tối đa 8 ký tự.",
"quickKeyPlaceholder": "vd: sudo ",
"addQuickKey": "Thêm",
"removeQuickKey": "Xóa",
"resetDefaults": "Đặt lại mặc định",
"done": "Xong"
},
"serial": {
"title": "Cổng nối tiếp",
"portLabel": "Cổng",
"portPlaceholder": "/dev/ttyUSB0 or COM3",
"baudRateLabel": "Tốc độ Baud",
"dataBitsLabel": "Dữ liệu",
"stopBitsLabel": "Bit dừng",
"parityLabel": "Kiểm tra chẵn lẻ",
"parityNone": "Không",
"parityEven": "Chẵn",
"parityOdd": "Lẻ",
"connect": "Kết nối cổng nối tiếp",
"disconnect": "Ngắt kết nối",
"refreshPorts": "Làm mới cổng",
"connected": "Đã kết nối tới {{path}} với tốc độ {{baud}} baud",
"disconnected": "Đã ngắt kết nối cổng nối tiếp",
"connectionError": "Không thể mở cổng nối tiếp",
"wsError": "Lỗi WebSocket",
"errorNoServerUrl": "Chưa cấu hình URL máy chủ",
"notSupportedTitle": "Không hỗ trợ Serial",
"notSupported": "Kết nối nối tiếp yêu cầu trình duyệt hỗ trợ Web Serial API (Chrome, Edge, hoặc Firefox 151+), hoặc ứng dụng Termix desktop.",
"hideHint": "Bạn có thể ẩn tab Serial trong Hồ sơ người dùng > Giao diện > Thanh bên > Điều hướng.",
"browserPickerHint": "Nhấn Kết nối và trình duyệt sẽ mở bộ chọn cổng để chọn thiết bị."
},
"metricsHistory": {
"title": "Lịch sử chỉ số",
"historySuffix": "Lịch sử",
"cpuMemoryDisk": "CPU / Bộ nhớ / Ổ đĩa",
"network": "Mạng",
"download": "RX",
"upload": "TX",
"noData": "Không có dữ liệu lịch sử cho khoảng thời gian này.",
"custom": "Tùy chỉnh",
"to": "đến",
"apply": "Áp dụng",
"viewHistory": "Xem lịch sử"
},
"alerts": {
"tabFirings": "Cảnh báo",
"tabRules": "Quy tắc",
"tabChannels": "Kênh",
"noFirings": "Không có cảnh báo chưa xác nhận",
"noRules": "Chưa cấu hình quy tắc cảnh báo",
"noChannels": "Chưa cấu hình kênh thông báo",
"rulesDesc": "Quy tắc cảnh báo kích hoạt thông báo",
"channelsDesc": "Nơi gửi thông báo cảnh báo",
"acknowledge": "Xác nhận",
"ackAll": "Xác nhận tất cả",
"allAcknowledged": "Tất cả cảnh báo đã được xác nhận",
"ackFailed": "Không thể xác nhận cảnh báo",
"ackAllFailed": "Không thể xác nhận tất cả cảnh báo",
"showAcknowledged": "Hiện tất cả",
"hideAcknowledged": "Ẩn đã xác nhận",
"addChannel": "Thêm kênh",
"editChannel": "Sửa kênh",
"channelName": "Tên",
"channelType": "Loại",
"channelNameRequired": "Tên là bắt buộc",
"webhookUrl": "URL",
"webhookUrlRequired": "Webhook URL là bắt buộc",
"webhookDesc": "Gửi tải trọng JSON qua POST đến URL này mỗi khi cảnh báo kích hoạt",
"ntfyServer": "URL máy chủ",
"ntfyTopic": "Chủ đề",
"ntfyTopicRequired": "Chủ đề là bắt buộc",
"ntfyToken": "Mã truy cập (tùy chọn)",
"channelSaveFailed": "Lỗi khi lưu kênh",
"test": "Kiểm tra",
"testSent": "Đã gửi thông báo kiểm tra",
"testFailed": "Gửi thông báo kiểm tra thất bại",
"testFailedWithReason": "Thông báo kiểm tra thất bại: {{reason}}",
"addRule": "Thêm quy tắc cảnh báo",
"editRule": "Sửa quy tắc cảnh báo",
"ruleName": "Tên quy tắc",
"ruleNameRequired": "Tên là bắt buộc",
"triggerType": "Kích hoạt",
"thresholdValue": "Ngưỡng (%)",
"durationSeconds": "Thời gian (giây, 0 = kích hoạt ngay)",
"cooldownMinutes": "Thời gian chờ (phút)",
"channels": "Kênh thông báo",
"noChannelsHint": "Vui lòng thêm kênh trong tab Kênh trước",
"ruleSaveFailed": "Lỗi khi lưu quy tắc"
},
"ai": {
"title": "Trợ lý",
"send": "Gửi",
"stop": "Dừng lại",
"save": "Cứu",
"cancel": "Hủy bỏ",
"running": "đang chạy",
"approve": "Chấp thuận",
"reject": "Từ chối",
"inputPlaceholder": "Hãy hỏi về máy chủ của bạn, hoặc mô tả một thay đổi mà bạn muốn đề xuất.",
"selectProvider": "Chọn nhà cung cấp",
"providerSettings": "Cài đặt nhà cung cấp",
"addProvider": "Thêm nhà cung cấp",
"editProvider": "Chỉnh sửa nhà cung cấp",
"removeProvider": "Xóa nhà cung cấp",
"providerType": "Nhà cung cấp",
"providerLabel": "Tên",
"providerLabelPlaceholder": "Ví dụ: Ollama địa phương",
"baseUrl": "Địa chỉ máy chủ",
"apiKey": "Khóa API",
"defaultModel": "Mô hình mặc định",
"defaultModelPlaceholder": "Ví dụ: llama3.1 hoặc claude-opus-5",
"labelRequired": "Đặt tên cho nhà cung cấp này",
"providerSaveFailed": "Không thể lưu nhà cung cấp",
"providerUpdated": "Nhà cung cấp đã cập nhật",
"providerDeleteFailed": "Không thể xóa nhà cung cấp",
"privateEndpointHint": "Các địa chỉ trên mạng riêng của bạn cần được quản trị viên cho phép truy cập trước.",
"providerOllama": "Ollama",
"providerAnthropic": "Nhân loại",
"providerOpenai": "OpenAI",
"providerGemini": "Google Gemini",
"providerOpenaiCompatible": "Tương thích với OpenAI",
"toolArguments": "Đầu vào",
"toolResult": "Kết quả",
"statusApplied": "Đã áp dụng",
"statusRejected": "Vật bị loại bỏ",
"proposalApplied": "Thay đổi đã được áp dụng",
"proposalApplyFailed": "Không thể áp dụng thay đổi",
"proposalRejectFailed": "Không thể từ chối thay đổi",
"enableTitle": "Kích hoạt trợ lý AI",
"enableDescription": "Hãy để trợ lý đọc cấu hình của bạn và đề xuất các thay đổi để bạn phê duyệt.",
"readOnlyCommands": "Cho phép các lệnh chẩn đoán chỉ đọc",
"readOnlyCommandsDescription": "Trợ lý có thể chạy một danh sách ngắn các lệnh an toàn như df và uptime mà không cần hỏi mỗi lần. Bất kỳ lệnh nào thay đổi máy chủ đều được đề xuất trước tiên.",
"modelDetectFailed": "Không thể liên lạc được với nhà cung cấp, vì vậy đây là danh sách chung. Bạn có thể nhập bất kỳ tên mẫu nào.",
"modelCustom": "Nhập tên mẫu",
"modelRefresh": "Làm mới danh sách",
"modelPlaceholder": "Chọn hoặc nhập mô hình",
"attachHint": "Nhập @ để tham chiếu đến máy chủ, đoạn mã hoặc quy trình tự động hóa. Các thay đổi được đề xuất để bạn phê duyệt.",
"runCommandTitle": "Chạy lệnh",
"assistant": "Trợ lý AI",
"terminalPanelEmpty": "Hãy hỏi trợ lý về máy chủ này. Bất cứ thay đổi nào về trạng thái đều cần sự chấp thuận của bạn trước.",
"terminalPanelPlaceholder": "Hãy hỏi về chủ nhà này...",
"noProvidersConfigured": "Chưa có nhà cung cấp AI nào được cấu hình. Hãy thêm một nhà cung cấp trong tab trợ lý AI.",
"runsInOpenTerminal": "Chương trình này chạy trong cửa sổ dòng lệnh đang mở của bạn.",
"runInTerminal": "Chạy"
},
"macros": {
"title": "Macro",
"description": "Chạy một chuỗi lệnh đã lưu trong cửa sổ dòng lệnh và phản hồi lại những gì máy chủ gửi về.",
"target": "Mục tiêu",
"noTerminal": "Không có thiết bị đầu cuối nào đang mở",
"empty": "Chưa có macro nào.",
"emptyHint": "Tạo macro để tự động hóa quy trình trên thiết bị đầu cuối, chẳng hạn như đăng nhập, khởi động lại dịch vụ hoặc trả lời các lời nhắc.",
"create": "Macro mới",
"back": "Quay lại phần macro",
"name": "Tên",
"namePlaceholder": "Khởi động lại máy chủ web",
"nameRequired": "Đặt tên cho macro trước khi lưu.",
"descriptionLabel": "Sự miêu tả",
"descriptionPlaceholder": "Chức năng của macro này (tùy chọn)",
"unsaved": "Thay đổi chưa được lưu",
"save": "Cứu",
"saved": "Macro đã được lưu",
"saveFailed": "Không thể lưu macro",
"delete": "Xóa bỏ",
"deleteTitle": "Xóa macro này?",
"deleteBody": "\"{{name}}\" sẽ bị xóa vĩnh viễn. Không thể hoàn tác.",
"deleted": "Macro đã bị xóa",
"cancel": "Hủy bỏ",
"run": "Chạy",
"stop": "Dừng lại",
"running": "Đang chạy...",
"completed": "Macro đã hoàn thành",
"failed": "Macro bị lỗi",
"loadFailed": "Không thể tải macro",
"needTerminal": "Trước tiên hãy mở và kết nối thiết bị đầu cuối.",
"noSteps": "Macro này chưa có bước nào. Hãy thêm một bước bên dưới.",
"addStep": "Thêm bước",
"stepNumber": "Bước {{number}}",
"removeStep": "Xóa bước",
"confirmRunTitle": "Chạy macro này?",
"confirmRunBody": "\"{{name}}\" sẽ gửi lệnh đến {{host}}.",
"confirmRunAction": "Chạy macro",
"stepTypes": {
"send": {
"label": "Gửi lệnh",
"help": "Nhập văn bản vào cửa sổ dòng lệnh, giống như khi bạn tự nhập văn bản."
},
"wait": {
"label": "Chờ kết quả đầu ra",
"help": "Tạm dừng cho đến khi máy chủ in ra đoạn văn bản bạn đã đặt tên, ví dụ như lời nhắc nhập mật khẩu."
},
"delay": {
"label": "Tạm dừng",
"help": "Chờ một khoảng thời gian cố định trước khi thực hiện bước tiếp theo."
},
"if": {
"label": "Nếu đầu ra chứa",
"help": "Kiểm tra tất cả những gì máy chủ đã in ra cho đến nay, sau đó chạy một trong hai nhánh."
},
"repeat": {
"label": "Lặp lại",
"help": "Thực thi các bước bên trong nó một số lần nhất định."
}
},
"send": {
"text": "Lệnh hoặc văn bản",
"textPlaceholder": "systemctl restart nginx",
"pressEnter": "Nhấn Enter sau khi gửi",
"pressEnterHelp": "Tắt tùy chọn này để nhập văn bản mà không cần gửi đi."
},
"wait": {
"pattern": "Chờ cho đến khi đầu ra chứa",
"patternPlaceholder": "mật khẩu:",
"timeout": "Bỏ cuộc sau",
"onTimeout": "Nếu nó không bao giờ xuất hiện",
"stop": "Dừng macro",
"continue": "Cứ tiếp tục đi"
},
"delay": {
"duration": "Chờ đợi"
},
"ifStep": {
"pattern": "Nếu đầu ra chứa",
"patternPlaceholder": "Đang hoạt động: đang hoạt động (đang chạy)",
"then": "Sau đó hãy làm như thế này",
"else": "Nếu không thì hãy làm như thế này",
"emptyBranch": "Không có bước nào"
},
"repeat": {
"count": "Số lần",
"times": "lần"
},
"match": {
"useRegex": "So khớp với biểu thức chính quy",
"useRegexHelp": "Bỏ phần này đi để văn bản khớp chính xác với nội dung đã viết.",
"invalidRegex": "Đây không phải là biểu thức chính quy hợp lệ, nó sẽ được so khớp như văn bản thuần túy."
},
"seconds": "giây",
"secondsShort": "{{count}}s"
},
"webEndpoint": {
"noHostSelected": "Chưa chọn máy chủ nào",
"notFound": "Điểm cuối này không còn tồn tại nữa.",
"tunnelUnreachableFromBrowser": "Điểm cuối này tạo đường hầm đến 127.0.0.1 trên máy đang chạy Termix, mà trình duyệt của bạn không thể truy cập được. Hãy đặt Bind Host của điểm cuối thành một địa chỉ mà máy đó phản hồi, chẳng hạn như 0.0.0.0, và gán cho nó một Cổng cục bộ cố định.",
"tunnelSharesSessionCookie": "Việc mở đường hầm này sẽ chuyển phiên Termix của bạn đến dịch vụ được tạo đường hầm, vì trình duyệt của bạn sẽ truy cập dịch vụ đó bằng cùng tên máy chủ mà Termix được phục vụ. Cookie bỏ qua cổng, vì vậy không thể phân biệt được hai dịch vụ này. Hãy sử dụng ứng dụng Termix dành cho máy tính để bàn hoặc mở Termix tại localhost.",
"directSharesSessionCookie": "Việc mở điểm cuối này sẽ gửi phiên Termix của bạn đến đó, vì trình duyệt của bạn truy cập nó từ cùng một trang web mà Termix được cung cấp. Cookie bỏ qua cổng, vì vậy một cổng khác không có nghĩa là một danh tính khác. Hãy sử dụng ứng dụng Termix dành cho máy tính để bàn, hoặc cung cấp giao diện người dùng web này từ một tên máy chủ khác.",
"retry": "Thử lại",
"reload": "Tải lại",
"copyUrl": "Sao chép URL",
"urlCopied": "URL đã được sao chép",
"copyFailed": "Không thể sao chép URL",
"openExternally": "Mở từ bên ngoài",
"isolationUnavailable": "Trình duyệt này không thể tách biệt các điểm cuối web khỏi phiên Termix của bạn. Hãy sử dụng trình duyệt hỗ trợ iframe không cần thông tin đăng nhập.",
"isolationNotice": "Các trang nhúng sử dụng một phiên riêng biệt. Đối với các trang yêu cầu lưu trữ hoặc đăng nhập bằng cửa sổ bật lên, hãy sử dụng một cửa sổ riêng biệt trong ứng dụng dành cho máy tính để bàn.",
"openIsolatedWindow": "Cửa sổ riêng biệt đang mở"
}
}