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": "Niciun server salvat",
"removeServer": "Elimina"
},
"migrationNotice": {
"title": "Termix Desktop rulează acum independent",
"body1": "Această aplicație se conecta direct la serverul Termix. A fost reelaborată pentru a rula complet independent, stocând gazdele și acreditările local, astfel încât să funcționeze în continuare offline. Sincronizarea bidirecțională cu un server Termix auto-găzduit este acum opțională.",
"body2": "Gazdele și acreditările existente sunt încă pe {{url}}. Activați sincronizarea la distanță și reconectați-vă la serverul respectiv pentru a le reactiva și a le menține sincronizate de acum înainte.",
"dismiss": "Nu acum",
"setUpSync": "Configurați sincronizarea la distanță"
},
"remoteSync": {
"title": "Sincronizare la distanță",
"description": "Opțional, conectați această aplicație desktop la un server Termix auto-găzduit pentru a sincroniza gazdele, acreditările și fragmentele de date pe toate dispozitivele. Aplicația funcționează întotdeauna complet offline, indiferent dacă vă conectați sau nu.",
"notConnected": "Neconectat",
"connected": "Conectat",
"connectedTo": "Conectat la {{url}}",
"lastSynced": "Ultima sincronizare {{time}}",
"neverSynced": "Nu s-a sincronizat niciodată",
"syncError": "Eroare de sincronizare: {{message}}",
"needsReauth": "Conectarea a expirat",
"connectButton": "Conectare la server",
"disconnectButton": "Deconecta",
"syncNowButton": "Sincronizează acum",
"syncing": "Se sincronizează...",
"serverUrl": "URL-ul serverului",
"enterServerUrl": "Introduceți adresa URL a serverului",
"mustIncludeProtocol": "URL-ul serverului trebuie să înceapă cu http:// sau https://",
"connectionTestFailed": "Nu s-a putut accesa un server Termix la adresa URL respectivă.",
"allowInvalidCertificate": "Permiteți certificatul nevalid",
"allowInvalidCertificateDesc": "A se utiliza numai pentru servere auto-găzduite de încredere, cu certificate autosemnate sau cu adresă IP.",
"savedServers": "Servere salvate",
"removeServer": "Elimina",
"continueButton": "Continua",
"cancelButton": "Anula",
"signInTitle": "Conectați-vă la {{url}}",
"originTitle": "Originea conexiunii",
"originDescription": "Alegeți în mod implicit de unde provin conexiunile SSH. Această opțiune poate fi ignorată pentru fiecare gazdă.",
"originLocal": "Acest dispozitiv (rețea locală)",
"originRemote": "Server la distanță",
"bannerReconnect": "Reconectați-vă",
"bannerMessage": "Sincronizarea la distanță necesită reautentificare"
},
"versionCheck": {
"error": "Eroare la verificarea versiunii",
"checkFailed": "Nu s-a putut verifica dacă există actualizări",
@@ -602,6 +641,7 @@
"overrideCredentialUsername": "Suprascrierea acreditărilor de utilizator",
"overrideCredentialUsernameDesc": "Folosește numele de utilizator specificat mai sus în locul numelui de utilizator al acreditării",
"oidcUsernameHint": "Folosește $oidc.preferred_username pentru a înlocui numele de utilizator OIDC.",
"tailscaleUsernameHint": "Acesta trebuie să fie un utilizator Unix căruia îi este acordată identitatea Tailscale în ACL-ul SSH al rețelei tailnet, nu neapărat root.",
"jumpHostChain": "Lanțul gazdă Jump",
"portKnocking": "Lovitura în port",
"addKnock": "Adăugați port",
@@ -650,6 +690,11 @@
"delayAfterMs": "Întârziere după (ms)",
"useSocks5Proxy": "Folosește proxy-ul SOCKS5",
"useSocks5ProxyDesc": "Dirijați conexiunea printr-un server proxy",
"connectionOrigin": "Originea conexiunii",
"connectionOriginDesc": "De unde provine conexiunea SSH a acestei gazde. Suprascrie setarea globală implicită a aplicației desktop.",
"connectionOriginDefault": "Utilizați implicit",
"connectionOriginLocal": "Acest dispozitiv (rețea locală)",
"connectionOriginRemote": "Server la distanță",
"proxyHost": "Gazdă proxy",
"proxyPort": "Port proxy",
"proxyUsername": "Nume de utilizator proxy",
@@ -762,6 +807,14 @@
"customThemeBrightCyan": "Cian strălucitor",
"customThemeBrightWhite": "Alb strălucitor",
"customThemeResetTooltip": "Resetare la setările implicite",
"savedThemesLabel": "Teme salvate",
"saveAsGlobalTheme": "Salvați ca temă globală",
"saveGlobalThemeNamePrompt": "Introduceți un nume pentru această temă",
"saveGlobalThemeSuccess": "Tema a fost salvată",
"saveGlobalThemeError": "Nu s-a putut salva tema",
"applyGlobalThemeTooltip": "Aplică această temă",
"deleteGlobalThemeTooltip": "Ștergeți această temă",
"noSavedThemes": "Nicio temă salvată încă",
"syntaxHighlightingLabel": "Evidențierea sintaxei",
"syntaxHighlightingDesc": "Colorează ieșirea terminalului (erori, căi, IP-uri, timestamp-uri)",
"syntaxHighlightingCategories": "Evidențiați categoriile",
@@ -791,6 +844,8 @@
"enableAutoTmuxDesc": "Lansează sau atașează automat la sesiunea tmux",
"enableSessionLogging": "Înregistrarea sesiunilor",
"enableSessionLoggingDesc": "Înregistrați ieșirea sesiunii terminale pentru o revizuire ulterioară",
"allowSessionSharing": "Permiteți partajarea sesiunii",
"allowSessionSharingDesc": "Permiteți partajarea sesiunilor live de pe această gazdă prin link sau cu alți utilizatori",
"enableCommandHistory": "Istoricul comenzilor",
"enableCommandHistoryDesc": "Înregistrați comenzile executate în acest terminal pentru istoric și completare automată",
"linkClickBehaviorLabel": "Comportamentul clicurilor pe link",
@@ -895,6 +950,7 @@
"proxmoxResultImported": "{{count}} importat",
"proxmoxResultUpdated": "{{count}} actualizat",
"proxmoxResultFailed": "{{count}} a eșuat",
"proxmoxResultSkippedNoIp": "{{count}} omis (nu a fost găsită nicio adresă IP)",
"proxmoxImportComplete": "Import Proxmox finalizat: {{summary}}",
"proxmoxDiscoveryFailed": "Descoperirea a eșuat",
"proxmoxImportFailed": "Importul a eșuat",
@@ -961,6 +1017,9 @@
"failedToSaveCredential": "Nu s-a putut salva acreditările",
"credentialNameRequired": "Vă rugăm să introduceți un nume pentru acreditare",
"credentialAuthRequired": "Adăugați o parolă, o cheie SSH sau ambele",
"createCredentialFromHostBtn": "Creați acreditări",
"createCredentialFromHostTitle": "Creați acreditări de la gazdă",
"createCredentialFromHostDesc": "Creați o intrare de acreditări reutilizabilă și partajabilă, preumplută cu numele de utilizator, parola și/sau cheia SSH actuale ale acestei gazde.",
"backToHosts": "Înapoi la Gazde",
"backToCredentials": "Înapoi la acreditări",
"pinned": "Fixat",
@@ -1000,6 +1059,9 @@
"folderNestingHint": "Folosește / pentru a separa niveluri și a crea foldere imbricate.",
"folderColor": "Culoare",
"folderIcon": "Pictogramă",
"folderCredential": "Acreditare",
"folderCredentialNone": "Nicio acreditare atribuită",
"folderCredentialHint": "Gazdele din acest folder care utilizează autentificarea „Credențiale stocate” fără a fi selectate propriile credențiale vor moșteni aceasta.",
"folderPreview": "Previzualizare",
"folderNameFallback": "Dosar fără titlu",
"createFolderButton": "Creați un folder",
@@ -1181,6 +1243,10 @@
"filterTagsGroup": "Etichete",
"shareHost": "Gazdă partajată",
"shareHostTitle": "Distribuie: {{name}}",
"shareFolder": "Partajați folderul",
"shareFolderTitle": "Partajați folderul: {{name}}",
"folderSharedSuccessfully": "Gazdă(e) {{count}} partajată(e) în folder",
"failedToShareFolder": "Nu s-a putut partaja folderul",
"sharing": {
"loadError": "Nu s-au putut încărca datele de partajare. Vă rugăm să încercați din nou.",
"shareWithSection": "Distribuiți cu",
@@ -1221,6 +1287,7 @@
"shareWithCount": "Distribuie ({{count}})",
"currentAccess": "Acces curent",
"noAccessEntries": "Această gazdă nu a fost încă partajată",
"folderShareSummary": "Gazdă(e) {{shared}} partajată din {{total}} în acest folder",
"grantedBy": "Acordat de",
"expires": "Expiră",
"expired": "Expirat",
@@ -1242,6 +1309,8 @@
"authMethod": "Metodă de autentificare",
"authTypeDirect": "Direct",
"authTypeCredential": "Acreditare",
"authTypeNone": "Nici unul",
"authTypeNoneDesc": "Nu sunt stocate acreditări. Vi se va solicita un nume de utilizator și o parolă de fiecare dată când vă conectați; acestea nu sunt salvate.",
"selectCredential": "Selectați o acreditare...",
"connectionSettings": "Setări de conectare",
"displaySettings": "Setări de afișare",
@@ -1259,6 +1328,7 @@
"rdpPort": "Port RDP",
"username": "Nume de utilizator",
"password": "Parolă",
"passwordSaved": "Parolă salvată, tastați pentru a o modifica",
"domain": "Domeniu",
"securityMode": "Mod de securitate",
"colorDepth": "Adâncimea culorii",
@@ -1424,7 +1494,60 @@
"expiresIn": "Expiră în {{duration}}",
"search": "Căutați conexiuni...",
"noSearchResults": "Nicio conexiune nu corespunde căutării dvs.",
"rename": "Redenumiți sesiunea"
"rename": "Redenumiți sesiunea",
"sectionSharedWithMe": "Distribuit cu mine",
"sharedBy": "Distribuit de {{username}}",
"join": "Alătură-te",
"sharedSessionLabel": "{{hostName}} (partajat)"
},
"sessionSharing": {
"guestView": {
"loading": "Conectare la sesiunea partajată...",
"linkInvalid": "Acest link de partajare este invalid, a expirat sau a fost revocat.",
"rateLimited": "Prea multe încercări, vă rugăm să încercați din nou în scurt timp",
"sessionEnded": "Această sesiune s-a încheiat",
"readOnlyBadge": "Doar vizualizare"
},
"modalTitle": "Partajați sesiunea",
"shareButton": "Distribuie",
"notReadyToShare": "Sesiunea nu este încă gata de partajare",
"modeTab": {
"link": "Legătură",
"user": "Utilizator"
},
"linkModeDescription": "Oricine are acest link se poate alătura, nu este necesar un cont.",
"userModeDescription": "Partajați cu un anumit utilizator care are deja acces la această gazdă. Dacă nu are încă acces, partajați mai întâi gazda cu acesta sau utilizați un link în schimb. După partajare, sesiunea apare în fila Conexiuni.",
"permissionLevel": {
"label": "Nivel de permisiune",
"readOnly": "Doar citire",
"readOnlyDescription": "Pot urmări sesiunea în direct, dar nu pot tasta sau interacționa.",
"readWrite": "Citire-scriere",
"readWriteDescription": "Poate tasta și interacționa cu sesiunea la fel ca proprietarul."
},
"expiryLabel": "Expirarea linkului",
"createLinkButton": "Creați un link",
"createShareButton": "Partajează cu utilizatorul",
"searchUsersPlaceholder": "Căutați utilizatori...",
"noUsersFound": "Nu au fost găsiți utilizatori",
"linkCreated": "Link de partajare creat",
"linkCopied": "Linkul a fost copiat în clipboard",
"copyLink": "Copiază linkul",
"shareCreated": "Sesiune partajată. Va apărea în fila Conexiuni.",
"shareFailed": "Nu s-a putut crea partajarea",
"userLacksHostAccess": "Utilizatorul respectiv nu are încă acces la această gazdă. Partajați mai întâi gazda cu acesta sau folosiți un link în schimb.",
"activeShares": "Acțiuni active",
"noActiveShares": "Nicio partajare activă pentru această sesiune",
"revoke": "Revoca",
"revokeConfirmTitle": "Revocați această partajare?",
"revokeConfirmDescription": "Oricine folosește această partajare va pierde accesul imediat.",
"revoked": "Acțiune revocată",
"revokeFailed": "Nu s-a putut revoca partajarea",
"joinCount": "{{count}} alătură-te",
"joinCount_other": "{{count}} se alătură",
"expiresAt": "Expiră la {{date}}",
"linkShareBadge": "Legătură",
"userShareBadge": "Utilizator: {{username}}",
"loadSharesFailed": "Nu s-au putut încărca partajările active"
},
"guacamole": {
"connecting": "Se conectează la sesiunea {{type}}...",
@@ -1436,6 +1559,9 @@
"reconnect": "Reconectați-vă",
"retry": "Reîncercați",
"guacdUnavailable": "Serviciul desktop la distanță (guacd) nu este disponibil. Asigurați-vă că guacd rulează, este accesibil și configurat corect în setările de administrare.",
"credentialPromptTitle": "Introduceți acreditările RDP",
"credentialPromptDescription": "Această gazdă este configurată să solicite acreditări la conectare. Acestea sunt utilizate doar pentru această sesiune și nu sunt salvate.",
"connect": "Conectează-te",
"ctrlAltDel": "Ctrl+Alt+Del",
"toolbar": {
"ctrlAltDel": "Ctrl+Alt+Del",
@@ -1461,7 +1587,9 @@
"reconnect": "Sesiune de reconectare",
"collapse": "Restrângeți bara de instrumente",
"expand": "Extindeți bara de instrumente",
"dragHandle": "Trageți pentru a repoziționa"
"dragHandle": "Trageți pentru a repoziționa",
"switchToTrackpad": "Comutare la modul trackpad (tragere pentru mutarea cursorului, atingere pentru clic)",
"switchToTouch": "Comutare la modul tactil (atingere direct unde doriți să faceți clic)"
}
},
"terminal": {
@@ -1508,6 +1636,11 @@
"totpRequired": "Autentificare cu doi factori necesară",
"totpCodeLabel": "Cod de verificare",
"totpVerify": "Verifica",
"mfaPromptRequired": "Autentificare necesară",
"mfaPushRequired": "Autentificare push necesară",
"mfaMenuPlaceholder": "Introduceți răspunsul dvs.",
"mfaWaitingApproval": "Se așteaptă aprobarea pe dispozitivul dvs....",
"mfaSendRequest": "Trimiteți cererea",
"warpgateAuthRequired": "Autentificare Warpgate necesară",
"warpgateSecurityKey": "Cheie de securitate",
"warpgateAuthUrl": "URL de autentificare",
@@ -2277,7 +2410,8 @@
"resetCodeRateLimited": "Rată limitată: Prea multe încercări de verificare. Vă rugăm să încercați din nou mai târziu.",
"resetCodeRateLimitedWithTime": "Rată limitată: Prea multe încercări de verificare. Vă rugăm să așteptați {{time}} secunde înainte de a încerca din nou.",
"authTokenSaveFailed": "Nu s-a putut salva jetonul de autentificare",
"failedToLoadServer": "Nu s-a putut încărca serverul"
"failedToLoadServer": "Nu s-a putut încărca serverul",
"remoteServerRequired": "Este necesar un server la distanță. Conectați un server la distanță în Setări pentru a utiliza acest tip de conexiune."
},
"messages": {
"registrationDisabled": "Înregistrarea unui cont nou este dezactivată în prezent de un administrator. Vă rugăm să vă conectați sau să contactați un administrator.",
@@ -2644,6 +2778,17 @@
"sslSaveFailed": "Setările SSL nu au putut fi salvate.",
"sslRequiresDomain": "Domeniul și adresa de e-mail sunt obligatorii",
"sslInfoNote": "După emiterea unui certificat, activați SSL în variabilele de mediu (ENABLE_SSL=true) și reporniți Termix.",
"sslManualOption": "Manual (încărcare certificat)",
"sslManualCert": "Certificat (PEM)",
"sslManualCertPlaceholder": "-----ÎNCEPERE CERTIFICAT-----",
"sslManualKey": "Cheie privată (PEM)",
"sslManualKeyPlaceholder": "-----ÎNCEPERE CHEIE PRIVATĂ-----",
"sslManualDesc": "Lipiți certificatul și cheia privată existente, inclusiv un lanț complet, dacă este necesar de către autoritatea de certificare.",
"sslManualUpload": "Încărcați și instalați certificatul",
"sslManualUploadLoading": "Se încarcă certificatul...",
"sslManualUploadSuccess": "Certificatul a fost încărcat și instalat cu succes",
"sslManualUploadFailed": "Încărcarea certificatului a eșuat",
"sslManualRequiresFields": "Certificatul și cheia privată sunt necesare",
"auditLogTotal": "{{total}} total intrări",
"auditLogEmpty": "Nu au fost găsite intrări în jurnalul de audit",
"auditLogSuccess": "Succes",
@@ -2672,6 +2817,12 @@
"commandHistoryEnabled": "Istoricul comenzilor",
"commandHistoryEnabledDesc": "Permite înregistrarea istoricului comenzilor. Când este dezactivată, istoricul nu este salvat, indiferent de setările pentru fiecare gazdă.",
"updateCommandHistoryFailed": "Nu s-a putut actualiza setarea istoricului comenzilor",
"analyticsEnabled": "Distribuiți statistici de utilizare anonime",
"analyticsEnabledDesc": "Trimite un număr zilnic anonim de utilizatori, gazde și utilizare a funcțiilor pentru a ajuta la îmbunătățirea Termix. Nu sunt incluse niciodată date personale sau detalii de conexiune.",
"updateAnalyticsFailed": "Setările de analiză nu au putut fi actualizate",
"sessionSharingGloballyEnabled": "Permiteți partajarea sesiunii",
"sessionSharingGloballyEnabledDesc": "Permite partajarea sesiunilor live de terminal, RDP, VNC și Telnet la nivel de instanță. Suprascrie fiecare comutare de partajare per gazdă atunci când este dezactivată.",
"updateSessionSharingFailed": "Setările de partajare a sesiunii nu au putut fi actualizate.",
"sessionTimeout": "Expirare sesiune",
"hours": "ore",
"sessionTimeoutRange": "Min 1 oră · Max 720 ore",
@@ -3119,6 +3270,47 @@
"executionSuccess": "Succes",
"executionFailed": "Eșuat"
},
"keybindings": {
"title": "Comenzi rapide de la tastatură",
"description": "Personalizați comenzile rapide de copiere, lipire și control din terminal sau asociați taste pentru a trimite text sau a rula un fragment de cod.",
"defaultsHeading": "Comenzi rapide încorporate",
"customHeading": "Comenzi rapide personalizate",
"addBinding": "Adăugați o comandă rapidă",
"addBindingTitle": "Adăugați o comandă rapidă",
"editBindingTitle": "Editare comandă rapidă",
"loading": "Încărcare...",
"noCustomBindings": "Încă nu există comenzi rapide personalizate",
"defaultBadge": "Implicit",
"customizedBadge": "Personalizat",
"customize": "Personalizare",
"resetToDefault": "Resetare la valorile implicite",
"resetAllToDefaults": "Resetați toate la valorile implicite",
"close": "Aproape",
"cancel": "Anula",
"saveBinding": "Salvați comanda rapidă",
"saveError": "Nu s-au putut salva comenzile rapide de la tastatură",
"pressKeysToRecord": "Combinație de taste",
"pressKeysPlaceholder": "Faceți clic și apăsați tastele",
"recording": "Apăsați tastele...",
"comboRequiredError": "Apăsați mai întâi o combinație de taste",
"textRequiredError": "Introduceți textul de trimis",
"controlCodeRequiredError": "Introduceți o singură literă pentru codul de control",
"snippetRequiredError": "Selectați un fragment",
"conflictWarning": "Această combinație este deja legată de {{combo}}. Salvarea va face ca ambele să se declanșeze.",
"actionLabel": "Acţiune",
"actionCopy": "Copiați selecția",
"actionPaste": "Pastă",
"actionSendControlCode": "Trimite semnal Ctrl+literă",
"actionSendText": "Trimiteți mesaj text",
"actionRunSnippet": "Execută fragmentul existent",
"controlCodeLabel": "Scrisoare",
"textLabel": "Text de trimis",
"appendEnterLabel": "Apăsați Enter după trimitere",
"snippetLabel": "Fragment",
"selectSnippetPlaceholder": "Selectați un fragment",
"orphanedSnippetWarning": "fragmentul nu a fost găsit",
"clipboardPermissionNote": "În unele browsere, este posibil să solicite permisiunea pentru clipboard la prima utilizare."
},
"userProfile": {
"donateTitle": "Menține Termix în viață",
"donateDescription": "Termix este gratuit, găzduit în regim self-hosting și construit de doar câțiva oameni în timpul lor liber. Dacă ți-a economisit timp sau bani, o donație în criptomonede ajută la menținerea activității.",
@@ -3134,6 +3326,7 @@
"sectionAppearance": "Aspect",
"sectionSecurity": "Securitate",
"sectionApiKeys": "Chei API",
"sectionData": "Date",
"sectionC2sTunnels": "Tuneluri C2S",
"usernameLabel": "Nume de utilizator",
"roleLabel": "Rol",
@@ -3162,6 +3355,9 @@
"settingsTerminal": "Terminal",
"commandAutocomplete": "Completare automată a comenzilor",
"commandAutocompleteDesc": "Afișează completarea automată în timpul tastării",
"keyboardShortcuts": "Comenzi rapide de la tastatură",
"keyboardShortcutsDescription": "Personalizați comenzile rapide pentru copiere, lipire și comenzi în terminal",
"manageShortcuts": "Gestionează",
"terminalLinkBehavior": "Clic pe linkul terminalului",
"terminalLinkBehaviorDesc": "Comportament implicit la clic pe linkuri în terminal",
"historyTracking": "Urmărirea istoricului",
@@ -3228,6 +3424,22 @@
"apiKeyUsageHint": "Includeți cheia dvs. în",
"apiKeyUsageHintHeader": "antet.",
"apiKeyPermissionsHint": "Cheile moștenesc permisiunile utilizatorului care le creează.",
"exportData": "Exportați datele mele",
"exportDataDesc": "Descărcați o copie de rezervă a gazdelor, acreditărilor și setărilor pentru a o transfera pe un alt dispozitiv",
"export": "Export",
"exporting": "Exportator...",
"importData": "Importați datele mele",
"importDataDesc": "Restaurați gazdele, acreditările și setările dintr-un fișier de rezervă .sqlite",
"importDataSelected": "Selectat: {{name}}",
"selectFile": "Selectați fișierul",
"changeFile": "Schimba",
"import": "Import",
"importing": "Importare...",
"exportSuccess": "Datele au fost exportate cu succes",
"exportFailed": "Exportul datelor a eșuat",
"importSelectFile": "Vă rugăm să selectați mai întâi un fișier",
"importCompleted": "Import finalizat: {{total}} articole importate, {{skipped}} omis",
"importFailed": "Importul a eșuat: {{error}}",
"roleUser": "Utilizator",
"authMethodDual": "Autentificare duală",
"authMethodOidc": "OIDC",
@@ -3379,6 +3591,7 @@
"pageUp": "PagUp",
"pageDown": "Pagină următoare",
"delete": "Șterge",
"paste": "Pastă",
"editQuickKeys": "Editați tastele rapide",
"quickKeysTitle": "Taste rapide",
"quickKeysDesc": "Atingeți × pentru a elimina. Acceptă până la 8 caractere.",