release-2.6.0 (#1085)

* fix: general bug fixes

* fix: general qol additions

* ci(deps): bump actions/setup-node in the github-actions group (#1068)

Bumps the github-actions group with 1 update: [actions/setup-node](https://github.com/actions/setup-node).


Updates `actions/setup-node` from 6 to 7
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

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 28 updates (#1069)

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

| Package | From | To |
| --- | --- | --- |
| [@biomejs/biome](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome) | `2.5.2` | `2.5.4` |
| [@codemirror/view](https://github.com/codemirror/view) | `6.43.5` | `6.43.6` |
| [@radix-ui/react-accordion](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/accordion) | `1.2.15` | `1.2.17` |
| [@radix-ui/react-alert-dialog](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/alert-dialog) | `1.1.18` | `1.1.20` |
| [@radix-ui/react-checkbox](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/checkbox) | `1.3.6` | `1.3.8` |
| [@radix-ui/react-dialog](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/dialog) | `1.1.18` | `1.1.20` |
| [@radix-ui/react-dropdown-menu](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/dropdown-menu) | `2.1.19` | `2.1.21` |
| [@radix-ui/react-label](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/label) | `2.1.11` | `2.1.12` |
| [@radix-ui/react-popover](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/popover) | `1.1.18` | `1.1.20` |
| [@radix-ui/react-progress](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/progress) | `1.1.11` | `1.1.13` |
| [@radix-ui/react-scroll-area](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/scroll-area) | `1.2.13` | `1.2.15` |
| [@radix-ui/react-select](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/select) | `2.3.2` | `2.3.4` |
| [@radix-ui/react-separator](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/separator) | `1.1.11` | `1.1.12` |
| [@radix-ui/react-slider](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/slider) | `1.4.2` | `1.4.4` |
| [@radix-ui/react-switch](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/switch) | `1.3.2` | `1.3.4` |
| [@radix-ui/react-tabs](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/tabs) | `1.1.16` | `1.1.18` |
| [@radix-ui/react-tooltip](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/tooltip) | `1.2.11` | `1.2.13` |
| [@tailwindcss/vite](https://github.com/tailwindlabs/tailwindcss/tree/HEAD/packages/@tailwindcss-vite) | `4.3.2` | `4.3.3` |
| [@uiw/codemirror-extensions-langs](https://github.com/uiwjs/react-codemirror) | `4.25.10` | `4.25.11` |
| [@uiw/codemirror-theme-github](https://github.com/uiwjs/react-codemirror) | `4.25.10` | `4.25.11` |
| [@uiw/react-codemirror](https://github.com/uiwjs/react-codemirror) | `4.25.10` | `4.25.11` |
| [@vitest/coverage-v8](https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-v8) | `4.1.9` | `4.1.10` |
| [@vitest/ui](https://github.com/vitest-dev/vitest/tree/HEAD/packages/ui) | `4.1.9` | `4.1.10` |
| [i18next](https://github.com/i18next/i18next) | `26.3.4` | `26.3.6` |
| [radix-ui](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/radix-ui) | `1.6.1` | `1.6.3` |
| [react-i18next](https://github.com/i18next/react-i18next) | `17.0.8` | `17.0.10` |
| [tailwindcss](https://github.com/tailwindlabs/tailwindcss/tree/HEAD/packages/tailwindcss) | `4.3.2` | `4.3.3` |
| [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest) | `4.1.9` | `4.1.10` |


Updates `@biomejs/biome` from 2.5.2 to 2.5.4
- [Release notes](https://github.com/biomejs/biome/releases)
- [Changelog](https://github.com/biomejs/biome/blob/main/packages/@biomejs/biome/CHANGELOG.md)
- [Commits](https://github.com/biomejs/biome/commits/@biomejs/biome@2.5.4/packages/@biomejs/biome)

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

Updates `@radix-ui/react-accordion` from 1.2.15 to 1.2.17
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/accordion/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/accordion)

Updates `@radix-ui/react-alert-dialog` from 1.1.18 to 1.1.20
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/alert-dialog/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/alert-dialog)

Updates `@radix-ui/react-checkbox` from 1.3.6 to 1.3.8
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/checkbox/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/checkbox)

Updates `@radix-ui/react-dialog` from 1.1.18 to 1.1.20
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/dialog/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/dialog)

Updates `@radix-ui/react-dropdown-menu` from 2.1.19 to 2.1.21
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/dropdown-menu/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/dropdown-menu)

Updates `@radix-ui/react-label` from 2.1.11 to 2.1.12
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/label/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/label)

Updates `@radix-ui/react-popover` from 1.1.18 to 1.1.20
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/popover/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/popover)

Updates `@radix-ui/react-progress` from 1.1.11 to 1.1.13
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/progress/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/progress)

Updates `@radix-ui/react-scroll-area` from 1.2.13 to 1.2.15
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/scroll-area/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/scroll-area)

Updates `@radix-ui/react-select` from 2.3.2 to 2.3.4
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/select/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/select)

Updates `@radix-ui/react-separator` from 1.1.11 to 1.1.12
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/separator/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/separator)

Updates `@radix-ui/react-slider` from 1.4.2 to 1.4.4
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/slider/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/slider)

Updates `@radix-ui/react-switch` from 1.3.2 to 1.3.4
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/switch/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/switch)

Updates `@radix-ui/react-tabs` from 1.1.16 to 1.1.18
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/tabs/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/tabs)

Updates `@radix-ui/react-tooltip` from 1.2.11 to 1.2.13
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/tooltip/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/tooltip)

Updates `@tailwindcss/vite` from 4.3.2 to 4.3.3
- [Release notes](https://github.com/tailwindlabs/tailwindcss/releases)
- [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/tailwindcss/commits/v4.3.3/packages/@tailwindcss-vite)

Updates `@uiw/codemirror-extensions-langs` from 4.25.10 to 4.25.11
- [Release notes](https://github.com/uiwjs/react-codemirror/releases)
- [Commits](https://github.com/uiwjs/react-codemirror/compare/v4.25.10...v4.25.11)

Updates `@uiw/codemirror-theme-github` from 4.25.10 to 4.25.11
- [Release notes](https://github.com/uiwjs/react-codemirror/releases)
- [Commits](https://github.com/uiwjs/react-codemirror/compare/v4.25.10...v4.25.11)

Updates `@uiw/react-codemirror` from 4.25.10 to 4.25.11
- [Release notes](https://github.com/uiwjs/react-codemirror/releases)
- [Commits](https://github.com/uiwjs/react-codemirror/compare/v4.25.10...v4.25.11)

Updates `@vitest/coverage-v8` from 4.1.9 to 4.1.10
- [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.10/packages/coverage-v8)

Updates `@vitest/ui` from 4.1.9 to 4.1.10
- [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.10/packages/ui)

Updates `i18next` from 26.3.4 to 26.3.6
- [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.4...v26.3.6)

Updates `radix-ui` from 1.6.1 to 1.6.3
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/radix-ui/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/radix-ui)

Updates `react-i18next` from 17.0.8 to 17.0.10
- [Changelog](https://github.com/i18next/react-i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/react-i18next/compare/v17.0.8...v17.0.10)

Updates `tailwindcss` from 4.3.2 to 4.3.3
- [Release notes](https://github.com/tailwindlabs/tailwindcss/releases)
- [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/tailwindcss/commits/v4.3.3/packages/tailwindcss)

Updates `vitest` from 4.1.9 to 4.1.10
- [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.10/packages/vitest)

---
updated-dependencies:
- dependency-name: "@biomejs/biome"
  dependency-version: 2.5.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: "@codemirror/view"
  dependency-version: 6.43.6
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: "@radix-ui/react-accordion"
  dependency-version: 1.2.17
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: "@radix-ui/react-alert-dialog"
  dependency-version: 1.1.20
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: "@radix-ui/react-checkbox"
  dependency-version: 1.3.8
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: "@radix-ui/react-dialog"
  dependency-version: 1.1.20
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: "@radix-ui/react-dropdown-menu"
  dependency-version: 2.1.21
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: "@radix-ui/react-label"
  dependency-version: 2.1.12
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: "@radix-ui/react-popover"
  dependency-version: 1.1.20
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: "@radix-ui/react-progress"
  dependency-version: 1.1.13
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: "@radix-ui/react-scroll-area"
  dependency-version: 1.2.15
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: "@radix-ui/react-select"
  dependency-version: 2.3.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: "@radix-ui/react-separator"
  dependency-version: 1.1.12
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: "@radix-ui/react-slider"
  dependency-version: 1.4.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: "@radix-ui/react-switch"
  dependency-version: 1.3.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: "@radix-ui/react-tabs"
  dependency-version: 1.1.18
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: "@radix-ui/react-tooltip"
  dependency-version: 1.2.13
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: "@tailwindcss/vite"
  dependency-version: 4.3.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: "@uiw/codemirror-extensions-langs"
  dependency-version: 4.25.11
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: "@uiw/codemirror-theme-github"
  dependency-version: 4.25.11
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: "@uiw/react-codemirror"
  dependency-version: 4.25.11
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: "@vitest/coverage-v8"
  dependency-version: 4.1.10
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: "@vitest/ui"
  dependency-version: 4.1.10
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: i18next
  dependency-version: 26.3.6
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: radix-ui
  dependency-version: 1.6.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: react-i18next
  dependency-version: 17.0.10
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: tailwindcss
  dependency-version: 4.3.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: vitest
  dependency-version: 4.1.10
  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 ws in the prod-patch-updates group (#1071)

Bumps the prod-patch-updates group with 1 update: [ws](https://github.com/websockets/ws).


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

---
updated-dependencies:
- dependency-name: ws
  dependency-version: 8.21.1
  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 the major-updates group with 2 updates (#1072)

Bumps the major-updates group with 2 updates: [nanoid](https://github.com/ai/nanoid) and [typescript](https://github.com/microsoft/TypeScript).


Updates `nanoid` from 5.1.16 to 6.0.0
- [Release notes](https://github.com/ai/nanoid/releases)
- [Changelog](https://github.com/ai/nanoid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ai/nanoid/compare/5.1.16...6.0.0)

Updates `typescript` from 6.0.3 to 7.0.2
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Commits](https://github.com/microsoft/TypeScript/commits)

---
updated-dependencies:
- dependency-name: nanoid
  dependency-version: 6.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: major-updates
- dependency-name: typescript
  dependency-version: 7.0.2
  dependency-type: direct:development
  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>

* fix: general qol additions and new analytics/telemetrics feature

* fix: incorrect version sent to posthog

* feat: add multiplayer/shared sessions for terminal and guacd

* feat: rework Electron desktop app to run standalone-first with optional two-way sync to a remote Termix server

* Fix Guacamole tab visibility lifecycle (#1074)

Co-authored-by: default-student <default-student@github.com>
Co-authored-by: Luke Gustafson <88517757+LukeGus@users.noreply.github.com>

* fix(alerts): send channel config as object payload instead of JSON string (#1075)

* fix tmux-monitor tailscale issue (#1076)

* Initial plan

* fix(tmux-monitor): explicitly handle tailscale auth in PanePreview hostConfig

For Tailscale-auth hosts the pane-preview attach path was building the
Terminal hostConfig with only the generic spread of host fields.  This
could omit or mismap auth-critical details and trigger a plain TCP/SSH
reachability path that doesn't work with Tailscale-only SSH endpoints.

The fix branches on `host.authType === "tailscale"` and:
- Carries `authType: "tailscale"` explicitly so the backend always selects
  the Tailscale-aware PTY path regardless of how the host object evolves.
- Derives `port` from `host.sshPort ?? host.port` so Tailscale SSH
  endpoints on a non-default SSH port are reached correctly.
- Leaves all non-tailscale auth types on the unchanged code path.

Reattach (bumping instanceId + attachNonce) continues to work because
terminalHostConfig is recomputed on every render with the latest
instanceIdRef.current value.

* refactor(tmux-monitor): simplify tailscale port logic with extracted variable

Address code review feedback: extract resolvedPort into a local variable
to avoid the duplicated `host.sshPort ?? host.port` expression that was
assigned to both `port` and `sshPort`.  Restructure as an if/else block
instead of an IIFE for readability.

* Potential fix for pull request finding

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

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* chore: run prettier

* chore: update beta release text

* fix: cant update credential of an RDP host

* feat: add custom key shortcuts

* feat: add support for MFA over SSH

* fix: Invalid websocket frame causing code 10006 crash triggering restart loop

* fix(net): correct SSRF blocklist false-positive blocking all outbound IPv4 (#1079)

* fix: correct IPv4-mapped-IPv6 blocklist entry blocking all outbound IPv4

::ffff:0:0/96 in the IPv6 blocklist matches every IPv4 address once
mapped, since Node's BlockList compares addresses in their mapped form
internally regardless of the declared family. This caused
safeOutboundFetch to reject all IPv4-resolved destinations as private,
breaking outbound requests (e.g. ntfy/webhook notifications) whenever
DNS resolved to IPv4. Replaced with individual mapped ranges mirroring
the existing IPv4 blocklist.

* test: cover isBlockedAddress and link the Node BlockList citation

Exports isBlockedAddress so its family-crossing behavior around
IPv4-mapped-IPv6 addresses can actually be asserted, instead of relying
on manual container debugging to notice a regression. Also swaps the
prior "Node's BlockList compares addresses in mapped form" comment for
one citing the documented example in the Node docs
(https://nodejs.org/api/net.html#class-netblocklist), since that
behavior isn't otherwise obvious from the addSubnet/check call sites.

Related: Termix-SSH/Support#1024

* refactor: derive IPv6 mirror from IPv4 list, split DNS error messages

Two follow-ups from review:

- The IPv6 blocklist previously hand-duplicated each IPv4 range as its
  IPv4-mapped-IPv6 equivalent. Nothing enforced the two stayed in sync,
  which is exactly how the original bug (a mismatched ::ffff:0:0/96
  entry blocking all IPv4) was introduced in the first place. Now
  derived from a single blockedIpv4Ranges list in one loop.

- The connect.lookup hook threw the same "Private destinations are not
  allowed" for both an empty DNS result and an actually-blocked address.
  An empty result is a resolution failure, not a privacy decision, and
  conflating the two is the same kind of opaque-error problem that made
  this bug slow to diagnose in production. Split into distinct messages.

Also extracted the lookup hook itself (createDnsLookupHook) so it can be
unit-tested against a fake resolver directly, instead of only through a
real fetch()/Agent call — the bug lived entirely in this callback, and
undici wraps any error thrown here as a generic "fetch failed" TypeError,
which is why isolating it matters for testability.

---------

Co-authored-by: brennanneoh <497569+brennanneoh@users.noreply.github.com>

* fix(ssh): do not offer chacha20-poly1305 without the native ssh2 binding (#1081)

The availability probe treated a working OpenSSL "chacha20" cipher as proof
that chacha20-poly1305@openssh.com is usable. It is not: ssh2 pure-JS
chacha20-poly1305 corrupts the transport, so the peer aborts the KEX
("incomplete message [preauth]") and the connection times out. Easy to hit
on jump-host connections whose target sshd negotiates chacha20-poly1305
first.

Only trust the native binding (sshcrypto.node); otherwise leave the cipher
disabled so filterCiphers() drops it and AES-GCM is negotiated instead.

Co-authored-by: XtraLarge <>

* fix: add Swiss German server layout (#1078)

* chore: update release notes

* feat: continue improving desktop app 2-way sync with logic fixes and a migration dialog

* fix: dekstop app showing auth form without syncing

* feat: create desktop auto sessions for existing setups

* feat: add electron backend killing

* fix: electron login and session related bugs and updated readme for v2.6.0

* chore: finalize release notes

* fix: click to expand hosts including extra bottom margin

* fix: desktop auth modal failing to log users in

* fix: desktop app failing to sync

* fix: reverse proxy causing sync error

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

* chore: sync Crowdin translations for 2.6.0

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: L.H. <117188168+default-student@users.noreply.github.com>
Co-authored-by: default-student <default-student@github.com>
Co-authored-by: Brad Baker <xyzulu@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Brennan Neoh <brennanneoh@users.noreply.github.com>
Co-authored-by: brennanneoh <497569+brennanneoh@users.noreply.github.com>
Co-authored-by: XtraLarge <eMail@WilliWerres.de>
Co-authored-by: ZacharyZcR <zacharyzcr1984@gmail.com>
This commit is contained in:
232 files changed
+50585 -32016

No files matched your search

+216 -3
View File
@@ -389,6 +389,45 @@
"noSavedServers": "Geen gestoorde bedieners nie",
"removeServer": "Verwyder"
},
"migrationNotice": {
"title": "Termix Desktop loop nou alleenstaande",
"body1": "Hierdie toepassing het voorheen direk aan jou Termix-bediener gekoppel. Dit is herontwerp om volledig op sy eie te loop, en stoor gashere en geloofsbriewe plaaslik sodat dit vanlyn kan bly werk. Tweerigting-sinchronisasie met 'n self-gehoste Termix-bediener is nou opsioneel.",
"body2": "Jou bestaande gashere en geloofsbriewe is steeds op {{url}}. Skakel Afstandsinchronisasie aan en koppel weer aan daardie bediener om hulle terug te bring en albei vorentoe gesinchroniseer te hou.",
"dismiss": "Nie nou nie",
"setUpSync": "Stel afstandsinchronisasie op"
},
"remoteSync": {
"title": "Afstandsinchronisasie",
"description": "Koppel opsioneel hierdie lessenaar-app aan 'n self-gehoste Termix-bediener om jou gashere, geloofsbriewe en brokkies oor toestelle te sinkroniseer. Die app werk altyd ten volle vanlyn, of jy nou koppel of nie.",
"notConnected": "Nie gekoppel nie",
"connected": "Verbonde",
"connectedTo": "Gekoppel aan {{url}}",
"lastSynced": "Laas gesinkroniseer {{time}}",
"neverSynced": "Nooit gesinkroniseer nie",
"syncError": "Sinkronisasiefout: {{message}}",
"needsReauth": "Aanmelding het verval",
"connectButton": "Koppel aan bediener",
"disconnectButton": "Ontkoppel",
"syncNowButton": "Sinkroniseer nou",
"syncing": "Sinkroniseer...",
"serverUrl": "Bediener-URL",
"enterServerUrl": "Voer asseblief 'n bediener-URL in",
"mustIncludeProtocol": "Bediener-URL moet met http:// of https:// begin",
"connectionTestFailed": "Kon nie 'n Termix-bediener by daardie URL bereik nie",
"allowInvalidCertificate": "Laat ongeldige sertifikaat toe",
"allowInvalidCertificateDesc": "Gebruik slegs vir vertroude selfgehoste bedieners met selfgetekende of IP-adres sertifikate.",
"savedServers": "Gestoorde bedieners",
"removeServer": "Verwyder",
"continueButton": "Gaan voort",
"cancelButton": "Kanselleer",
"signInTitle": "Meld aan by {{url}}",
"originTitle": "Verbindingsoorsprong",
"originDescription": "Kies waar SSH-verbindings standaard vandaan kom. Dit kan per gasheer oorskryf word.",
"originLocal": "Hierdie toestel (plaaslike netwerk)",
"originRemote": "Afstandbediener",
"bannerReconnect": "Herkoppel",
"bannerMessage": "Afstandsinchronisasie benodig herverifikasie"
},
"versionCheck": {
"error": "Weergawekontrolefout",
"checkFailed": "Kon nie vir opdaterings kyk nie",
@@ -602,6 +641,7 @@
"overrideCredentialUsername": "Oorskryf geloofsbriewe gebruikersnaam",
"overrideCredentialUsernameDesc": "Gebruik die gebruikersnaam wat hierbo gespesifiseer is in plaas van die gebruikersnaam van die geloofsbriewe",
"oidcUsernameHint": "Gebruik $oidc.preferred_username om jou OIDC-aanmeldnaam te vervang.",
"tailscaleUsernameHint": "Dit moet 'n Unix-gebruiker wees aan wie jou Tailscale-identiteit in die tailnet se SSH ACL toegestaan word, nie noodwendig root nie.",
"jumpHostChain": "Springgasheerketting",
"portKnocking": "Port Knocking",
"addKnock": "Voeg poort by",
@@ -650,6 +690,11 @@
"delayAfterMs": "Vertraging na (ms)",
"useSocks5Proxy": "Gebruik SOCKS5 Proxy",
"useSocks5ProxyDesc": "Roeteer verbinding deur 'n proxy-bediener",
"connectionOrigin": "Verbindingsoorsprong",
"connectionOriginDesc": "Waar hierdie gasheer se SSH-verbinding vandaan kom. Oorskryf die rekenaarprogram se globale verstekwaarde.",
"connectionOriginDefault": "Gebruik verstekwaarde",
"connectionOriginLocal": "Hierdie toestel (plaaslike netwerk)",
"connectionOriginRemote": "Afstandbediener",
"proxyHost": "Proxy-gasheer",
"proxyPort": "Proxy-poort",
"proxyUsername": "Proxy-gebruikersnaam",
@@ -762,6 +807,14 @@
"customThemeBrightCyan": "Helder Siaan",
"customThemeBrightWhite": "Helderwit",
"customThemeResetTooltip": "Stel terug na verstekwaardes",
"savedThemesLabel": "Gestoorde temas",
"saveAsGlobalTheme": "Stoor as globale tema",
"saveGlobalThemeNamePrompt": "Voer 'n naam vir hierdie tema in",
"saveGlobalThemeSuccess": "Tema gestoor",
"saveGlobalThemeError": "Kon nie tema stoor nie",
"applyGlobalThemeTooltip": "Pas hierdie tema toe",
"deleteGlobalThemeTooltip": "Vee hierdie tema uit",
"noSavedThemes": "Geen gestoorde temas nog nie",
"syntaxHighlightingLabel": "Sintaksis-uitlig",
"syntaxHighlightingDesc": "Kleur terminaaluitvoer in (foute, paaie, IP's, tydstempels)",
"syntaxHighlightingCategories": "Merk kategorieë uit",
@@ -791,6 +844,8 @@
"enableAutoTmuxDesc": "Begin of koppel outomaties aan tmux-sessie",
"enableSessionLogging": "Sessie-logging",
"enableSessionLoggingDesc": "Neem terminaalsessie-uitvoer op vir latere hersiening",
"allowSessionSharing": "Laat Sessiedeling Toe",
"allowSessionSharingDesc": "Laat regstreekse sessies op hierdie gasheer via skakel of met ander gebruikers gedeel word",
"enableCommandHistory": "Opdraggeskiedenis",
"enableCommandHistoryDesc": "Rekordopdragte word in hierdie terminaal uitgevoer vir geskiedenis en outovoltooiing",
"linkClickBehaviorLabel": "Skakelklikgedrag",
@@ -895,6 +950,7 @@
"proxmoxResultImported": "{{count}} ingevoer",
"proxmoxResultUpdated": "{{count}} opgedateer",
"proxmoxResultFailed": "{{count}} het misluk",
"proxmoxResultSkippedNoIp": "{{count}} oorgeslaan (geen IP gevind nie)",
"proxmoxImportComplete": "Proxmox-invoer voltooi: {{summary}}",
"proxmoxDiscoveryFailed": "Ontdekking het misluk",
"proxmoxImportFailed": "Invoer het misluk",
@@ -961,6 +1017,9 @@
"failedToSaveCredential": "Kon nie geloofsbriewe stoor nie",
"credentialNameRequired": "Voer asseblief 'n naam vir die geloofsbrief in",
"credentialAuthRequired": "Voeg 'n wagwoord, 'n SSH-sleutel of albei by",
"createCredentialFromHostBtn": "Skep geloofsbriewe",
"createCredentialFromHostTitle": "Skep geloofsbriewe vanaf gasheer",
"createCredentialFromHostDesc": "Skep 'n herbruikbare, deelbare geloofsbriewe-inskrywing wat vooraf ingevul is met hierdie gasheer se huidige gebruikersnaam, wagwoord en/of SSH-sleutel.",
"backToHosts": "Terug na gashere",
"backToCredentials": "Terug na geloofsbriewe",
"pinned": "Vasgepen",
@@ -1000,6 +1059,9 @@
"folderNestingHint": "Gebruik / om vlakke te skei en geneste vouers te skep.",
"folderColor": "Kleur",
"folderIcon": "Ikoon",
"folderCredential": "Geloofsbrief",
"folderCredentialNone": "Geen geloofsbriewe toegeken nie",
"folderCredentialHint": "Gashere in hierdie vouer wat \"Gestoorde geloofsbriewe\"-magtiging gebruik sonder dat hul eie geloofsbriewe gekies is, sal hierdie een erf.",
"folderPreview": "Voorskou",
"folderNameFallback": "Naamlose vouer",
"createFolderButton": "Skep vouer",
@@ -1181,6 +1243,10 @@
"filterTagsGroup": "Etikette",
"shareHost": "Deel gasheer",
"shareHostTitle": "Deel: {{name}}",
"shareFolder": "Deel vouer",
"shareFolderTitle": "Deel vouer: {{name}}",
"folderSharedSuccessfully": "Gedeelde {{count}} gasheer(s) in vouer",
"failedToShareFolder": "Kon nie vouer deel nie",
"sharing": {
"loadError": "Kon nie deeldata laai nie. Probeer asseblief weer.",
"shareWithSection": "Deel met",
@@ -1221,6 +1287,7 @@
"shareWithCount": "Deel ({{count}})",
"currentAccess": "Huidige toegang",
"noAccessEntries": "Hierdie gasheer is nog nie gedeel nie",
"folderShareSummary": "Gedeelde {{shared}} van {{total}} gasheer(s) in hierdie vouer",
"grantedBy": "Toegeken deur",
"expires": "Vervaldatum",
"expired": "Verstryk",
@@ -1242,6 +1309,8 @@
"authMethod": "Magtigingsmetode",
"authTypeDirect": "Direkte",
"authTypeCredential": "Geloofsbrief",
"authTypeNone": "Geen",
"authTypeNoneDesc": "Geen aanmeldingsbesonderhede word gestoor nie. Jy sal elke keer as jy koppel vir 'n gebruikersnaam en wagwoord gevra word; hulle word nie gestoor nie.",
"selectCredential": "Kies 'n geloofsbrief...",
"connectionSettings": "Verbindingsinstellings",
"displaySettings": "Skerminstellings",
@@ -1259,6 +1328,7 @@
"rdpPort": "RDP-poort",
"username": "Gebruikersnaam",
"password": "Wagwoord",
"passwordSaved": "Wagwoord gestoor, tik om te verander",
"domain": "Domein",
"securityMode": "Sekuriteitsmodus",
"colorDepth": "Kleurdiepte",
@@ -1424,7 +1494,60 @@
"expiresIn": "Verval oor {{duration}}",
"search": "Soek verbindings...",
"noSearchResults": "Geen verbindings stem ooreen met jou soektog nie",
"rename": "Hernoem sessie"
"rename": "Hernoem sessie",
"sectionSharedWithMe": "Met my gedeel",
"sharedBy": "Gedeel deur {{username}}",
"join": "Sluit aan",
"sharedSessionLabel": "{{hostName}} (gedeel)"
},
"sessionSharing": {
"guestView": {
"loading": "Verbind met gedeelde sessie...",
"linkInvalid": "Hierdie deelskakel is ongeldig, het verval of is herroep",
"rateLimited": "Te veel pogings, probeer asseblief weer binnekort",
"sessionEnded": "Hierdie sessie is verby",
"readOnlyBadge": "Slegs kyk"
},
"modalTitle": "Deel sessie",
"shareButton": "Deel",
"notReadyToShare": "Sessie is nog nie gereed om te deel nie",
"modeTab": {
"link": "Skakel",
"user": "Gebruiker"
},
"linkModeDescription": "Enigiemand met hierdie skakel kan aansluit, geen rekening nodig nie.",
"userModeDescription": "Deel met 'n spesifieke gebruiker wat reeds toegang tot hierdie gasheer het. Indien hulle nog nie toegang het nie, deel die gasheer eers met hulle of gebruik eerder 'n skakel. Sodra dit gedeel is, verskyn die sessie in hul Verbindings-oortjie.",
"permissionLevel": {
"label": "Toestemmingsvlak",
"readOnly": "Leesalleen",
"readOnlyDescription": "Kan die sessie regstreeks kyk, maar kan nie tik of interaksie hê nie.",
"readWrite": "Lees-skryf",
"readWriteDescription": "Kan tik en met die sessie interaksie hê net soos die eienaar."
},
"expiryLabel": "Skakelvervaldatum",
"createLinkButton": "Skep skakel",
"createShareButton": "Deel met gebruiker",
"searchUsersPlaceholder": "Soek gebruikers...",
"noUsersFound": "Geen gebruikers gevind nie",
"linkCreated": "Deel skakel geskep",
"linkCopied": "Skakel gekopieer na knipbord",
"copyLink": "Kopieer skakel",
"shareCreated": "Sessie gedeel. Dit sal in hul Verbindings-oortjie verskyn.",
"shareFailed": "Kon nie deel skep nie",
"userLacksHostAccess": "Daardie gebruiker het nog nie toegang tot hierdie gasheer nie. Deel die gasheer eers met hulle, of gebruik eerder 'n skakel.",
"activeShares": "Aktiewe aandele",
"noActiveShares": "Geen aktiewe delings vir hierdie sessie nie",
"revoke": "Herroep",
"revokeConfirmTitle": "Herroep hierdie deling?",
"revokeConfirmDescription": "Enigiemand wat hierdie deel gebruik, sal onmiddellik toegang verloor.",
"revoked": "Deel herroep",
"revokeFailed": "Kon nie deel herroep nie",
"joinCount": "{{count}} sluit aan",
"joinCount_other": "{{count}} sluit aan",
"expiresAt": "Vervaldatum {{date}}",
"linkShareBadge": "Skakel",
"userShareBadge": "Gebruiker: {{username}}",
"loadSharesFailed": "Kon nie aktiewe delings laai nie"
},
"guacamole": {
"connecting": "Verbind met {{type}} sessie...",
@@ -1436,6 +1559,9 @@
"reconnect": "Herkoppel",
"retry": "Probeer weer",
"guacdUnavailable": "Diens vir afstandwerkskerm (guacd) is nie beskikbaar nie. Maak asseblief seker dat guacd loop, toeganklik is en behoorlik in administrateurinstellings gekonfigureer is.",
"credentialPromptTitle": "Voer RDP-aanbewyse in",
"credentialPromptDescription": "Hierdie gasheer is ingestel om vir geloofsbriewe te vra tydens verbinding. Hulle word slegs vir hierdie sessie gebruik en word nie gestoor nie.",
"connect": "Verbind",
"ctrlAltDel": "Ctrl+Alt+Del",
"toolbar": {
"ctrlAltDel": "Ctrl+Alt+Del",
@@ -1461,7 +1587,9 @@
"reconnect": "Herkoppel Sessie",
"collapse": "Vou nutsbalk in",
"expand": "Vou die nutsbalk uit",
"dragHandle": "Sleep om te herposisioneer"
"dragHandle": "Sleep om te herposisioneer",
"switchToTrackpad": "Skakel oor na raakvlakmodus (sleep om wyser te beweeg, tik om te klik)",
"switchToTouch": "Skakel oor na raakmodus (tik direk waar jy wil klik)"
}
},
"terminal": {
@@ -1508,6 +1636,11 @@
"totpRequired": "Tweefaktor-verifikasie vereis",
"totpCodeLabel": "Verifikasiekode",
"totpVerify": "Verifieer",
"mfaPromptRequired": "Verifikasie Vereis",
"mfaPushRequired": "Stoot-verifikasie vereis",
"mfaMenuPlaceholder": "Voer jou antwoord in",
"mfaWaitingApproval": "Wag vir goedkeuring op jou toestel...",
"mfaSendRequest": "Stuur versoek",
"warpgateAuthRequired": "Warpgate-verifikasie vereis",
"warpgateSecurityKey": "Sekuriteitsleutel",
"warpgateAuthUrl": "Verifikasie-URL",
@@ -2277,7 +2410,8 @@
"resetCodeRateLimited": "Tempo beperk: Te veel verifikasiepogings. Probeer asseblief later weer.",
"resetCodeRateLimitedWithTime": "Tempo beperk: Te veel verifikasiepogings. Wag asseblief {{time}} sekondes voordat u weer probeer.",
"authTokenSaveFailed": "Kon nie verifikasietoken stoor nie",
"failedToLoadServer": "Kon nie bediener laai nie"
"failedToLoadServer": "Kon nie bediener laai nie",
"remoteServerRequired": "Afstandbediener word benodig. Koppel 'n afstandbediener in Instellings om hierdie verbindingstipe te gebruik."
},
"messages": {
"registrationDisabled": "Nuwe rekeningregistrasie is tans deur 'n administrateur gedeaktiveer. Meld asseblief aan of kontak 'n administrateur.",
@@ -2644,6 +2778,17 @@
"sslSaveFailed": "Kon nie SSL-instellings stoor nie",
"sslRequiresDomain": "Domein en e-posadres word vereis",
"sslInfoNote": "Nadat u 'n sertifikaat uitgereik het, aktiveer SSL in u omgewingveranderlikes (ENABLE_SSL=true) en herbegin Termix.",
"sslManualOption": "Handleiding (laai sertifikaat op)",
"sslManualCert": "Sertifikaat (PEM)",
"sslManualCertPlaceholder": "-----BEGIN SERTIFIKAAT-----",
"sslManualKey": "Privaatsleutel (PEM)",
"sslManualKeyPlaceholder": "-----BEGIN PRIVAAT SLEUTEL-----",
"sslManualDesc": "Plak jou bestaande sertifikaat en privaat sleutel, insluitend 'n volledige ketting indien vereis deur jou CA.",
"sslManualUpload": "Laai sertifikaat op en installeer dit",
"sslManualUploadLoading": "Laai tans sertifikaat op...",
"sslManualUploadSuccess": "Sertifikaat suksesvol opgelaai en geïnstalleer",
"sslManualUploadFailed": "Sertifikaatoplaai het misluk",
"sslManualRequiresFields": "Sertifikaat en privaat sleutel word vereis",
"auditLogTotal": "{{total}} totale inskrywings",
"auditLogEmpty": "Geen ouditlogboekinskrywings gevind nie",
"auditLogSuccess": "Sukses",
@@ -2672,6 +2817,12 @@
"commandHistoryEnabled": "Opdraggeskiedenis",
"commandHistoryEnabledDesc": "Laat die opname van opdraggeskiedenis toe. Wanneer dit gedeaktiveer is, word geskiedenis nie gestoor nie, ongeag die instellings per gasheer.",
"updateCommandHistoryFailed": "Kon nie die instelling vir opdraggeskiedenis opdateer nie",
"analyticsEnabled": "Deel Anonieme Gebruiksstatistieke",
"analyticsEnabledDesc": "Stuur 'n anonieme daaglikse telling van gebruikers, gashere en funksiegebruik om Termix te help verbeter. Geen persoonlike data of verbindingsbesonderhede word ooit ingesluit nie.",
"updateAnalyticsFailed": "Kon nie analitiese instelling opdateer nie",
"sessionSharingGloballyEnabled": "Laat Sessiedeling Toe",
"sessionSharingGloballyEnabledDesc": "Laat lewendige terminaal-, RDP-, VNC- en Telnet-sessies toe om instansiewyd gedeel te word. Oorskryf elke deelskakelaar per gasheer wanneer dit gedeaktiveer is.",
"updateSessionSharingFailed": "Kon nie sessiedelinginstelling opdateer nie",
"sessionTimeout": "Sessie-tydsbeperking",
"hours": "ure",
"sessionTimeoutRange": "Min 1 uur · Maks 720 uur",
@@ -3119,6 +3270,47 @@
"executionSuccess": "Sukses",
"executionFailed": "Misluk"
},
"keybindings": {
"title": "Sleutelbordkortpaaie",
"description": "Pasmaak terminaalkopieer-, plak- en beheerkortpaaie, of bind sleutels om teks te stuur of 'n brokkie uit te voer.",
"defaultsHeading": "Ingeboude kortpaaie",
"customHeading": "Pasgemaakte kortpaaie",
"addBinding": "Voeg kortpad by",
"addBindingTitle": "Voeg kortpad by",
"editBindingTitle": "Wysig Kortpad",
"loading": "Laai tans...",
"noCustomBindings": "Geen persoonlike kortpaaie nog nie",
"defaultBadge": "Standaard",
"customizedBadge": "Aangepas",
"customize": "Pasmaak",
"resetToDefault": "Stel terug na verstekwaarde",
"resetAllToDefaults": "Stel alles terug na verstekwaardes",
"close": "Maak toe",
"cancel": "Kanselleer",
"saveBinding": "Stoor Kortpad",
"saveError": "Kon nie sleutelbordkortpaaie stoor nie",
"pressKeysToRecord": "Sleutelkombinasie",
"pressKeysPlaceholder": "Klik en druk sleutels",
"recording": "Druk sleutels...",
"comboRequiredError": "Druk eers 'n sleutelkombinasie",
"textRequiredError": "Voer die teks in om te stuur",
"controlCodeRequiredError": "Voer 'n enkele letter vir die beheerkode in",
"snippetRequiredError": "Kies 'n uittreksel",
"conflictWarning": "Hierdie kombinasie is reeds gebind aan {{combo}}. As jy dit stoor, sal albei aktiveer.",
"actionLabel": "Aksie",
"actionCopy": "Kopieer seleksie",
"actionPaste": "Plak",
"actionSendControlCode": "Stuur Ctrl+letter sein",
"actionSendText": "Stuur SMS",
"actionRunSnippet": "Voer bestaande brokkie uit",
"controlCodeLabel": "Brief",
"textLabel": "SMS om te stuur",
"appendEnterLabel": "Druk Enter na stuur",
"snippetLabel": "Brokkie",
"selectSnippetPlaceholder": "Kies 'n uittreksel",
"orphanedSnippetWarning": "brokkie nie gevind nie",
"clipboardPermissionNote": "Kan in sommige blaaiers met die eerste gebruik vir knipbordtoestemming vra."
},
"userProfile": {
"donateTitle": "Hou Termix lewendig",
"donateDescription": "Termix is gratis, self-gehost en gebou deur slegs 'n paar mense in hul vrye tyd. As dit jou tyd of geld bespaar het, help 'n kripto-skenking om dit aan die gang te hou.",
@@ -3134,6 +3326,7 @@
"sectionAppearance": "Voorkoms",
"sectionSecurity": "Sekuriteit",
"sectionApiKeys": "API-sleutels",
"sectionData": "Data",
"sectionC2sTunnels": "C2S-tonnels",
"usernameLabel": "Gebruikersnaam",
"roleLabel": "Rol",
@@ -3162,6 +3355,9 @@
"settingsTerminal": "Terminaal",
"commandAutocomplete": "Opdrag Outomatiese Voltooiing",
"commandAutocompleteDesc": "Wys outovoltooiing terwyl jy tik",
"keyboardShortcuts": "Sleutelbordkortpaaie",
"keyboardShortcutsDescription": "Pas terminale kopieer-, plak- en opdragkortpaaie aan",
"manageShortcuts": "Bestuur",
"terminalLinkBehavior": "Klik op die terminaalskakel",
"terminalLinkBehaviorDesc": "Standaardgedrag wanneer skakels in die terminaal geklik word",
"historyTracking": "Geskiedenisopsporing",
@@ -3228,6 +3424,22 @@
"apiKeyUsageHint": "Sluit jou sleutel in die",
"apiKeyUsageHintHeader": "opskrif.",
"apiKeyPermissionsHint": "Sleutels erf die regte van die skeppergebruiker.",
"exportData": "Voer my data uit",
"exportDataDesc": "Laai 'n rugsteun van jou gashere, geloofsbriewe en instellings af om na 'n ander toestel oor te dra",
"export": "Uitvoer",
"exporting": "Uitvoer tans...",
"importData": "Voer my data in",
"importDataDesc": "Herstel jou gashere, geloofsbriewe en instellings vanaf 'n .sqlite-rugsteunlêer",
"importDataSelected": "Gekies: {{name}}",
"selectFile": "Kies Lêer",
"changeFile": "Verandering",
"import": "Invoer",
"importing": "Voer tans in...",
"exportSuccess": "Data suksesvol uitgevoer",
"exportFailed": "Data-uitvoer het misluk",
"importSelectFile": "Kies asseblief eers 'n lêer",
"importCompleted": "Invoer voltooi: {{total}} items ingevoer, {{skipped}} oorgeslaan",
"importFailed": "Invoer het misluk: {{error}}",
"roleUser": "Gebruiker",
"authMethodDual": "Dubbele Magtiging",
"authMethodOidc": "OIDC",
@@ -3379,6 +3591,7 @@
"pageUp": "Bladsy Op",
"pageDown": "PgDn",
"delete": "Del",
"paste": "Plak",
"editQuickKeys": "Wysig vinnige sleutels",
"quickKeysTitle": "Vinnige sleutels",
"quickKeysDesc": "Tik × om te verwyder. Ondersteun tot 8 karakters.",